4.06.2013 - Version 0.3.4 - PIOBJECT() macro, ethernet improvement, documentation based on Doxygen

This commit is contained in:
peri4
2013-06-04 21:28:15 +04:00
parent 02c629d6a8
commit 9111640ca8
53 changed files with 3019 additions and 910 deletions

View File

@@ -1,23 +1,29 @@
project(pip)
find_package(Qt4)
cmake_minimum_required(VERSION 2.6)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES} . ../peri4_widgets)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} .)
set(VERSION "0.0304")
set(SOVERSION ${VERSION})
set(CMAKE_BUILD_TYPE "Release")
file(GLOB CPPS "pi*.cpp")
if (${WIN32})
add_definitions(-Wall -O2)
else (${WIN32})
add_definitions(-Wall -O2 -g3 --fast-math)
endif (${WIN32})
include(GenerateExportHeader)
execute_process(COMMAND "make_rc_win.bat")
add_definitions("-O2")
#add_definitions(-DEF)
list(APPEND CPPS "pip_resource_win.o")
add_library(pip SHARED ${CPPS})
if (${WIN32})
target_link_libraries(pip pthread ws2_32 Iphlpapi)
generate_export_header(pip)
target_link_libraries(pip ws2_32 Iphlpapi)
else (${WIN32})
if(DEFINED ENV{QNX_HOST})
add_definitions("-O2")
add_library(pip STATIC ${CPPS})
else()
add_definitions("-Wall -O2 -g3")
add_library(pip SHARED ${CPPS})
endif()
target_link_libraries(pip pthread rt)
endif (${WIN32})
add_executable(pip_test "main.cpp")
if (${WIN32})
target_link_libraries(pip_test pthread ws2_32 Iphlpapi pip)
else (${WIN32})
target_link_libraries(pip_test pip ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} pcollection)
endif (${WIN32})
target_link_libraries(pip_test pip)
add_subdirectory(system_test)

399
main.cpp
View File

@@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//#define PIP_DEBUG
#include "pip.h"
@@ -52,7 +52,7 @@ private:
void signalFunc(PISignals::Signal signal) {
if (signal != PISignals::Interrupt) return;
cout << "Ctrl+C pressed, exiting ..." << endl;
cout << endl << "Ctrl+C pressed, exiting ..." << endl;
exit(0);
};
@@ -71,293 +71,252 @@ void timerEvent2(void * data, int delim) {
class ObjectTest: public PIObject {
PIOBJECT(ObjectTest)
public:
ObjectTest(const PIString & name = PIString()): PIObject(name) {h = hi = ht = false;}
EVENT_HANDLER(ObjectTest, void, handler) {h = true; cout << " handler in \"" << name() << "\"" << endl;}
EVENT_HANDLER2(ObjectTest, void, handler_i_s, int, i, PIString, s) {hi = true; cout << " handler_i_s in \"" << name() << "\", i = " << i << ", s = \"" << s << "\"" << endl;}
EVENT_HANDLER2(ObjectTest, void, handler_timeout, void * , data, int, delim) {ht = true; cout << " handler_timeout in \"" << name() << "\", data = " << data << ", delim = " << delim << endl;}
EVENT_HANDLER(void, handler) {h = true; cout << " handler in \"" << name() << "\"" << endl;}
EVENT_HANDLER2(void, handler_i_s, int, i, PIString, s) {hi = true; cout << " handler_i_s in \"" << name() << "\", i = " << i << ", s = \"" << s << "\"" << endl;}
EVENT_HANDLER2(void, handler_timeout, void * , data, int, delim) {ht = true; cout << " handler_timeout in \"" << name() << "\", data = " << data << ", delim = " << delim << endl;}
bool h, hi, ht;
};
class ObjectTest2: public PIObject {
PIOBJECT(ObjectTest2)
public:
ObjectTest2(const PIString & name = PIString()): PIObject(name) {;}
void raise0(const PIString & e) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent(this, e);}
void raise2(const PIString & e, int i, const PIString & s) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent<int, PIString>(this, e, i, s);}
EVENT(ObjectTest2, event0)
EVENT(ObjectTest2, event2)
EVENT(event0)
EVENT(event2)
};
class CA: public PIObject {
PIOBJECT(CA)
public:
CA(const PIString & n): PIObject(n) {;}
EVENT_HANDLER(CA, void, handler_ca) {a = true; cout << " handler CA" << endl;}
EVENT(CA, event_ca)
EVENT_HANDLER(void, handler_ca) {a = true; cout << " handler CA" << endl;}
EVENT(event_ca)
bool a;
};
class CB: public CA {
PIOBJECT(CB)
public:
CB(const PIString & n): CA(n) {;}
EVENT_HANDLER(CB, void, handler_cb) {b = true; cout << " handler CB" << endl;}
EVENT_HANDLER(void, handler_cb) {b = true; cout << " handler CB" << endl;}
bool b;
};
class CC: public CB {
PIOBJECT(CC)
public:
CC(const PIString & n): CB(n) {;}
EVENT_HANDLER(CC, void, handler_cc) {c = true; cout << " handler CC" << endl;}
EVENT_HANDLER(void, handler_cc) {c = true; cout << " handler CC" << endl;}
bool c;
};
class CD: public CC {
PIOBJECT(CD)
public:
CD(const PIString & n): CC(n) {;}
EVENT_HANDLER(CD, void, handler_cd) {d = true; cout << " handler CD" << endl;}
EVENT_HANDLER(void, handler_cd) {d = true; cout << " handler CD" << endl;}
bool d;
};
PIDiagnostics diag;
bool corr = true;
void te(void * , int) {
diag.received(256, corr);
diag.sended(512);
}
struct Packet {
int from;
int to;
float data;
int cs;
class ObjectA: public PIObject {
PIOBJECT(ObjectA)
public:
EVENT_HANDLER1(void, handlerA, const PIString & , str) {piCout << "handler A:" << str;}
EVENT2(eventA2, int, i, float, f);
EVENT1(eventA1, const PIString & , str);
};
class ObjectB: public PIObject {
PIOBJECT(ObjectB)
public:
EVENT_HANDLER2(void, handlerB, int, i, float, f) {piCout << "handler B:" << i << "," << f;}
EVENT1(eventB, PIString, str);
};
#pragma pack(push, 1)
struct 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 {
msgHeader(ushort msg_id_ = 0) {
sign[0] = 'B';
sign[1] = 'R';
sign[2] = 'K';
sign[3] = 'D';
msg_id = msg_id_;
sys_id = 2;
subsys_id = 1;
fragment = security = cnt = 0;
size = sizeof(msgHeader);
}
char sign[4];
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;
}
ushort size;
ushort cnt;
uchar fragment;
ushort msg_id;
uchar sys_id;
uchar subsys_id;
uchar security;
bool verify_sign() {return (sign[0] == 'B' && sign[1] == 'R' && sign[2] == 'K' && sign[3] == 'D');}
};
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;
}
struct msg2105base {
msgHeader header;
uchar command; // 3
union {
ullong msgTime;
struct {
uchar fi_number: 7; // номер частотного участка, 1 - 36
uchar bort : 1; // борт: 0 - левый, 1 - правый
uint time_ns;
uint time_s;
};
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;
};
uint id;
ushort type1kod;
float type1ver;
ushort type2kod;
float type2ver;
ushort type3kod;
float type3ver;
double azimut;
ullong imp_recv_time;
double geo_width_PEC;
double geo_length_PEC;
double geo_width_CP;
double geo_length_CP;
float height;
float kurs_CP;
float kren_CP;
float tangaj_CP;
};
struct InpuData {
InpuData() {header.msg_id = 2113;}
msgHeader header;
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;
};
uchar data[122];
};
#pragma pack(pop)
void te(void*, int);
PITimer tm_(te);
PISerial ser("/dev/ttyS0");
bool pins[9];
void te(void*, int) {
for (int i = 1; i <= 9; ++i)
pins[i - 1] = ser.isPin(i);
}
void ke(char key, void*) {
int p = key - '0';
if (key >= '1' && key <= '9')
ser.setPin(p, !pins[p - 1]);
}
int main(int argc, char * argv[]) {
PIKbdListener kbd;
kbd.enableExitCapture();
PICLI cli(argc, argv);
cli.addArgument("sender");
PIEthernet eth;
int i = 0;
bool _ok;
if (cli.hasArgument("sender")) {
while (!PIKbdListener::exiting) {
_ok = eth.send("234.0.2.1", 10101, &i, sizeof(i));
cout << "send " << i << " - " << (_ok ? "ok" : "fail") << endl;
i++;
msleep(100);
}
} else {
eth.setParameter(PIEthernet::Broadcast);
eth.open(":10101");
eth.joinMulticastGroup("234.0.2.1");
while (!PIKbdListener::exiting) {
eth.read(&i, sizeof(i));
cout << "receive " << i << endl;
}
}
return 0;
class RC: public PIObject {
PIOBJECT(RC)
public:
EVENT_HANDLER2(void, re, ullong, id, int, size) {piCout << "written id =" << id << "size =" << size;}
};
/*tm_.start(10.);
PIConsole con(false, ke);
con.enableExitCapture();
//ser.setParameter(PISerial::HardwareFlowControl);
ser.open();
con.addVariable("1 (CAR)", pins);
con.addVariable("2 (SR) ", pins + 1);
con.addVariable("3 (ST) ", pins + 2);
con.addVariable("4 (DTR)", pins + 3);
con.addVariable("5 (GND)", pins + 4);
con.addVariable("6 (DSR)", pins + 5);
con.addVariable("7 (RTS)", pins + 6);
con.addVariable("8 (CTS)", pins + 7);
con.addVariable("9 (RNG)", pins + 8);
con.start();
con.waitForFinish();
return 0;*/
/*FilterCommand fc;
PIEthernet eth(PIEthernet::TCP_SingleTCP);
eth.open("127.0.0.1:10201");
while (1) {
eth.read(&fc, sizeof(fc));
cout << int(fc.fi_number) << ", " << int(fc.bort) << ", " << int(fc.freq_start) << ", " << int(fc.freq_end) << ", " << int(fc.play_channels) << ", " << int(fc.record_channels) << endl;
}
return 0;*/
/*PIDir dir(argv[1]);
FILE*f = popen("cd ../ && pwd", "w");
char fd[4096];
int ret = fread(fd, 4096, 1, f);
pclose(f);
cout << PIString(fd, ret);
f = popen("cd ../ && pwd", "w");
ret = fread(fd, 4096, 1, f);
pclose(f);
cout << PIString(fd, ret);
return 0;
cout << dir.path() << endl;
dir.up();
cout << dir.path() << endl;
PIVector<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;
int main(int argc, char ** argv) {
InpuData data;
PIEthernet eth(PIEthernet::UDP);
data.first_number = 0;
data.packet_number = 0;
data.packet_last = 0;
data.antenna_number = data.frequency_number = data.data_type = 0;
float t = 0.f;
int pc = 20, cnt = 0;
for (int p = 0; p < pc; ++p) {
data.packet_number = p;
data.packet_last = (p == pc - 1 ? 1 : 0);
data.first_number = p * 97;
PIBitArray ba_;
int ci = 0;
for (int i = 0; i < 97; ++i) {
t += M_PI/4;
ci = sin(t) * 511 + 511;
if (cnt % 500 > 80) ci = 512;
cnt++;
for (int b = 0; b < 10; ++b)
ba_.push_back(((i >> b) & 1) == 1);
ba_.push_back(((ci >> b) & 1) == 1);
}
//cout << ba_.byteSize() << ", " << ba_.bitSize() << endl;
memcpy(data.data, ba_.data(), 122);
cout << ba_ << endl;
eth.send("127.0.0.1:5000", &data, sizeof(data));
}
/*cout << ba_ << endl;
for (int i = 0; i < 122; ++i)
cout << int(data.data[i]) << ", ";
cout << endl;
eth.send("127.0.0.1:5000", &data, sizeof(data));
cout << endl;*/
return 0;
/*PIKbdListener kbd;
kbd.enableExitCapture();
PIEthernet * _eth;
PIByteArray ba_(16);
if (PIString(argv[argc - 1]) == "s") {
_eth = new PIEthernet(PIEthernet::TCP_Server);
piCout << "listen" << _eth->listen("127.0.0.1:1111");
int cc = 0;
while (!PIKbdListener::exiting) {
if (cc != _eth->clientsCount()) {
piCout << "new client";
_eth->clients().back()->startThreadedRead();
cc++;
}
msleep(1);
}
} else {
_eth = new PIEthernet(PIEthernet::TCP_Client);
piCout << "connection" << _eth->connect("127.0.0.1:1111");
_eth->send(PIString("0123456789101112").data(), 16);
while (!PIKbdListener::exiting) {
msleep(1);
}
}
delete _eth;
return 0;
msg2105base msg;
msg.header.size = sizeof(msg);
msg.header.msg_id = 2105;
msg.msgTime = 1;
//PIKbdListener kbd;
//kbd.enableExitCapture();
RC rc_;
PIEthernet eth;
CONNECT2(void, ullong, int, &eth, threadedWriteEvent, &rc_, re);
eth.setParameter(PIEthernet::Broadcast);
eth.open("127.0.0.1:10211");
eth.setSendAddress("234.0.2.1:10211");
eth.joinMulticastGroup("234.0.2.1");
eth.startThreadedWrite();
for (int i = 0; i < 100000; ++i) {
PISystemTime tm = currentSystemTime();
msg.type1kod = (i + 1) % 34;
msg.id = piRoundd(double(i) / 5. + 50);
if (i % 15 >= 10) msg.id += 10000;
msg.time_ns = tm.seconds;
msg.time_s = tm.nanoseconds;
msg.azimut = sin(float(i) / 20.) * 90;
msg.geo_width_PEC = sin(float(i) / 50.) * 90;
msg.geo_length_PEC = cos(float(i) / 50.) * 90;
piCout << "push to queue with id =" << eth.writeThreaded(&msg, sizeof(msg));
piMSleep(50);
if (PIKbdListener::exiting) break;
}
return 0;*/
/*QApplication app(argc, argv);
PIFFT fft;
PIVector<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();
return app.exec();*/
PISignals::setSlot(signalFunc);
//PISignals::grabSignals(PISignals::Interrupt);
bool r_string = true, r_thread = true, r_mutex = true, r_timer = true, r_file = true, r_eval = true, r_event = true;
bool succ = true;
cout << "== PIP test program ==" << endl;

View File

@@ -22,7 +22,7 @@
#include "picontainers.h"
class PIBitArray {
class PIP_EXPORT PIBitArray {
public:
PIBitArray(const int & size = 0) {resize(size);}
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
@@ -99,5 +99,6 @@ private:
};
inline std::ostream & operator <<(std::ostream & s, const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) {s << ba[i]; if (i % 8 == 7) s << ' ';} return s;}
inline PICout operator <<(PICout s, const PIBitArray & ba) {s.space(); s.setControl(0, true); for (uint i = 0; i < ba.bitSize(); ++i) {s << ba[i]; if (i % 8 == 7) s << ' ';} s.restoreControl(); return s;}
#endif // PIBITARRAY_H

View File

@@ -90,12 +90,24 @@ private:
PIVector<node> nodes;
};
class PIByteArray: public PIVector<uchar> {
class PIP_EXPORT PIByteArray: public PIVector<uchar> {
public:
PIByteArray() {;}
PIByteArray(const uint size) {resize(size);}
PIByteArray(const void * data, const uint size) {for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);}
struct RawData {
friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
public:
RawData(void * data, int size) {d = data; s = size;}
RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;}
RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
private:
void * d;
int s;
};
PIByteArray resized(int new_size) {PIByteArray tv(*this); tv.resize(new_size); return tv;}
PIByteArray & convertToBase64();
@@ -146,42 +158,56 @@ private:
};
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba) {for (uint i = 0; i < ba.size(); ++i) s << ba[i]; return s;}
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba) {s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; return s;}
inline PICout operator <<(PICout s, const PIByteArray & ba) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
#define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v));
inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const short & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const int & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const long & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const ushort & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const uint & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const float & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const double & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); memcpy(s.data(os), v.d, v.s); return s;}
template <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;}
template <typename T>
inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;}
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {v = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, short & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, int & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, long & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, llong & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, uint & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, float & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, double & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
#undef PBA_OPERATOR_TO
#define PBA_OPERATOR_FROM memcpy(&v, s.data(), sizeof(v)); s.remove(0, sizeof(v));
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;}
template <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;}
template <typename T>
inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
#undef PBA_OPERATOR_FROM
#endif // PIBYTEARRAY_H

110
pichar.h
View File

@@ -1,3 +1,6 @@
/*! \file pichar.h
* \brief Unicode char
*/
/*
PIP - Platform Independent Primitives
Unicode char
@@ -21,24 +24,41 @@
#define PICHAR_H
#include "pibytearray.h"
class PIChar
/*! \brief Unicode char
* \details This class is wrapper around \c "uint".
* There are many contructors and information functions;
*/
class PIP_EXPORT PIChar
{
friend class PIString;
friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v);
friend PIByteArray & operator >>(PIByteArray & s, PIChar & v);
public:
//! Contructs ascii symbol
PIChar(const char c) {ch = c; ch &= 0xFF;}
//! Contructs 2-bytes symbol
PIChar(const short c) {ch = c; ch &= 0xFFFF;}
PIChar(const int c = 0) {ch = c;}
//! Contructs 4-bytes symbol
PIChar(const int c) {ch = c;}
//! Contructs ascii symbol
PIChar(const uchar c) {ch = c; ch &= 0xFF;}
//! Contructs 2-bytes symbol
PIChar(const ushort c) {ch = c; ch &= 0xFFFF;}
PIChar(const uint c) {ch = c;}
//! Default constructor. Contructs 4-bytes symbol
PIChar(const uint c = 0) {ch = c;}
//! Contructs symbol from no more than 4 bytes of string
PIChar(const char * c) {ch = *reinterpret_cast<const int * >(c);}
//inline operator const int() {return static_cast<const int>(ch);}
//inline operator const char() {return toAscii();}
//! Copy operator
PIChar & operator =(const char v) {ch = v; return *this;}
/*inline PIChar & operator =(const short v) {ch = v; return *this;}
inline PIChar & operator =(const int v) {ch = v; return *this;}
@@ -46,6 +66,7 @@ public:
inline PIChar & operator =(const ushort v) {ch = v; return *this;}
inline PIChar & operator =(const uint v) {ch = v; return *this;}*/
//! Compare operator
bool operator ==(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) == 0;}
/*inline bool operator ==(const PIChar & o) const {if (o.isAscii() ^ isAscii()) return false;
if (isAscii()) return (o.toAscii() == toAscii());
@@ -57,6 +78,7 @@ public:
inline bool operator ==(const ushort o) const {return (PIChar(o) == *this);}
inline bool operator ==(const uint o) const {return (PIChar(o) == *this);}*/
//! Compare operator
bool operator !=(const PIChar & o) const {return !(o == *this);}
/*inline bool operator !=(const char o) const {return (PIChar(o) != *this);}
inline bool operator !=(const short o) const {return (PIChar(o) != *this);}
@@ -65,62 +87,134 @@ public:
inline bool operator !=(const ushort o) const {return (PIChar(o) != *this);}
inline bool operator !=(const uint o) const {return (PIChar(o) != *this);}*/
//! Compare operator
bool operator >(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) < 0;}
//! Compare operator
bool operator <(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) > 0;}
//! Compare operator
bool operator >=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) <= 0;}
//! Compare operator
bool operator <=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) >= 0;}
//! Return \b true if symbol is digit ('0' to '9')
bool isDigit() const {return isdigit(ch) != 0;}
//! Return \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F')
bool isHex() const {return isxdigit(ch) != 0;}
//! Return \b true if symbol is drawable (without space)
bool isGraphical() const {return isgraph(ch) != 0;}
//! Return \b true if symbol is control byte (< 32 or 127)
bool isControl() const {return iscntrl(ch) != 0;}
//! Return \b true if symbol is in lower case
bool isLower() const {return islower(ch) != 0;}
//! Return \b true if symbol is in upper case
bool isUpper() const {return isupper(ch) != 0;}
//! Return \b true if symbol is printable (with space)
bool isPrint() const {return isprint(ch) != 0;}
//! Return \b true if symbol is space or tab
bool isSpace() const {return isspace(ch) != 0;}
//! Return \b true if symbol is alphabetical letter
bool isAlpha() const {return isalpha(ch) != 0;}
//! Return \b true if symbol is ascii (< 128)
bool isAscii() const {return isascii(ch) != 0;}
int toInt() const {return static_cast<const int>(ch);}
const wchar_t * toWCharPtr() const {return &ch;}
int toInt() const {return int(ch);}
const wchar_t * toWCharPtr() const {return reinterpret_cast<const wchar_t * >(&ch);}
//! Return as <tt>"char * "</tt> string
const char * toCharPtr() const {return reinterpret_cast<const char * >(&ch);}
wchar_t toWChar() const {return ch;}
wchar_t toWChar() const {return wchar_t(ch);}
char toAscii() const {return ch % 256;}
int unicode16Code() const {wchar_t wc; if (mbtowc(&wc, toCharPtr(), 4) > 0) return wc; return 0;}
//#ifdef WINDOWS
// inline PIChar toUpper() const __attribute__ ((optimize(0))) {return PIChar(toupper(ch));}
// inline PIChar toLower() const __attribute__ ((optimize(0))) {return PIChar(tolower(ch));}
//#else
//! Return symbol in upper case
PIChar toUpper() const {return PIChar(toupper(ch));}
//! Return symbol in lower case
PIChar toLower() const {return PIChar(tolower(ch));}
//#endif
private:
wchar_t ch;
uint ch;
};
//! Output operator to \c std::ostream
inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;}
//! Output operator to \a PICout
inline PICout operator <<(PICout s, const PIChar & v) {s.space(); s.setControl(0, true); s << v.toCharPtr(); s.restoreControl(); return s;}
//! Write operator to \c PIByteArray
inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << uint(v.ch); return s;}
//! Read operator from \c PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {uint i; s >> i; v.ch = wchar_t(i); return s;}
//! Compare operator
inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);}
//! Compare operator
inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);}
//! Compare operator
inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);}
//! Compare operator
inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);}
//! Compare operator
inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);}
//! Compare operator
inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);}
//! Compare operator
inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);}
//! Compare operator
inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);}
//! Compare operator
inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);}
//! Compare operator
inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= c);}
//! Compare operator
inline bool operator ==(const int v, const PIChar & c) {return (PIChar(v) == c);}
//! Compare operator
inline bool operator >(const int v, const PIChar & c) {return (PIChar(v) > c);}
//! Compare operator
inline bool operator <(const int v, const PIChar & c) {return (PIChar(v) < c);}
//! Compare operator
inline bool operator >=(const int v, const PIChar & c) {return (PIChar(v) >= c);}
//! Compare operator
inline bool operator <=(const int v, const PIChar & c) {return (PIChar(v) <= c);}
#endif // PICHAR_H

View File

@@ -69,7 +69,7 @@ void PICLI::parse() {
_args_opt << cra;
continue;
}
piCout << "[PICli] Arguments overflow, \"" << cra << "\" ignored" << endl;
piCout << "[PICli] Arguments overflow, \"" << cra << "\" ignored";
}
if (last == 0 ? false : last->has_value) {
last->value = cra;

View File

@@ -22,7 +22,7 @@
#include "pistring.h"
class PICLI
class PIP_EXPORT PICLI
{
public:
PICLI(int argc, char * argv[]);

View File

@@ -22,7 +22,7 @@
#include "piprocess.h"
class PICodec: private PIProcess
class PIP_EXPORT PICodec: private PIProcess
{
public:
PICodec(): PIProcess() {setGrabOutput(true); tf = PIFile::openTemporary(PIIODevice::ReadWrite); tf.open();}

View File

@@ -277,7 +277,7 @@ void PIConfig::addEntry(const PIString & name, const PIString & value, const PIS
void PIConfig::setValue(const PIString & name, const PIString & value, const PIString & type, bool write) {
Entry & e(getValue(name));
if (&e == &empty) {
addEntry(name, value, type);
addEntry(name, value, type, write);
return;
}
e._value = value;
@@ -376,10 +376,14 @@ void PIConfig::removeEntry(Branch & b, PIConfig::Entry * e) {
void PIConfig::writeAll() {
//cout << this << " write < " << size() << endl;
clear();
//*this << "1234567894132456798\n"; return;
//writeEntry(&root);
buildFullNames(&root);
Branch b = allLeaves();
//for (int i = 0; i < b.size_s(); ++i)
// cout << b[i]->_name << " = " << b[i]->_value << endl;
int j = 0;
for (int i = 0; i < other.size_s(); ++i) {
//cout << j << endl;
@@ -387,25 +391,27 @@ void PIConfig::writeAll() {
if (b[j]->_line == i) {
b[j]->buildLine();
*this << b[j]->_all << '\n';
//cout << this << " " << b[j]->_all << endl;
++j;
} else {
*this << other[i];
if (i < other.size_s() - 1) *this << '\n';
//cout << this << " " << other[i] << endl;
}
} else {
*this << other[i];
if (i < other.size_s() - 1) *this << '\n';
//cout << this << " " << other[i] << endl;
}
//cout << other[i] << endl;
}
flush();
readAll();
//cout << this << " write > " << size() << endl;
}
void PIConfig::readAll() {
root.clear();
flush();
parse();
}

View File

@@ -49,17 +49,17 @@
Entry & getValue(const PIString & vname, const float def, bool * exist = 0) const {return getValue(vname, ftos(def), exist);} \
Entry & getValue(const PIString & vname, const double def, bool * exist = 0) const {return getValue(vname, dtos(def), exist);}
class PIConfig: public PIFile
class PIP_EXPORT PIConfig: public PIFile
{
friend class Entry;
friend class Branch;
public:
PIConfig(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
~PIConfig() {piForeach (Entry * i, root._children) deleteEntry(i); close();}
~PIConfig() {/*piForeach (Entry * i, root._children) deleteEntry(i); close();*/}
class Entry;
class Branch: public PIVector<Entry * > {
class PIP_EXPORT Branch: public PIVector<Entry * > {
friend class PIConfig;
friend class Entry;
friend std::ostream & operator <<(std::ostream & s, const Branch & v);
@@ -90,7 +90,7 @@ public:
};
class Entry {
class PIP_EXPORT Entry {
friend class PIConfig;
friend class Branch;
public:

View File

@@ -20,12 +20,15 @@
#include "piconsole.h"
extern PIMutex __PICout_mutex__;
PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() {
setPriority(piLow);
needLockRun(true);
ret_func = slot;
num_format = 0;
cur_tab = width = height = pwidth = pheight = my = 0;
cur_tab = width = height = pwidth = pheight = max_y = 0;
def_align = Nothing;
#ifdef WINDOWS
ulcoord.X = ulcoord.Y = 0;
@@ -93,9 +96,11 @@ bool PIConsole::setTab(uint index) {
return true;
}
lock();
__PICout_mutex__.lock();
cur_tab = index;
clearScreen();
fillLabels();
__PICout_mutex__.unlock();
unlock();
return true;
}
@@ -135,6 +140,23 @@ bool PIConsole::setTabBindKey(const PIString & name, char bind_key) {
void PIConsole::key_event(char key, void * t) {
PIConsole * p = (PIConsole * )t;
int ct = p->cur_tab;
if (key == char(PIKbdListener::LeftArrow)) {
do {
ct--;
if (ct < 0) return;
} while (p->tabs[ct].key == 0);
p->setTab(ct);
return;
}
if (key == char(PIKbdListener::RightArrow)) {
do {
ct++;
if (ct >= p->tabs.size_s()) return;
} while (p->tabs[ct].key == 0);
p->setTab(ct);
return;
}
for (uint i = 0; i < p->tabsCount(); ++i) {
if (p->tabs[i].key == key) {
p->setTab(i);
@@ -148,7 +170,7 @@ void PIConsole::key_event(char key, void * t) {
void PIConsole::stop(bool clear) {
PIThread::stop(true);
if (clear) clearScreen();
moveTo(0, my + 4);
moveTo(0, max_y + 4);
showCursor();
couts(fstr(Normal));
#ifdef WINDOWS
@@ -273,9 +295,12 @@ void PIConsole::begin() {
#ifdef WINDOWS
SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
#endif
max_y = 0;
__PICout_mutex__.lock();
clearScreen();
hideCursor();
fillLabels();
__PICout_mutex__.unlock();
}
@@ -292,6 +317,7 @@ void PIConsole::run() {
width = ws.ws_col;
height = ws.ws_row;
#endif
__PICout_mutex__.lock();
if (pwidth != width || pheight != height) {
clearScreen();
fillLabels();
@@ -304,7 +330,7 @@ void PIConsole::run() {
PIVector<Variable> & cvars(tabs[cur_tab].columns[i].variables);
cx = col_wid * i;
toUpperLeft();
if (my < cvars.size()) my = cvars.size();
if (max_y < cvars.size()) max_y = cvars.size();
j = 0;
piForeachC (Variable & tv, cvars) {
if (j > height - 3) continue;
@@ -343,13 +369,19 @@ void PIConsole::run() {
newLine();
}
}
#ifdef WINDOWS
moveTo(0, max_y + 1);
#else
moveTo(0, max_y + 2);
#endif
fflush(0);
__PICout_mutex__.unlock();
}
void PIConsole::fillLabels() {
if (!isRunning()) return;
uint cx, cy, my = 0, mx = 0, dx;
uint cx, cy, mx = 0, dx;
#ifdef WINDOWS
GetConsoleScreenBufferInfo(hOut, &sbi);
width = sbi.srWindow.Right - sbi.srWindow.Left;
@@ -360,6 +392,7 @@ void PIConsole::fillLabels() {
width = ws.ws_col;
height = ws.ws_row;
#endif
max_y = 0;
col_cnt = columns().size();
col_wid = (col_cnt > 0) ? width / col_cnt : width;
for (uint i = 0; i < col_cnt; ++i) {
@@ -378,7 +411,7 @@ void PIConsole::fillLabels() {
toUpperLeft();
for (uint j = 0; j < cvars.size(); ++j) {
if (int(j) > height - 3) continue;
if (my < j) my = j;
if (max_y < j) max_y = j;
moveRight(cx);
Variable & tv(cvars[j]);
cvars[j].nx = cx;
@@ -426,9 +459,9 @@ void PIConsole::fillLabels() {
}
}
#ifdef WINDOWS
moveTo(0, my + 1);
moveTo(0, max_y + 1);
#else
moveTo(0, my + 2);
moveTo(0, max_y + 2);
#endif
if (!tabs[cur_tab].status.isEmpty()) {
printValue(tabs[cur_tab].status);
@@ -446,6 +479,9 @@ void PIConsole::status() {
ctab = &tabs[i];
if (ctab->key == 0) continue;
printValue(ctab->key, PIConsole::White | PIConsole::Bold);
if (i == cur_tab)
printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black);
else
printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse);
printValue(" ");
}
@@ -522,10 +558,10 @@ void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int c
addString("protocol " + name, col, format | PIConsole::Bold);
addVariable("Rec - " + ptr->receiverDeviceName(), ptr->receiverDeviceState_ptr(), col, format);
addVariable("Send - " + ptr->senderDeviceName(), ptr->senderDeviceState_ptr(), col, format);
addVariable("Sended count", ptr->sendCount_ptr(), col, format);
addVariable("Received count", ptr->receiveCount_ptr(), col, format);
addVariable("Invalid count", ptr->wrongCount_ptr(), col, format);
addVariable("Missed count", ptr->missedCount_ptr(), col, format);
addVariable("Sended count", ptr->sendCount_ptr(), col, format);
addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format);
addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format);
addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format);
@@ -535,6 +571,17 @@ void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int c
addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format);
addVariable("Quality", ptr->quality_ptr(), col, format);
}
void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, PIFlags<PIConsole::Format> format) {
addString(name + " diagnostics", col, format | PIConsole::Bold);
addVariable("Received count", ptr->receiveCount_ptr(), col, format);
addVariable("Invalid count", ptr->wrongCount_ptr(), col, format);
addVariable("Sended count", ptr->sendCount_ptr(), col, format);
addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format);
addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format);
addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format);
addVariable("Send speed", ptr->sendSpeed_ptr(), col, format);
addVariable("Quality", ptr->quality_ptr(), col, format);
}
void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, PIFlags<PIConsole::Format> format) {
addString("monitor " + name, col, format | PIConsole::Bold);
addVariable("state", &(ptr->statistic().state), col, format);

View File

@@ -22,6 +22,7 @@
#include "pikbdlistener.h"
#include "piprotocol.h"
#include "pidiagnostics.h"
#include "pisystemmonitor.h"
#ifndef WINDOWS
# include <sys/ioctl.h>
@@ -32,8 +33,9 @@
/// void clearVariables(bool clearScreen = true)
/// void start(bool wait = false)
/// void stop(bool clear = false)
class PIConsole: public PIThread
class PIP_EXPORT PIConsole: public PIThread
{
PIOBJECT(PIConsole)
public:
PIConsole(bool startNow = true, KBFunc slot = 0);
~PIConsole();
@@ -84,6 +86,7 @@ public:
void addVariable(const PIString & name, const float * ptr, int column = 1, PIFlags<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, const PIProtocol * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, const PIDiagnostics * 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, const void * ptr, int fromBit, int bitCount, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addEmptyLine(int column = 1, uint count = 1);
@@ -117,14 +120,14 @@ public:
void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;}
void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();}
EVENT_HANDLER0(PIConsole, void, clearVariables) {clearVariables(true);}
EVENT_HANDLER1(PIConsole, void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();}
EVENT_HANDLER0(void, clearVariables) {clearVariables(true);}
EVENT_HANDLER1(void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();}
EVENT_HANDLER0(PIConsole, void, waitForFinish) {WAIT_FOR_EXIT}
EVENT_HANDLER0(PIConsole, void, start) {start(false);}
EVENT_HANDLER1(PIConsole, void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER0(PIConsole, void, stop) {stop(false);}
EVENT_HANDLER1(PIConsole, void, stop, bool, clear);
EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT}
EVENT_HANDLER0(void, start) {start(false);}
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, clear);
PIString fstr(PIFlags<PIConsole::Format> f);
void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);}
@@ -273,7 +276,7 @@ private:
Alignment def_align;
KBFunc ret_func;
int width, height, pwidth, pheight, ret, col_wid, num_format;
uint my;
uint max_y;
uint cur_tab, col_cnt;
};

View File

@@ -1,6 +1,12 @@
/*! \file picontainers.h
* \brief Generic containers based on STL
*
* This file declare all containers and useful macroses
* to use them
*/
/*
PIP - Platform Independent Primitives
Generic containers, based on STL
Generic containers based on STL
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
@@ -22,6 +28,37 @@
#include "piincludes.h"
#ifdef DOXYGEN
/*! \def piForeach(i,c)
* \brief Macro for iterate any container
* \details Use this macros instead of standard "for"
* to get read/write access to each element of container.
* Pass direction is direct \n
* Example: \snippet picontainers.cpp foreach
*/
/*! \def piForeachC(i,c)
* \brief Macro for iterate any container only for read
* \details Use this macros instead of standard "for"
* to get read access to each element of container.
* Pass direction is direct \n
* Example: \snippet picontainers.cpp foreachC
*/
/*! \def piForeachR(i,c)
* \brief Macro for iterate any container with reverse direction
* \details Use this macros instead of standard "for"
* to get read/write access to each element of container.
* Pass direction is reverse \n
* Example: \snippet picontainers.cpp foreachR
*/
/*! \def piForeachCR(i,c)
* \brief Macro for iterate any container only for read with reverse direction
* \details Use this macros instead of standard "for"
* to get read access to each element of container.
* Pass direction is reverse \n
* Example: \snippet picontainers.cpp foreachCR
*/
#endif
#ifdef CC_GCC
template<typename Type>
@@ -126,42 +163,6 @@ template <typename T> inline _PIForeachC<T> * _PIForeachCastC(_PIForeachBase & c
#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
template<typename Enum>
class PIFlags {
public:
PIFlags(): flags(0) {;}
PIFlags(Enum e): flags(e) {;}
PIFlags(const PIFlags & f): flags(f.flags) {;}
PIFlags(const int i): flags(i) {;}
PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
void operator =(const PIFlags & f) {flags = f.flags;}
void operator =(const Enum & e) {flags = e;}
void operator =(const int & i) {flags = i;}
void operator |=(const PIFlags & f) {flags |= f.flags;}
void operator |=(const Enum & e) {flags |= e;}
void operator |=(const int i) {flags |= i;}
void operator &=(const PIFlags & f) {flags &= f.flags;}
void operator &=(const Enum & e) {flags &= e;}
void operator &=(const int i) {flags &= i;}
void operator ^=(const PIFlags & f) {flags ^= f.flags;}
void operator ^=(const Enum & e) {flags ^= e;}
void operator ^=(const int i) {flags ^= i;}
PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
bool operator [](Enum e) const {return (flags & e) == e;}
operator int() const {return flags;}
private:
int flags;
};
/*
template <typename T>
class PIVector {
@@ -269,7 +270,7 @@ public:
bool operator ==(const PIVector<T> & t) const {if (size_ != t.size_) return false; for (uint i = 0; i < size_; ++i) if (t[i] != data_[i]) return false; return true;}
bool operator !=(const PIVector<T> & t) const {if (size_ != t.size_) return true; for (uint i = 0; i < size_; ++i) if (t[i] != data_[i]) return true; return false;}
bool contain(const T & v) const {for (uint i = 0; i < size_; ++i) if (v == data_[i]) return true; return false;}
bool contains(const T & v) const {for (uint i = 0; i < size_; ++i) if (v == data_[i]) return true; return false;}
T * data(int index = 0) {return &(data_[index]);}
const T * data(int index = 0) const {return &(data_[index]);}
@@ -370,35 +371,193 @@ private:
uint size_, rsize_, os;
};
*/
/*! \brief Dynamic array for any type
* \details This class used to store dynamic array of any
* type of data. In memory data stored linear. You can insert
* item in any place of remove some items from any place.
* For quick add elements there is stream operator <<.
* This class based on std::vector, expanding his
* functionality.
*/
template<typename Type, typename Allocator = std::allocator<Type> >
class PIVector: public vector<Type, Allocator> {
class PIP_EXPORT PIVector: public vector<Type, Allocator> {
typedef PIVector<Type, Allocator> _CVector;
typedef vector<Type, Allocator> _stlc;
public:
//! Contructs an empty vector
PIVector() {piMonitor.containers++;}
//! Contructs vector with single element "value"
PIVector(const Type & value) {piMonitor.containers++; _stlc::push_back(value);}
//! Contructs vector with two elements "v0" and "v1"
PIVector(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);}
//! Contructs vector with three elements "v0", "v1" and "v2"
PIVector(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);}
//! Contructs vector with four elements "v0", "v1", "v2" and "v3"
PIVector(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);}
/*! \brief Contructs vector with size "size" filled elements "value"
* \details Example: \snippet picontainers.cpp PIVector::PIVector */
PIVector(uint size, const Type & value = Type()) {piMonitor.containers++; _stlc::resize(size, value);}
~PIVector() {piMonitor.containers--;}
/*! \brief Read-only access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::at_c
* \sa \a operator[] */
const Type & at(uint index) const {return (*this)[index];}
/*! \brief Full access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::at
* \sa \a operator[] */
Type & at(uint index) {return (*this)[index];}
/*! \brief Read-only pointer to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::data_c */
const Type * data(uint index = 0) const {return &(*this)[index];}
/*! \brief Pointer to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::data */
Type * data(uint index = 0) {return &(*this)[index];}
#ifdef DOXYGEN
//! Elements count
uint size() const;
#endif
//! Elements count
int size_s() const {return static_cast<int>(_stlc::size());}
//! Return \c "true" if vector is empty, i.e. size = 0
bool isEmpty() const {return _stlc::empty();}
//! Return \c "true" if vector has at least one element equal "t"
bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
//! Return how many times element "t" appears in vector
int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
typedef int (*CompareFunc)(const Type * , const Type * );
//! Standard compare function for type "Type". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1.
static int compare_func(const Type * t0, const Type * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
#ifdef DOXYGEN
/*! \brief Resize vector to size "size"
* \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n
* Example: \snippet picontainers.cpp PIVector::resize
* \sa \a size(), \a clear() */
void resize(uint size, const Type & new_type = Type());
//! Increase vector size with "size" elements
PIVector<Type, Allocator> & enlarge(uint size);
//! Clear vector. Equivalent to call <tt>"resize(0)"</tt>
void clear();
/*! \brief Sort vector using quick sort algorithm and standard compare function
* \details Example: \snippet picontainers.cpp PIVector::sort_0
* With custom compare function: \snippet picontainers.cpp PIVector::sort_1 */
PIVector<Type, Allocator> & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(Type), (int(*)(const void * , const void * ))compare); return *this;}
/*! \brief Fill vector with elements "t" leave size is unchanged and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::fill */
PIVector<Type, Allocator> & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
//! Last element of vector
Type & back();
//! Last element of vector
const Type & back() const;
//! First element of vector
Type & front();
//! First element of vector
const Type & front() const;
//! Add new element "t" at the end of vector and return reference to vector
PIVector<Type, Allocator> & push_back(const Type & t);
//! Add new element "t" at the beginning of vector and return reference to vector
PIVector<Type, Allocator> & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); return *this;}
//! Remove one element from the end of vector and return reference to vector
PIVector<Type, Allocator> & pop_back();
//! Remove one element from the beginning of vector and return reference to vector
PIVector<Type, Allocator> & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
//! Remove one element from the end of vector and return it
Type take_back() {Type t(_stlc::back()); _stlc::pop_back(); return t;}
//! Remove one element from the beginning of vector and return it
Type take_front() {Type t(_stlc::front()); pop_front(); return t;}
/*! \brief Remove one element by index "index" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::remove_0
* \sa \a removeOne(), \a removeAll() */
PIVector<Type, Allocator> & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
/*! \brief Remove "count" elements by first index "index" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::remove_1
* \sa \a removeOne(), \a removeAll() */
PIVector<Type, Allocator> & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
/*! \brief Remove no more than one element equal "v" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::removeOne
* \sa \a remove(), \a removeAll() */
PIVector<Type, Allocator> & removeOne(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
/*! \brief Remove all elements equal "v" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::removeAll
* \sa \a remove(), \a removeOne() */ */
PIVector<Type, Allocator> & removeAll(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
/*! \brief Insert element "t" after index "pos" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::insert_0 */
PIVector<Type, Allocator> & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
/*! \brief Insert other vector "t" after index "pos" and return reference to vector
* \details Example: \snippet picontainers.cpp PIVector::insert_1 */
PIVector<Type, Allocator> & insert(uint pos, const PIVector<Type, Allocator> & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
/*! \brief Full access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::()
* \sa \a at() */
Type & operator [](uint index);
/*! \brief Read-only access to element by index "index"
* \details Example: \snippet picontainers.cpp PIVector::()_c
* \sa \a at() */
const Type & operator [](uint index) const;
//! Add new element "t" at the end of vector and return reference to vector
PIVector<Type, Allocator> & operator <<(const Type & t) {_stlc::push_back(t); return *this;}
//! Add vector "t" at the end of vector and return reference to vector
PIVector<Type, Allocator> & operator <<(const PIVector<Type, Allocator> & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
//! Compare with vector "t"
bool operator ==(const PIVector<Type, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
//! Compare with vector "t"
bool operator !=(const PIVector<Type, Allocator> & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
bool contains(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
#else
_CVector & enlarge(uint size_) {int ns = size_s() + size_; if (ns <= 0) _stlc::clear(); else _stlc::resize(ns); return *this;}
_CVector & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(Type), (int(*)(const void * , const void * ))compare); return *this;}
_CVector & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
_CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
_CVector & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); return *this;}
Type take_front() {Type t(_stlc::front()); pop_front(); return t;}
Type take_back() {Type t(_stlc::back()); _stlc::pop_back(); return t;}
_CVector & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;}
_CVector & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;}
//_CVector & remove(const Type & t) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) {_stlc::erase(i); --i;} return *this;}
_CVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
_CVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
_CVector & removeOne(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
_CVector & removeAll(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
_CVector & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
@@ -407,14 +566,24 @@ public:
_CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
bool operator !=(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;}
bool contain(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
bool contains(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
#endif
};
/*! \brief Output operator for std::ostream
* \relates PIVector
* \details Example: \snippet picontainers.cpp PIVector::ostream<< */
template<typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIVector<Type> & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
/*! \brief Output operator for PICout
* \relates PIVector
* \details Example: \snippet picontainers.cpp PIVector::PICout<< */
template<typename Type>
inline PICout operator <<(PICout s, const PIVector<Type> & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
template<typename Type, typename Allocator = std::allocator<Type> >
class PIList: public list<Type, Allocator> {
class PIP_EXPORT PIList: public list<Type, Allocator> {
typedef PIList<Type, Allocator> _CList;
typedef list<Type, Allocator> _stlc;
public:
@@ -431,16 +600,18 @@ public:
Type * data(uint index = 0) {return &(*this)[index];}
int size_s() const {return static_cast<int>(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
_CList & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
_CList & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;}
_CList & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;}
_CList & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
_CList & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
_CList & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
_CList & operator <<(const Type & t) {_stlc::push_back(t); return *this;}
PIVector<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
template<typename Type, typename Compare = std::less<Type>, typename Allocator = std::allocator<Type> >
class PISet: public set<Type, Compare, Allocator> {
class PIP_EXPORT PISet: public set<Type, Compare, Allocator> {
typedef PISet<Type, Compare, Allocator> _CSet;
typedef set<Type, Compare, Allocator> _stlc;
public:
@@ -452,15 +623,15 @@ public:
~PISet() {piMonitor.containers--;}
int size_s() const {return static_cast<int>(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
_CSet & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;}
_CSet & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;}
_CSet & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
_CSet & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
_CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;}
bool operator [](const Type & t) {return _stlc::find(t);}
PIVector<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
template<typename Type>
class PIStack: public PIVector<Type> {
class PIP_EXPORT PIStack: public PIVector<Type> {
typedef PIStack<Type> _CStack;
public:
PIStack() {;}
@@ -476,7 +647,7 @@ public:
};
template<typename Type, typename Allocator = std::allocator<Type> >
class PIDeque: public deque<Type, Allocator> {
class PIP_EXPORT PIDeque: public deque<Type, Allocator> {
typedef PIDeque<Type, Allocator> _CDeque;
typedef deque<Type, Allocator> _stlc;
public:
@@ -488,12 +659,14 @@ public:
~PIDeque() {piMonitor.containers--;}
int size_s() const {return static_cast<int>(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
_CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;}
PIVector<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
template<typename Type>
class PIQueue: public PIDeque<Type> {
class PIP_EXPORT PIQueue: public PIDeque<Type> {
typedef PIQueue<Type> _CQueue;
public:
PIQueue() {;}
@@ -510,7 +683,7 @@ public:
template<typename Type0, typename Type1>
class PIPair {
class PIP_EXPORT PIPair {
public:
PIPair() {first = Type0(); second = Type1();}
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}
@@ -519,21 +692,62 @@ public:
};
template<typename Type0, typename Type1>
inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;}
template<typename Type0, typename Type1>
inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;}
template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;}
template<typename Key, typename Type>
class PIMap: public map<Key, Type> {
class PIP_EXPORT PIMap: public map<Key, Type> {
typedef PIMap<Key, Type> _CMap;
typedef map<Key, Type> _stlc;
typedef std::pair<Key, Type> _stlpair;
public:
PIMap() {;}
PIMap(const Key & key_, const Type & value_) {insert(key_, value_);}
_CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(std::pair<Key, Type>(key_, value_)); return *this;}
_CMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(std::pair<Key, Type>(entry_.first, entry_.second)); return *this;}
bool isEmpty() const {return _stlc::empty();}
bool contains(const Key & key_) const {return _stlc::count(key_) > 0;}
_CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;}
_CMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;}
Key key(Type value_) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();}
Type & value(Key key_) {return (*this)[key_];}
Type value(Key key_) const {return (*this)[key_];}
Type & value(const Key & key_) {typename _stlc::iterator it = _stlc::find(key_); if (it == _stlc::end()) it->second = Type(); return it->second;}
Type value(const Key & key_) const {return _stlc::find(key_)->second;}
};
template<typename Key, typename Type>
class PIP_EXPORT PIMultiMap: public multimap<Key, Type> {
typedef PIMultiMap<Key, Type> _CMultiMap;
typedef multimap<Key, Type> _stlc;
typedef std::pair<Key, Type> _stlpair;
public:
PIMultiMap() {;}
PIMultiMap(const Key & key_, const Type & value_) {insert(key_, value_);}
_CMultiMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;}
_CMultiMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;}
bool isEmpty() const {return _stlc::empty();}
bool contains(const Key & key_) const {return _stlc::count(key_) > 0;}
Key key(Type value_) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();}
PIVector<Key> keys(Type value_) const {
PIVector<Key> ret;
for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++)
if (i->second == value_)
ret << i->first;
return ret;
}
Type & value(const Key & key_) {return _stlc::find(key_)->second;}
Type value(const Key & key_) const {return _stlc::find(key_)->second;}
PIVector<Type> values(const Key & key_) const {
std::pair<typename _stlc::const_iterator, typename _stlc::const_iterator> range = _stlc::equal_range(key_);
PIVector<Type> ret;
for (typename _stlc::const_iterator i = range.first; i != range.second; ++i)
ret << i->second;
return ret;
}
Type & operator [](const Key & key_) {if (!contains(key_)) return _stlc::insert(_stlpair(key_, Type()))->second; return _stlc::find(key_)->second;}
Type operator [](const Key & key_) const {return _stlc::find(key_)->second;}
};
#endif // PICONTAINERS_H

View File

@@ -23,7 +23,7 @@
#include "pistring.h"
template <int L>
class uint_cl {
class PIP_EXPORT uint_cl {
public:
uint_cl() {for (int i = 0; i < L / 8; ++i) data_[i] = 0;}
uint_cl(const uint_cl<L> & v) {for (int i = 0; i < L / 8; ++i) data_[i] = v.data_[i];}
@@ -160,7 +160,7 @@ inline std::ostream & operator <<(std::ostream & s, const uint_cl<L> & v) {std::
template <uint L>
class PICRC {
class PIP_EXPORT 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();}

View File

@@ -26,7 +26,7 @@
#include <sys/dir.h>
#include <sys/stat.h>
class PIDir
class PIP_EXPORT PIDir
{
public:
PIDir();

View File

@@ -1,6 +1,6 @@
/*
PIP - Platform Independent Primitives
Ethernet, UDP
Ethernet, UDP/TCP Broadcast/Multicast
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
@@ -47,7 +47,7 @@ PIEthernet::PIEthernet(PIEthernet::Type type, void * data, ReadRetFunc slot): PI
sock = sock_s = -1;
ret_func_ = slot;
connected_ = false;
params = PIEthernet::ReuseAddress;
params = (type == UDP ? PIEthernet::ReuseAddress : 0);
server_thread_.setData(this);
setThreadedReadBufferSize(65536);
if (type_ != UDP) init();
@@ -58,6 +58,7 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
piMonitor.ethernets++;
setPriority(piHigh);
type_ = TCP_Client;
path_ = ip_port;
parseAddress(ip_port, &ip_s, &port_s);
sock = sock_;
sock_s = -1;
@@ -80,22 +81,28 @@ PIEthernet::~PIEthernet() {
bool PIEthernet::init() {
//cout << "init " << type_ << endl;
closeSocket(sock);
int st = 0;
int st = 0, pr = 0;;
#ifdef WINDOWS
int flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
int flags = 0;
#else
int so = 1;
#endif
if (type_ == UDP) st = SOCK_DGRAM;
else st = SOCK_STREAM;
if (type_ == UDP) {
st = SOCK_DGRAM;
pr = IPPROTO_UDP;
} else {
st = SOCK_STREAM;
pr = IPPROTO_TCP;
}
#ifdef WINDOWS
if (type_ == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
if (params[ReuseAddress]) flags |= WSA_FLAG_OVERLAPPED;
sock = WSASocket(AF_INET, st, type_ == UDP ? IPPROTO_UDP : IPPROTO_TCP, NULL, 0, flags);
sock = WSASocket(AF_INET, st, pr, NULL, 0, flags);
#else
sock = socket(AF_INET, st, type_ == UDP ? IPPROTO_UDP : IPPROTO_TCP);
sock = socket(AF_INET, st, pr);
#endif
if (sock == -1) {
piCout << "[PIEthernet] Cant`t create socket, " << EthErrorString() << endl;
piCout << "[PIEthernet] Cant`t create socket, " << ethErrorString();
return false;
}
#ifndef WINDOWS
@@ -116,9 +123,11 @@ void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
bool PIEthernet::openDevice() {
if (connected_) return true;
if (sock == -1) init();
init();
if (sock == -1 || path_.isEmpty()) return false;
parseAddress(path_, &ip_, &port_);
if (type_ != UDP)
return true;
//cout << " bind to " << sock << ": " << (params[PIEthernet::Broadcast] ? "0.0.0.0" : path_) << ": " << port_ << " ..." <<endl;
memset(&addr_, 0, sizeof(addr_));
addr_.sin_family = AF_INET;
@@ -134,9 +143,12 @@ bool PIEthernet::openDevice() {
tries++;
}
if (tries == 10) {
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << EthErrorString() << endl;
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
return false;
}
opened_ = true;
while (!mcast_queue.isEmpty())
joinMulticastGroup(mcast_queue.dequeue());
//cout << "!" << endl;
return true;
}
@@ -150,6 +162,7 @@ bool PIEthernet::closeDevice() {
delete i;
clients_.clear();
if (server_thread_.isRunning()) server_thread_.terminate();
if (connected_) disconnected(false);
connected_ = false;
return true;
}
@@ -159,9 +172,15 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
if (sock == -1) init();
if (sock == -1) return false;
if (type_ != UDP) {
piCout << "[PIEthernet] Only UDP sockets can join multicast groups" << endl;
piCout << "[PIEthernet] Only UDP sockets can join multicast groups";
return false;
}
if (!opened_) {
if (mcast_queue.has(group))
return false;
mcast_queue.enqueue(group);
return true;
}
#ifdef WINDOWS
parseAddress(path_, &ip_, &port_);
memset(&addr_, 0, sizeof(addr_));
@@ -170,23 +189,23 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
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;
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << ethErrorString();
return false;
}
leafs.insert(group, ret);
#else
# ifndef QNX
if (!params[Broadcast])
piCout << "[PIEthernet] Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!" << endl;
piCout << "[PIEthernet] Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!";
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());
/*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;
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << ethErrorString();
return false;
}
# endif
@@ -199,7 +218,7 @@ 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;
piCout << "[PIEthernet] Only UDP sockets can leave multicast groups";
return false;
}
#ifdef WINDOWS
@@ -218,7 +237,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
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;
piCout << "[PIEthernet] Cant`t leave multicast group " << group << ", " << ethErrorString();
return false;
}
#endif
@@ -227,20 +246,22 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
}
bool PIEthernet::connect(const PIString & ip, int port) {
bool PIEthernet::connect() {
if (sock == -1) return false;
memset(&addr_, 0, sizeof(addr_));
addr_.sin_port = htons(port);
addr_.sin_addr.s_addr = inet_addr(ip.data());
parseAddress(path_, &ip_, &port_);
addr_.sin_port = htons(port_);
addr_.sin_addr.s_addr = inet_addr(ip_.data());
addr_.sin_family = AF_INET;
#ifdef QNX
addr_.sin_len = sizeof(addr_);
#endif
//piCout << "[PIEthernet] connect to " << ip << ":" << port << endl;
//piCout << "[PIEthernet] connect to " << ip << ":" << port_;
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
if (!connected_)
piCout << "[PIEthernet] Cant`t connect to " << ip << ":" << port << ", " << EthErrorString() << endl;
piCout << "[PIEthernet] Cant`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
opened_ = connected_;
if (connected_) connected();
return connected_;
}
@@ -262,14 +283,14 @@ bool PIEthernet::listen() {
tries++;
}
if (tries == 10) {
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << EthErrorString() << endl;
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
return false;
}
if (::listen(sock, 64) == -1) {
piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << EthErrorString() << endl;
piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString();
return false;
}
//piCout << "[PIEthernet] listen on " << ip_ << ":" << port_ << endl;
//piCout << "[PIEthernet] listen on " << ip_ << ":" << port_;
server_thread_.start(server_func);
return true;
}
@@ -288,19 +309,27 @@ int PIEthernet::read(void * read_to, int max_size) {
::listen(sock, 64);
s = accept(sock, (sockaddr * )&client_addr, &slen);
if (s == -1) {
piCout << "[PIEthernet] Cant`t accept new connection, " << EthErrorString() << endl;
piCout << "[PIEthernet] Cant`t accept new connection, " << ethErrorString();
return -1;
}
rs = recv(s, (char * )read_to, max_size, 0);
closeSocket(s);
return rs;
case UDP: case TCP_Client:
case TCP_Client:
if (!connected_) return -1;
case UDP:
#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);
piCout << "eth" << path_ << "read return" << rs << errno;
if (rs <= 0) {
connected_ = false;
disconnected(rs < 0);
piCout << "eth" << path_ << "disconnected";
}
if (rs > 0) received(read_to, rs);
return rs;
//return ::read(sock, read_to, max_size);
default: break;
@@ -313,10 +342,10 @@ int PIEthernet::read(void * read_to, int max_size) {
int PIEthernet::write(const void * data, int max_size) {
if (sock == -1) init();
if (sock == -1 || !isWriteable()) {
//piCout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
//piCout << "[PIEthernet] Can`t send to uninitialized socket";
return -1;
}
//piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes" << endl;
//piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
int ret = 0;
switch (type_) {
case TCP_SingleTCP:
@@ -327,11 +356,14 @@ int PIEthernet::write(const void * data, int max_size) {
#ifdef QNX
addr_.sin_len = sizeof(addr_);
#endif
//piCout << "connect SingleTCP" << ip_s << ":" << port_s << "...";
if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) {
piCout << "[PIEthernet] Cant`t connect to " << ip_s << ":" << port_s << ", " << EthErrorString() << endl;
piCout << "[PIEthernet] Cant`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
return -1;
}
ret = ::write(sock, data, max_size);
//piCout << "ok, write SingleTCP" << int(data) << max_size << "bytes ...";
ret = ::send(sock, (const char *)data, max_size, 0);
//piCout << "ok, ret" << ret;
closeSocket(sock);
init();
return ret;
@@ -346,7 +378,7 @@ int PIEthernet::write(const void * data, int max_size) {
return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
#endif
case TCP_Client:
return ::write(sock, data, max_size);
return ::send(sock, (const char *)data, max_size, 0);
default: break;
//return ::read(sock, read_to, max_size);
}
@@ -359,12 +391,13 @@ void PIEthernet::server_func(void * eth) {
socklen_t slen = sizeof(client_addr);
int s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
if (s == -1) {
piCout << "[PIEthernet] Cant`t accept new connection, " << EthErrorString() << endl;
piCout << "[PIEthernet] Cant`t accept new connection, " << ethErrorString();
return;
}
PIString ip(inet_ntoa(client_addr.sin_addr));
ip += ":" + PIString::fromNumber(htons(client_addr.sin_port));
ce->clients_ << new PIEthernet(s, ip);
ce->newConnection(ce->clients_.back());
//cout << "connected " << ip << endl;
//char d[256];
//cout << " recv " << recv(s, d, 256, 0) << endl;
@@ -375,7 +408,7 @@ void PIEthernet::server_func(void * eth) {
PIStringList PIEthernet::interfaces() {
#ifdef WINDOWS
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead" << endl;
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
return PIStringList();
#else
# ifdef QNX
@@ -434,7 +467,7 @@ PIStringList PIEthernet::interfaces() {
PIString PIEthernet::interfaceAddress(const PIString & interface_) {
#ifdef WINDOWS
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead" << endl;
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
return PIString();
#else
struct ifreq ifr;
@@ -459,14 +492,14 @@ PIStringList PIEthernet::allAddresses() {
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO)));
if (pAdapterInfo == 0) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo" << endl;
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo";
return PIStringList();
}
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen));
if (pAdapterInfo == 0) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo" << endl;
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo";
return PIStringList();
}
}
@@ -482,7 +515,7 @@ PIStringList PIEthernet::allAddresses() {
pAdapter = pAdapter->Next;
}
} else
piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret << endl;
piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret;
if (pAdapterInfo)
HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
return al;
@@ -490,6 +523,6 @@ PIStringList PIEthernet::allAddresses() {
PIStringList il = interfaces(), al;
piForeachC (PIString & i, il)
al << interfaceAddress(i);
return al;
return al.removeStrings("0.0.0.0");
#endif
}

View File

@@ -1,6 +1,6 @@
/*
PIP - Platform Independent Primitives
Ethernet, UDP
Ethernet, UDP/TCP Broadcast/Multicast
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
@@ -24,8 +24,9 @@
#include "piiodevice.h"
#include "piprocess.h"
class PIEthernet: public PIIODevice
class PIP_EXPORT PIEthernet: public PIIODevice
{
PIOBJECT(PIEthernet)
friend class PIPeer;
public:
// slot is any function format "bool <func>(void*, uchar*, int)"
@@ -35,7 +36,7 @@ public:
enum Parameters {ReuseAddress = 0x1, Broadcast = 0x2};
PIEthernet(Type type = UDP, void * data = 0, ReadRetFunc slot = 0);
~PIEthernet();
virtual ~PIEthernet();
void setReadAddress(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);}
void setReadAddress(const PIString & ip_port) {path_ = ip_port;}
@@ -61,8 +62,9 @@ public:
bool joinMulticastGroup(const PIString & group);
bool leaveMulticastGroup(const PIString & group);
bool connect(const PIString & ip, int port);
bool connect(const PIString & ip_port) {parseAddress(ip_port, &ip_c, &port_c); return connect(ip_c, port_c);}
bool connect();
bool connect(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port); return connect();}
bool connect(const PIString & ip_port) {path_ = ip_port; return connect();}
bool isConnected() const {return connected_;}
bool listen();
@@ -73,9 +75,10 @@ public:
int clientsCount() const {return clients_.size_s();}
PIVector<PIEthernet * > clients() {return clients_;}
bool send(const PIString & ip, int port, const void * data, int size) {ip_s = ip; port_s = port; return send(data, size);}
bool send(const PIString & ip_port, const void * data, int size) {parseAddress(ip_port, &ip_s, &port_s); return send(data, size);}
bool send(const void * data, int size) {return (write(data, size) == size);}
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
bool send(const void * data, int size, bool threaded = false) {if (threaded) {writeThreaded(data, size); return true;} return (write(data, size) == size);}
bool send(const PIByteArray & ba, bool threaded = false) {if (threaded) {writeThreaded(ba); return true;} return (write(ba) == ba.size_s());}
int read(void * read_to, int max_size);
int write(const void * data, int max_size);
@@ -85,6 +88,10 @@ public:
static PIString interfaceAddress(const PIString & interface_);
static PIStringList allAddresses();
EVENT1(newConnection, PIEthernet * , client)
EVENT0(connected)
EVENT1(disconnected, bool, withError)
protected:
PIEthernet(int sock, PIString ip_port);
@@ -106,6 +113,7 @@ protected:
PIString ip_, ip_s, ip_c;
PIThread server_thread_;
PIVector<PIEthernet * > clients_;
PIQueue<PIString> mcast_queue;
#ifdef WINDOWS
PIMap<PIString, SOCKET> leafs;
#endif
@@ -115,7 +123,7 @@ protected:
private:
static void server_func(void * eth);
static std::string EthErrorString() {
static std::string ethErrorString() {
#ifdef WINDOWS
char * msg;
int err = WSAGetLastError();

View File

@@ -72,7 +72,7 @@ namespace PIEvaluatorTypes {
⋀ &
|
*/
class PIEvaluatorContent
class PIP_EXPORT PIEvaluatorContent
{
friend class PIEvaluator;
public:
@@ -108,7 +108,7 @@ private:
};
class PIEvaluator
class PIP_EXPORT PIEvaluator
{
public:
PIEvaluator() {;}

View File

@@ -32,7 +32,7 @@ bool PIFile::openDevice() {
bool PIFile::closeDevice() {
if (!opened_) return true;
if (!opened_ || fd == 0) return true;
return (fclose(fd) == 0);
}
@@ -104,7 +104,7 @@ void PIFile::resize(llong new_size, char fill_) {
delete[] buff;
return;
}
piCout << "[PIFile] Downsize is not support yet :-(" << endl;
piCout << "[PIFile] Downsize is not support yet :-(";
}

View File

@@ -27,27 +27,29 @@
/// void clear()
/// void resize(llong new_size, char fill = 0)
/// void remove()
class PIFile: public PIIODevice
class PIP_EXPORT PIFile: public PIIODevice
{
PIOBJECT(PIFile)
public:
PIFile(const PIString & path = PIString(), DeviceMode type = ReadWrite): PIIODevice(path, type) {setPrecision(5); openDevice();}
~PIFile() {close();}
//PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;}
void flush() {fflush(fd);}
EVENT_HANDLER(PIFile, void, clear) {close(); fd = fopen(path_.data(), "w"); close(); open();}
void flush() {if (!opened_) fflush(fd);}
EVENT_HANDLER(void, clear) {close(); fd = fopen(path_.data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();}
void seek(llong position) {if (!opened_) return; fseek(fd, position, SEEK_SET); clearerr(fd);}
void seekToBegin() {if (!opened_) return; fseek(fd, 0, SEEK_SET); clearerr(fd);}
void seekToEnd() {if (!opened_) return; fseek(fd, 0, SEEK_END); clearerr(fd);}
void seekToLine(llong line) {if (!opened_) return; seekToBegin(); piForTimes (line) readLine(); clearerr(fd);} // line 0 - begin of file
EVENT_HANDLER1(PIFile, void, resize, llong, new_size) {resize(new_size, 0);}
EVENT_HANDLER2(PIFile, void, resize, llong, new_size, char, fill);
EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);}
EVENT_HANDLER2(void, resize, llong, new_size, char, fill);
//void fill(char c) {stream.fill(c);}
char readChar() {return (char)fgetc(fd);}
PIString readLine();
llong readAll(void * data);
PIByteArray readAll(bool forceRead = false);
EVENT_HANDLER0(PIFile, void, remove) {close(); std::remove(path_.data());}
EVENT_HANDLER0(void, remove) {close(); std::remove(path_.data());}
void setPath(const PIString & path) {path_ = path; if (opened_) openDevice();}
llong size();
@@ -56,11 +58,11 @@ public:
bool isEmpty() {return (size() <= 0);}
int precision() const {return prec;}
void setPrecision(int prec_) {prec = prec_; prec_str = "." + itos(prec_);}
void setPrecision(int prec_) {prec = prec_; if (prec >= 0) prec_str = "." + itos(prec_); else prec_str = "";}
int read(void * read_to, int max_size) {if (!canRead()) return -1; return fread(read_to, max_size, 1, fd);}
int write(const void * data, int max_size) {if (!canWrite()) return -1; return fwrite(data, max_size, 1, fd);}
PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable()) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;}
int read(void * read_to, int max_size) {if (!canRead() || fd == 0) return -1; return fread(read_to, max_size, 1, fd);}
int write(const void * data, int max_size) {if (!canWrite() || fd == 0) return -1; return fwrite(data, max_size, 1, fd);}
PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable() || fd == 0) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;}
PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;}
@@ -75,7 +77,9 @@ public:
PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;}
PIFile & operator <<(const char & v) {if (!isWriteable()) return *this; write(&v, 1); return *this;}
PIFile & operator =(const PIFile & f) {path_ = f.path_; mode_ = f.mode_; return *this;}
PIFile & operator <<(const char v) {if (!isWriteable()) return *this; write(&v, 1); return *this;}
//PIFile & operator <<(const string & v) {write(v.c_str(), v.size()); return *this;}
PIFile & operator <<(const PIString & v) {if (!isWriteable()) return *this; write(v.data(), v.lengthAscii()); return *this;}
PIFile & operator <<(const PIByteArray & v) {if (!isWriteable()) return *this; write(v.data(), v.size()); return *this;}
@@ -83,11 +87,11 @@ public:
PIFile & operator <<(int v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%d", v); return *this;}
PIFile & operator <<(long v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%ld", v); return *this;}
PIFile & operator <<(llong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lld", v); return *this;}
PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%c", v); return *this;}
PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hd", v); return *this;}
PIFile & operator <<(uint v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%d", v); return *this;}
PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%ld", v); return *this;}
PIFile & operator <<(ullong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lld", v); return *this;}
PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%u", int(v)); return *this;}
PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hu", v); return *this;}
PIFile & operator <<(uint v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%u", v); return *this;}
PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lu", v); return *this;}
PIFile & operator <<(ullong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%llu", v); return *this;}
PIFile & operator <<(float v) {if (!isWriteable()) return *this; ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;}
PIFile & operator <<(double v) {if (!isWriteable()) return *this; ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;}

View File

@@ -23,7 +23,7 @@
#include "pimath.h"
template<typename Type>
class PIPoint {
class PIP_EXPORT PIPoint {
public:
Type x;
Type y;
@@ -55,7 +55,7 @@ template<typename Type>
std::ostream & operator <<(std::ostream & s, const PIPoint<Type> & v) {s << '{' << v.x << ", " << v.y << '}'; return s;}
template<typename Type>
class PIRect {
class PIP_EXPORT PIRect {
public:
Type x0;
Type y0;

View File

@@ -18,6 +18,7 @@
*/
#include "piincludes.h"
#include "pimutex.h"
bool isPIInit = false;
bool piDebug = true;
@@ -29,3 +30,41 @@ lconv * currentLocale = std::localeconv();
#ifdef MAC_OS
clock_serv_t __pi_mac_clock;
#endif
PIMutex __PICout_mutex__;
/*! \class PICout
* \brief Class for formatted output similar std::cout
*
* \section PICout_sec0 Synopsis
* This class provide many stream operators for output with some features.
* Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel
* threads.
*
* \section PICout_sec1 Features
* - insertion spaces between entries
* - insertion new line at the end of output
* - strings are quoted
* - custom output operator can be easily written
*
* \section PICout_ex0 Example
* \snippet picout.cpp 0
*/
PICout::PICout(PIFlags<PICoutControl> controls): fo_(true), cc_(false), co_(controls) {
__PICout_mutex__.lock();
}
PICout::~PICout() {
if (cc_) return;
newLine();
__PICout_mutex__.unlock();
}
/*! \mainpage Title
* This is main page
*/

View File

@@ -1,3 +1,9 @@
/*! \file piincludes.h
* \brief Global includes of PIP
*
* This file include all needed STL and declare many useful
* macros and functions
*/
/*
PIP - Platform Independent Primitives
Global includes
@@ -20,12 +26,58 @@
#ifndef PIINCLUDES_H
#define PIINCLUDES_H
#define PIP_VERSION 0x000300
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
#define PIP_VERSION 0x000304
//! Major value of PIP version
#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16
//! Minor value of PIP version
#define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8
//! Revision value of PIP version
#define PIP_VERSION_REVISION PIP_VERSION & 0xFF
//! Suffix of PIP version
#define PIP_VERSION_SUFFIX ""
#ifdef DOXYGEN
//! Macro is defined when compile-time debug is enabled
# define PIP_DEBUG
//! Macro is defined when host is any Windows
# define WINDOWS
//! Macro is defined when host is QNX
# define QNX
//! Macro is defined when host is FreeBSD
# define FREE_BSD
//! Macro is defined when host is Mac OS
# define MAC_OS
//! Macro is defined when host is any Linux
# define LINUX
//! Macro is defined when compiler is GCC or MinGW
# define CC_GCC
//! Macro is defined when PIP is decided that host is support language
# define HAS_LOCALE
//! Macro is defined when compiler is Visual Studio
# define CC_VC
//! Macro is defined when compiler is unknown
# define CC_OTHER
//! Macro is defined when PIP use "rt" library for timers implementation
# define PIP_TIMER_RT
#endif
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
# define WINDOWS
#endif
@@ -60,6 +112,13 @@
#else
# define CC_OTHER
#endif
#ifdef PIP_DEBUG
# undef NDEBUG
#else
# ifndef NDEBUG
# define NDEBUG
# endif
#endif
#ifdef WINDOWS
# ifdef CC_GCC
@@ -69,6 +128,11 @@
# define typeof __typeof__
#endif
#include "pip_export.h"
#if defined(DOXYGEN) || defined(CC_GCC)
# undef PIP_EXPORT
# define PIP_EXPORT
#endif
#include <iostream>
#ifdef CC_GCC
# include <unistd.h>
@@ -90,6 +154,7 @@
#include <cctype>
#include <ctime>
#include <csignal>
#include <cassert>
//#include <signal.h>
#include <typeinfo>
#include <algorithm>
@@ -153,7 +218,10 @@ extern char ** environ;
extern PIMonitor piMonitor;
//! Macro used for infinite loop
#define FOREVER for (;;)
//! Macro used for infinite wait
#define FOREVER_WAIT FOREVER msleep(1);
typedef long long llong;
@@ -175,6 +243,7 @@ using std::deque;
using std::stack;
using std::set;
using std::map;
using std::multimap;
using std::string;
#ifndef QNX
using std::wstring;
@@ -188,15 +257,118 @@ typedef std::basic_string<wchar_t> wstring;
static locale_t currentLocale_t = 0;
#endif
/*! \brief Templated function for swap two values
* \details Example:\n \snippet piincludes.cpp swap */
template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;}
/*! \brief Templated function return round of float falue
* \details Round is the nearest integer value \n
* There is some macros:
* - \c piRoundf for "float"
* - \c piRoundd for "double"
*
* Example:
* \snippet piincludes.cpp round */
template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
/*! \brief Templated function return floor of float falue
* \details Floor is the largest integer that is not greater than value \n
* There is some macros:
* - \c piFloorf for "float"
* - \c piFloord for "double"
*
* Example:
* \snippet piincludes.cpp floor */
template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
/*! \brief Templated function return ceil of float falue
* \details Ceil is the smallest integer that is not less than value \n
* There is some macros:
* - \c piCeilf for "float"
* - \c piCeild for "double"
*
* Example:
* \snippet piincludes.cpp ceil */
template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
/*! \brief Templated function return absolute of numeric falue
* \details Absolute is the positive or equal 0 value \n
* There is some macros:
* - \c piAbss for "short"
* - \c piAbsi for "int"
* - \c piAbsl for "long"
* - \c piAbsll for "llong"
* - \c piAbsf for "float"
* - \c piAbsd for "double"
*
* Example:
* \snippet piincludes.cpp abs */
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
/*! \brief Templated function return minimum of two values
* \details There is some macros:
* - \c piMins for "short"
* - \c piMini for "int"
* - \c piMinl for "long"
* - \c piMinll for "llong"
* - \c piMinf for "float"
* - \c piMind for "double"
*
* Example:
* \snippet piincludes.cpp min2 */
template<typename T> inline T piMin(const T & f, const T & s) {return (f > s) ? s : f;}
/*! \brief Templated function return minimum of tree values
* \details There is some macros:
* - \c piMins for "short"
* - \c piMini for "int"
* - \c piMinl for "long"
* - \c piMinll for "llong"
* - \c piMinf for "float"
* - \c piMind for "double"
*
* Example:
* \snippet piincludes.cpp min3 */
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);}
/*! \brief Templated function return maximum of two values
* \details There is some macros:
* - \c piMaxs for "short"
* - \c piMaxi for "int"
* - \c piMaxl for "long"
* - \c piMaxll for "llong"
* - \c piMaxf for "float"
* - \c piMaxd for "double"
*
* Example:
* \snippet piincludes.cpp max2 */
template<typename T> inline T piMax(const T & f, const T & s) {return (f < s) ? s : f;}
/*! \brief Templated function return maximum of tree values
* \details There is some macros:
* - \c piMaxs for "short"
* - \c piMaxi for "int"
* - \c piMaxl for "long"
* - \c piMaxll for "llong"
* - \c piMaxf for "float"
* - \c piMaxd for "double"
*
* Example:
* \snippet piincludes.cpp max3 */
template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);}
/*! \brief Templated function return clamped value
* \details Clamped is the not greater than "max" and not lesser than "min" value \n
* There is some macros:
* - \c piClamps for "short"
* - \c piClampi for "int"
* - \c piClampl for "long"
* - \c piClampll for "llong"
* - \c piClampf for "float"
* - \c piClampd for "double"
*
* Example:
* \snippet piincludes.cpp clamp */
template<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>
@@ -231,10 +403,11 @@ template<typename T> inline T piClamp(const T & v, const T & min, const T & max)
#define piClampd piClamp<double>
extern bool isPIInit;
extern bool piDebug;
extern string ifconfigPath;
#define piCout if (piDebug) cout
//! global variable enabling output to piCout
extern bool piDebug;
extern string ifconfigPath;
class PIInit {
public:
@@ -245,10 +418,8 @@ public:
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGALRM);
if (pthread_sigmask(SIG_BLOCK, &ss, 0) == -1) {
//cout << "[PITimer] sigaction error: " << errorString() << endl;
//return 0;
}
sigprocmask(SIG_BLOCK, &ss, 0);
pthread_sigmask(SIG_BLOCK, &ss, 0);
ifconfigPath = "/bin/ifconfig";
if (!fileExists(ifconfigPath)) {
ifconfigPath = "/sbin/ifconfig";
@@ -305,8 +476,8 @@ inline double round(const double & v) {return floor(v + 0.5);}
#endif
inline ushort letobe_s(ushort v) {return v = (v << 8) | (v >> 8);}
inline bool atob(const string & str) { return str == "1" ? true : false;};
inline string btos(const bool num) { return num ? "0" : "1";};
inline bool atob(const string & str) {return str == "1" ? true : false;}
inline string btos(const bool num) {return num ? "0" : "1";}
inline string itos(const int num) {
char ch[256];
#ifndef CC_VC
@@ -314,7 +485,7 @@ inline string itos(const int num) {
#else
sprintf_s(ch, 256, "%d", num);
#endif
return string(ch); };
return string(ch);}
inline string ltos(const long num) {
char ch[256];
#ifndef CC_VC
@@ -322,23 +493,23 @@ inline string ltos(const long num) {
#else
sprintf_s(ch, 256, "%ld", num);
#endif
return string(ch); };
return string(ch);}
inline string uitos(const uint num) {
char ch[256];
#ifndef CC_VC
sprintf(ch, "%ud", num);
sprintf(ch, "%u", num);
#else
sprintf_s(ch, 256, "%ud", num);
sprintf_s(ch, 256, "%u", num);
#endif
return string(ch); };
return string(ch);}
inline string ultos(const ulong num) {
char ch[256];
#ifndef CC_VC
sprintf(ch, "%lud", num);
sprintf(ch, "%lu", num);
#else
sprintf_s(ch, 256, "%lud", num);
sprintf_s(ch, 256, "%lu", num);
#endif
return string(ch); };
return string(ch);}
inline string ftos(const float num) {
char ch[256];
#ifndef CC_VC
@@ -346,7 +517,7 @@ inline string ftos(const float num) {
#else
sprintf_s(ch, 256, "%g", num);
#endif
return string(ch); };
return string(ch);}
inline string dtos(const double num) {
char ch[256];
#ifndef CC_VC
@@ -354,9 +525,11 @@ inline string dtos(const double num) {
#else
sprintf_s(ch, 256, "%g", num);
#endif
return string(ch); };
return string(ch);}
#ifdef CC_VC
/*! \fn errorString()
* \brief Return readable error description in format "code <number> - <description>" */
#ifdef WINDOWS
inline string errorString() {
char * msg;
int err = GetLastError();
@@ -368,6 +541,259 @@ inline void errorClear() {errno = 0;}
inline string errorString() {int e = errno; return "code " + itos(e) + " - " + string(strerror(e));}
#endif
/// Return readable version of PIP
inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION) + PIP_VERSION_SUFFIX;}
/*! \brief This class used as container for bit flags
* \details PIFlags is wrapper around \c "int". There are many
* bit-wise operators, native conversion to int and function
* to test flag. \n Example:
* \snippet piincludes.cpp flags
*/
template<typename Enum>
class PIP_EXPORT PIFlags {
public:
//! Constructor with flags = 0
PIFlags(): flags(0) {;}
//! Constructor with flags = Enum "e"
PIFlags(Enum e): flags(e) {;}
//! Constructor with flags = PIFlags "f"
PIFlags(const PIFlags & f): flags(f.flags) {;}
//! Constructor with flags = int "i"
PIFlags(const int i): flags(i) {;}
//! Set flags "f" to value "on"
PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
//! Set flag "e" to value "on"
PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
//! Set flag "i" to value "on"
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
//! copy operator
void operator =(const PIFlags & f) {flags = f.flags;}
//! copy operator
void operator =(const Enum & e) {flags = e;}
//! copy operator
void operator =(const int & i) {flags = i;}
//! compare operator
void operator ==(const PIFlags & f) {flags == f.flags;}
//! compare operator
void operator ==(const Enum & e) {flags == e;}
//! compare operator
void operator ==(const int i) {flags == i;}
//! compare operator
void operator !=(const PIFlags & f) {flags != f.flags;}
//! compare operator
void operator !=(const Enum & e) {flags != e;}
//! compare operator
void operator !=(const int i) {flags != i;}
//! compare operator
void operator >(const PIFlags & f) {flags > f.flags;}
//! compare operator
void operator >(const Enum & e) {flags > e;}
//! compare operator
void operator >(const int i) {flags > i;}
//! compare operator
void operator <(const PIFlags & f) {flags < f.flags;}
//! compare operator
void operator <(const Enum & e) {flags < e;}
//! compare operator
void operator <(const int i) {flags < i;}
//! compare operator
void operator >=(const PIFlags & f) {flags >= f.flags;}
//! compare operator
void operator >=(const Enum & e) {flags >= e;}
//! compare operator
void operator >=(const int i) {flags >= i;}
//! compare operator
void operator <=(const PIFlags & f) {flags <= f.flags;}
//! compare operator
void operator <=(const Enum & e) {flags <= e;}
//! compare operator
void operator <=(const int i) {flags <= i;}
//! Bit-wise AND operator
void operator &=(const PIFlags & f) {flags &= f.flags;}
//! Bit-wise AND operator
void operator &=(const Enum & e) {flags &= e;}
//! Bit-wise AND operator
void operator &=(const int i) {flags &= i;}
//! Bit-wise OR operator
void operator |=(const PIFlags & f) {flags |= f.flags;}
//! Bit-wise OR operator
void operator |=(const Enum & e) {flags |= e;}
//! Bit-wise OR operator
void operator |=(const int i) {flags |= i;}
//! Bit-wise XOR operator
void operator ^=(const PIFlags & f) {flags ^= f.flags;}
//! Bit-wise XOR operator
void operator ^=(const Enum & e) {flags ^= e;}
//! Bit-wise XOR operator
void operator ^=(const int i) {flags ^= i;}
//! Bit-wise AND operator
PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
//! Bit-wise AND operator
PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
//! Bit-wise AND operator
PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
//! Bit-wise OR operator
PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
//! Bit-wise OR operator
PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
//! Bit-wise OR operator
PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
//! Bit-wise XOR operator
PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
//! Bit-wise XOR operator
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
//! Bit-wise XOR operator
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
//! Test flag operator
bool operator [](Enum e) const {return (flags & e) == e;}
//! Implicity conversion to \c int
operator int() const {return flags;}
private:
int flags;
};
//! Macro used for conditional (piDebug) output to PICout
#define piCout if (piDebug) PICout()
class PIMutex;
extern PIMutex __PICout_mutex__;
//! \brief Namespace contains enums controlled PICout
namespace PICoutManipulators {
//! \brief Enum contains special characters
enum PIP_EXPORT PICoutSpecialChar {
Null /*! Null-character, '\\0' */,
NewLine /*! New line character, '\\n' */,
Tab /*! Tab character, '\\t' */,
Esc /*! Escape character, '\\e' */,
Quote /*! Quote character, '"' */
};
//! \brief Enum contains immediate action
enum PIP_EXPORT PICoutAction {
Flush /*! Flush the output */
};
//! \brief Enum contains control of PICout
enum PIP_EXPORT PICoutControl {
AddNone /*! No controls */ = 0x0,
AddSpaces /*! Spaces will be appear after each output */ = 0x1,
AddNewLine /*! New line will be appear after all output */ = 0x2,
AddQuotes /*! Each string will be quoted */ = 0x4,
AddAll /*! All controls */ = 0xFFFFFFFF
};
};
using namespace PICoutManipulators;
typedef PIFlags<PICoutControl> PICoutControls;
class PIP_EXPORT PICout {
public:
//! Default constructor with default features
PICout(PIFlags<PICoutControl> controls = AddSpaces | AddNewLine);
PICout(const PICout & other): fo_(other.fo_), cc_(true), co_(other.co_) {;}
~PICout();
//! Output operator for strings with <tt>"const char * "</tt> type
PICout operator <<(const char * v) {space(); quote(); std::cout << v; quote(); return *this;}
//! Output operator for strings with <tt>"std::string"</tt> type
PICout operator <<(const string & v) {space(); quote(); std::cout << v; quote(); return *this;}
//! Output operator for boolean values
PICout operator <<(const bool v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"char"</tt> values
PICout operator <<(const char v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"unsigned char"</tt> values
PICout operator <<(const uchar v) {space(); std::cout << ushort(v); return *this;}
//! Output operator for <tt>"short"</tt> values
PICout operator <<(const short v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"unsigned short"</tt> values
PICout operator <<(const ushort v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"int"</tt> values
PICout operator <<(const int v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"unsigned int"</tt> values
PICout operator <<(const uint v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"long"</tt> values
PICout operator <<(const long v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"unsigned long"</tt> values
PICout operator <<(const ulong v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"long long"</tt> values
PICout operator <<(const llong v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"unsigned long long"</tt> values
PICout operator <<(const ullong v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"float"</tt> values
PICout operator <<(const float v) {space(); std::cout << v; return *this;}
//! Output operator for <tt>"double"</tt> values
PICout operator <<(const double v) {space(); std::cout << v; return *this;}
//! Output operator for \a PICoutSpecialChar values
PICout operator <<(const PICoutSpecialChar v) {
switch (v) {
case Null: std::cout << char(0);
case NewLine: std::cout << '\n';
case Tab: std::cout << '\t';
case Esc: std::cout << '\e';
case Quote: std::cout << '"';
};
return *this;
}
//! Do some action
PICout operator <<(const PICoutAction v) {
switch (v) {
case Flush: std::cout << std::flush;
};
return *this;
}
//! Set control flag "c" is "on" state
void setControl(PICoutControl c, bool on = true) {co_.setFlag(c, on);}
//! Set control flags "c" and if "save" exec \a saveControl()
void setControl(PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c;}
//! Save control flags to internal stack \sa \a restoreControl()
void saveControl() {cos_.push(co_);}
//! Restore control flags from internal stack \sa \a saveControl()
void restoreControl() {if (!cos_.empty()) {co_ = cos_.top(); cos_.pop();}}
/*! \brief Conditional put space character to output
* \details If it is not a first output and control \a AddSpaces is set
* space character is put \sa \a quote(), \a newLine() */
inline void space() {if (!fo_ && co_[AddSpaces]) std::cout << ' '; fo_ = false;}
/*! \brief Conditional put quote character to output
* \details If control \a AddQuotes is set
* quote character is put \sa \a space(), \a newLine() */
inline void quote() {if (co_[AddQuotes]) std::cout << '"'; fo_ = false;}
/*! \brief Conditional put new line character to output
* \details If control \a AddNewLine is set
* new line character is put \sa \a space(), \a quote() */
inline void newLine() {if (co_[AddNewLine]) std::cout << std::endl; fo_ = false;}
private:
bool fo_, cc_;
PICoutControls co_;
std::stack<PICoutControls> cos_;
};
#endif // PIINCLUDES_H

View File

@@ -20,6 +20,45 @@
#include "piiodevice.h"
/*! \class PIIODevice
* \brief Base class for input/output classes
*
* \section PIIODevice_sec0 Synopsis
* This class provide open/close logic, threaded read and virtual input/output
* functions \a read() and \a write(). You should implement pure virtual
* function \a openDevice() in your subclass.
*
* \section PIIODevice_sec1 Open and close
* PIIODevice have boolean variable indicated open status. Returns of functions
* \a openDevice() and \a closeDevice() change this variable.
*
* \section PIIODevice_sec2 Threaded read
* PIIODevice based on PIThread, so it`s overload \a run() to exec \a read()
* in background thread. If read is successful virtual function \a threadedRead()
* is executed. Default implementation of this function execute external static
* function set by \a setThreadedReadSlot() with data set by \a setThreadedReadData().
* Extrenal static function should have format \n
* bool func_name(void * Threaded_read_data, uchar * readed_data, int readed_size)\n
* Threaded read starts with function \a startThreadedRead().
*
* \section PIIODevice_sec3 Internal buffer
* PIIODevice have internal buffer for threaded read, and \a threadedRead() function
* receive pointer to this buffer in first argument. You can adjust size of this buffer
* by function \a setThreadedReadBufferSize() \n
* Default size of this buffer is 4096 bytes
*
* \section PIIODevice_sec4 Reopen
* When threaded read is begin its call \a open() if device is closed. While threaded
* read running PIIODevice check if device opened every read and if not call \a open()
* every reopen timeout if reopen enabled. Reopen timeout is set by \a setReopenTimeout(),
* reopen enable is set by \a setReopenEnabled().
*
* \section PIIODevice_ex0 Example
* \snippet piiodevice.cpp 0
*/
//! Constructs a empty PIIODevice
PIIODevice::PIIODevice(): PIThread() {
mode_ = ReadOnly;
opened_ = init_ = thread_started_ = false;
@@ -27,12 +66,18 @@ PIIODevice::PIIODevice(): PIThread() {
reopen_timeout_ = 1000;
ret_func_ = 0;
ret_data_ = 0;
tri = 0;
buffer_tr.resize(4096);
CONNECT2(void, void * , int, &timer, timeout, this, check_start);
CONNECT(void, &write_thread, started, this, write_func);
init();
}
/*! \brief Constructs a PIIODevice with path and mode
* \param path path to device
* \param type mode for open
* \param initNow init or not in constructor */
PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool initNow): PIThread() {
path_ = path;
mode_ = type;
@@ -41,8 +86,10 @@ PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool
reopen_timeout_ = 1000;
ret_func_ = 0;
ret_data_ = 0;
tri = 0;
buffer_tr.resize(4096);
CONNECT2(void, void * , int, &timer, timeout, this, check_start);
CONNECT(void, &write_thread, started, this, write_func);
if (initNow) init();
}
@@ -56,6 +103,21 @@ void PIIODevice::check_start(void * data, int delim) {
}
void PIIODevice::write_func() {
while (!write_thread.isStopping()) {
while (!write_queue.isEmpty()) {
if (write_thread.isStopping()) return;
write_thread.lock();
PIPair<PIByteArray, ullong> item(write_queue.dequeue());
write_thread.unlock();
int ret = write(item.first);
threadedWriteEvent(item.second, ret);
}
msleep(1);
}
}
void PIIODevice::terminate() {
thread_started_ = false;
if (!isInitialized()) return;
@@ -103,4 +165,14 @@ void PIIODevice::run() {
return;
}
threadedRead(buffer_tr.data(), readed_);
threadedReadEvent(buffer_tr.data(), readed_);
}
ullong PIIODevice::writeThreaded(const PIByteArray & data) {
write_thread.lock();
write_queue.enqueue(PIPair<PIByteArray, ullong>(data, tri));
++tri;
write_thread.unlock();
return tri - 1;
}

View File

@@ -1,3 +1,6 @@
/*! \file piiodevice.h
* \brief Abstract input/output device
*/
/*
PIP - Platform Independent Primitives
Abstract input/output device
@@ -25,36 +28,59 @@
// function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData
typedef bool (*ReadRetFunc)(void * , uchar * , int );
/// events:
/// void opened()
/// void closed()
///
/// handlers:
/// bool open()
/// bool open(const PIString & path)
/// bool open(const DeviceMode & type)
/// bool open(const PIString & path, const DeviceMode & type)
/// bool close()
/// bool initialize()
/// void flush()
class PIIODevice: public PIThread {
// events:
// void opened()
// void closed()
//
// handlers:
// bool open()
// bool open(const PIString & path)
// bool open(const DeviceMode & type)
// bool open(const PIString & path, const DeviceMode & type)
// bool close()
// bool initialize()
// void flush()
class PIP_EXPORT PIIODevice: public PIThread
{
PIOBJECT(PIIODevice)
public:
PIIODevice();
enum DeviceMode {ReadOnly = 0x01, WriteOnly = 0x02, ReadWrite = 0x03};
//! \brief Open modes for PIIODevice
enum DeviceMode {
ReadOnly /*! Device can only read */ = 0x01,
WriteOnly /*! Device can only write */ = 0x02,
ReadWrite /*! Device can both read and write */ = 0x03
};
PIIODevice(const PIString & path, DeviceMode type = ReadWrite, bool initNow = true);
virtual ~PIIODevice() {if (opened_) {closeDevice(); if (!opened_) closed();}}
virtual ~PIIODevice() {stop(); write_thread.stop(); if (opened_) {closeDevice(); if (!opened_) closed();}}
//! Current open mode of device
DeviceMode mode() const {return mode_;}
//! Current path of device
PIString path() const {return path_;}
//! return \b true if mode is ReadOnly or ReadWrite
bool isReadable() const {return (mode_ & ReadOnly);}
//! return \b true if mode is WriteOnly or ReadWrite
bool isWriteable() const {return (mode_ & WriteOnly);}
bool isInitialized() const {return init_;}
//! return \b true if device is successfully opened
bool isOpened() const {return opened_;}
//! return \b true if device is closed
bool isClosed() const {return !opened_;}
//! return \b true if device can read \b now
bool canRead() const {return opened_ && (mode_ & ReadOnly);}
//! return \b true if device can write \b now
bool canWrite() const {return opened_ && (mode_ & WriteOnly);}
@@ -74,34 +100,83 @@ public:
int threadedReadBufferSize() const {return buffer_tr.size_s();}
const uchar * threadedReadBuffer() const {return buffer_tr.data();}
bool isThreadedRead() const {return isRunning();}
void startThreadedRead() {if (!isRunning()) start();}
void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) start();}
EVENT_HANDLER(PIIODevice, bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER1(PIIODevice, bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER1(PIIODevice, bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER2(PIIODevice, bool, open, const PIString &, _path, const DeviceMode &, _type) {path_ = _path; mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER(PIIODevice, bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;}
EVENT_HANDLER(PIIODevice, bool, initialize) {init_ = init(); return init_;}
// Flush device
EVENT_VHANDLER(PIIODevice, void, flush) {;}
EVENT(PIIODevice, opened)
EVENT(PIIODevice, closed)
bool isThreadedWrite() const {return write_thread.isRunning();}
void startThreadedWrite() {if (!write_thread.isRunning()) write_thread.startOnce();}
void stopThreadedWrite() {write_thread.stop();}
void clearThreadedWriteQueue() {write_thread.lock(); write_queue.clear(); write_thread.unlock();}
// Read from device to "read_to" maximum "max_size" bytes, return readed bytes count
virtual int read(void * read_to, int max_size) {piCout << "[PIIODevice] \"read\" not implemented!" << endl; return -2;}
virtual int read(void * read_to, int max_size) {piCout << "[PIIODevice] \"read\" not implemented!"; return -2;}
// Write to device "data" maximum "max_size" bytes, return written bytes count
virtual int write(const void * data, int max_size) {piCout << "[PIIODevice] \"write\" not implemented!" << endl; return -2;}
virtual int write(const void * data, int max_size) {piCout << "[PIIODevice] \"write\" not implemented!"; return -2;}
// Read from device maximum "max_size" bytes and return them as PIByteArray
PIByteArray read(int max_size) {buffer_in.resize(max_size); int ret = read(buffer_in.data(), max_size); if (ret < 0) return PIByteArray(); return buffer_in.resized(ret);}
int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
ullong writeThreaded(const void * data, int max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));}
ullong writeThreaded(const PIByteArray & data);
EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER1(bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER1(bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _type) {path_ = _path; mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER(bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;}
EVENT_HANDLER(bool, initialize) {init_ = init(); return init_;}
EVENT_VHANDLER(void, flush) {;}
EVENT(opened)
EVENT(closed)
EVENT2(threadedReadEvent, uchar * , readed, int, size)
EVENT2(threadedWriteEvent, ullong, id, int, written_size)
//! \handlers
//! \{
//! \fn bool open()
//! \brief Open device
//! \fn bool open(const PIString & path)
//! \brief Open device with path "path"
//! \fn bool open(const DeviceMode & mode)
//! \brief Open device with mode "mode"
//! \fn bool open(const PIString & path, const DeviceMode & mode)
//! \brief Open device with path "path" and mode "mode"
//! \}
//! \vhandlers
//! \{
//! \fn void flush()
//! \brief Immediate write all buffers
//! \}
//! \events
//! \{
//! \fn void opened()
//! \brief Raise if succesfull open
//! \fn void closed()
//! \brief Raise if succesfull close
//! \fn void threadedReadEvent(uchar * readed, int size)
//! \brief Raise if read thread succesfull read some data
//! \fn void threadedWriteEvent(ullong id, int written_size)
//! \brief Raise if write thread succesfull write some data of queue item with id "id"
//! \}
protected:
// Function executed before first openDevice() or from constructor
@@ -124,14 +199,18 @@ protected:
void * ret_data_;
private:
EVENT_HANDLER2(PIIODevice, void, check_start, void * , data, int, delim);
EVENT_HANDLER2(void, check_start, void * , data, int, delim);
EVENT_HANDLER(void, write_func);
void begin();
void run();
void end() {terminate();}
PITimer timer;
PIThread write_thread;
PIByteArray buffer_in, buffer_tr;
PIQueue<PIPair<PIByteArray, ullong> > write_queue;
ullong tri;
int readed_;
};

View File

@@ -42,8 +42,8 @@ PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() {
void PIKbdListener::begin() {
//cout << "list begin" << endl;
#ifdef WINDOWS
SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT);
GetConsoleMode(hIn, &tmode);
SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT);
#else
struct termios term;
tcgetattr(0, &term);
@@ -55,17 +55,68 @@ void PIKbdListener::begin() {
void PIKbdListener::run() {
rc = 0;
char lc = 0;
#ifdef WINDOWS
INPUT_RECORD ir;
ReadConsoleInput(hIn, &ir, 1, &ret);
if (ir.EventType == KEY_EVENT) {
KEY_EVENT_RECORD ker = ir.Event.KeyEvent;
if (ker.bKeyDown) {
bool ctrl = ((ker.dwControlKeyState & LEFT_CTRL_PRESSED) || (ker.dwControlKeyState & RIGHT_CTRL_PRESSED));
//cout << "key " << int(ker.wVirtualKeyCode) << endl;
switch (ker.wVirtualKeyCode) {
case 37: ret = 1; lc = (ctrl ? CtrlLeftArrow : LeftArrow); break;
case 38: ret = 1; lc = (ctrl ? CtrlUpArrow : UpArrow); break;
case 39: ret = 1; lc = (ctrl ? CtrlRightArrow : RightArrow); break;
case 40: ret = 1; lc = (ctrl ? CtrlDownArrow : DownArrow); break;
default: ret = 1; lc = ker.uChar.AsciiChar; break;
}
if (lc == 0) return;
} else return;
} else return;
/*if (lc == 0) {
ReadConsole(hIn, &rc, 1, &ret, 0);
//cout << "read console" << endl;
lc = char(rc);
}*/
/*if (ret < 0 || ret > 3) return;
lc = char(((uchar * )&rc)[ret - 1]);
for (int i = 0; i < ret; ++i)
cout << std::hex << int(((uchar * )&rc)[i]) << ' ';
cout << endl << std::hex << rc << endl;*/
#else
ret = read(0, &rc, 1);
ret = read(0, &rc, 4);
if (ret < 0 || ret > 3) return;
lc = char(((uchar * )&rc)[ret - 1]);
//for (int i = 0; i < ret; ++i)
// cout << std::hex << int(((uchar * )&rc)[i]) << ' ';
//cout << endl << std::hex << rc << endl;
if (((char * )&rc)[0] == '\e' && ret == 3) {
if (((char * )&rc)[1] == '[') {
switch (((char * )&rc)[2]) {
case 'A': lc = UpArrow; break; // up
case 'B': lc = DownArrow; break; // down
case 'C': lc = RightArrow; break; // right
case 'D': lc = LeftArrow; break; // left
}
}
}
if (((char * )&rc)[0] == '5' && ret == 2) {
switch (((char * )&rc)[1]) {
case 'A': lc = CtrlUpArrow; break; // up
case 'B': lc = CtrlDownArrow; break; // down
case 'C': lc = CtrlRightArrow; break; // right
case 'D': lc = CtrlLeftArrow; break; // left
}
}
#endif
if (exit_enabled && rc == exit_key) {
if (exit_enabled && ret == 1 && lc == exit_key) {
PIKbdListener::exiting = true;
return;
}
keyPressed(rc, data);
if (ret_func != 0 && ret > 0) ret_func(rc, data);
keyPressed(lc, data);
if (ret_func != 0 && ret > 0) ret_func(lc, data);
}

View File

@@ -35,25 +35,38 @@ typedef void (*KBFunc)(char, void * );
/// handlers:
/// void enableExitCapture(char key = 'Q')
/// void setActive(bool yes = true)
class PIKbdListener: public PIThread {
class PIP_EXPORT PIKbdListener: public PIThread
{
PIOBJECT(PIKbdListener)
friend class PIConsole;
public:
enum SpecialSymbol {
UpArrow = -1,
DownArrow = -2,
RightArrow = -3,
LeftArrow = -4,
CtrlUpArrow = -5,
CtrlDownArrow = -6,
CtrlRightArrow = -7,
CtrlLeftArrow = -8
};
// slot is any function format "void <func>(char, void * )"
PIKbdListener(KBFunc slot = 0, void * data = 0);
~PIKbdListener() {terminate(); end();}
void setData(void * data_) {data = data_;}
void setSlot(KBFunc slot_) {ret_func = slot_;}
EVENT_HANDLER(PIKbdListener, void, enableExitCapture) {enableExitCapture('Q');}
EVENT_HANDLER1(PIKbdListener, void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;}
EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');}
EVENT_HANDLER1(void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;}
void disableExitCapture() {exit_enabled = false;}
bool exitCaptured() const {return exit_enabled;}
char exitKey() const {return exit_key;}
bool isActive() {return is_active;}
EVENT_HANDLER(PIKbdListener, void, setActive) {setActive(true);}
EVENT_HANDLER1(PIKbdListener, void, setActive, bool, yes);
EVENT_HANDLER(void, setActive) {setActive(true);}
EVENT_HANDLER1(void, setActive, bool, yes);
EVENT2(PIKbdListener, keyPressed, char, key, void * , data)
EVENT2(keyPressed, char, key, void * , data)
static bool exiting;
@@ -62,6 +75,8 @@ private:
void run();
void end();
void raiseSpecial();
KBFunc ret_func;
char exit_key;
bool exit_enabled, is_active;
@@ -71,7 +86,7 @@ private:
void * hIn;
DWORD smode, tmode;
#else
char rc;
int rc;
int ret;
struct termios sterm, tterm;
#endif

View File

@@ -99,13 +99,15 @@ 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));
for (uint i = 0; i < v.size(); i++)
result[i] = abs(v[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));
for (uint i = 0; i < v.size(); i++)
result[i] = abs(v[i]);
return result;
}
@@ -117,7 +119,7 @@ class PIMathMatrixT;
#define PIMV_FOR(v, s) for (uint v = s; v < Size; ++v)
template<uint Size, typename Type = double>
class PIMathVectorT {
class PIP_EXPORT PIMathVectorT {
typedef PIMathVectorT<Size, Type> _CVector;
public:
PIMathVectorT() {resize(Size);}
@@ -139,7 +141,7 @@ public:
Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);}
Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);}
Type angleRad(const _CVector & v) const {return acos(angleCos(v));}
Type angleDeg(const _CVector & v) const {return toGrad(acos(angleCos(v)));}
Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));}
_CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));}
_CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; PIMV_FOR(i, 0) c[i] /= tv; return *this;}
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
@@ -207,7 +209,7 @@ typedef PIMathVectorT<4u, double> PIMathVectorT4d;
#define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v)
template<uint Cols, uint Rows = Cols, typename Type = double>
class PIMathMatrixT {
class PIP_EXPORT PIMathMatrixT {
typedef PIMathMatrixT<Cols, Rows, Type> _CMatrix;
typedef PIMathMatrixT<Rows, Cols, Type> _CMatrixI;
typedef PIMathVectorT<Rows, Type> _CMCol;
@@ -417,7 +419,7 @@ class PIMathMatrix;
#define PIMV_FOR(v, s) for (uint v = s; v < size_; ++v)
template<typename Type>
class PIMathVector {
class PIP_EXPORT PIMathVector {
typedef PIMathVector<Type> _CVector;
public:
PIMathVector(const uint size = 3) {resize(size);}
@@ -440,7 +442,7 @@ public:
Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);}
Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);}
Type angleRad(const _CVector & v) const {return acos(angleCos(v));}
Type angleDeg(const _CVector & v) const {return toGrad(acos(angleCos(v)));}
Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));}
_CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));}
_CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; PIMV_FOR(i, 0) c[i] /= tv; return *this;}
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
@@ -499,7 +501,7 @@ typedef PIMathVector<double> PIMathVectord;
#define PIMM_FOR_R(v) for (uint v = 0; v < rows_; ++v)
template<typename Type>
class PIMathMatrix {
class PIP_EXPORT PIMathMatrix {
typedef PIMathMatrix<Type> _CMatrix;
typedef PIMathVector<Type> _CMCol;
typedef PIMathVector<Type> _CMRow;
@@ -716,7 +718,7 @@ struct TransferFunction { // Для задания передаточной фу
// Эйлера
// Рунге-Кутта 4-го порядка
// Адамса-Бэшфортса-Моултона 2, 3, 4 порядков
class Solver
class PIP_EXPORT Solver
{
public:
enum Method {Global = -1,
@@ -774,7 +776,7 @@ private:
class PIFFT
class PIP_EXPORT PIFFT
{
public:
PIFFT();
@@ -827,7 +829,7 @@ private:
};
class PIStatistic {
class PIP_EXPORT PIStatistic {
public:
PIStatistic();
bool calculate(const PIVector<double> &val);

View File

@@ -20,7 +20,14 @@
#ifndef PIMONITOR_H
#define PIMONITOR_H
class PIMonitor
#include "pip_export.h"
#if defined(DOXYGEN) || defined(__GNUC__)
# undef PIP_EXPORT
# define PIP_EXPORT
#endif
class PIP_EXPORT PIMonitor
{
public:
PIMonitor();

View File

@@ -64,12 +64,12 @@ public:
PIRepeater(const PIString & config, const PIString & name) {
PIConfig conf(config, PIIODevice::ReadOnly);
if (!conf.isOpened()) {
piCout << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
piCout << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!";
return;
}
PIConfig::Entry & b(conf.getValue(name));
if (b.childCount() != 2) {
piCout << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!" << endl;
piCout << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!";
return;
}
addProtocol(config, b.child(0)->fullName());

View File

@@ -21,11 +21,11 @@
#define PIMUTEX_H
#include "piincludes.h"
#ifdef CC_GCC
#ifndef WINDOWS
# include <pthread.h>
#endif
class PIMutex
class PIP_EXPORT PIMutex
{
public:
#ifndef WINDOWS
@@ -59,7 +59,8 @@ private:
};
class PIMutexLocker
class PIP_EXPORT PIMutexLocker
{
public:
PIMutexLocker(PIMutex * m): mutex(m) {mutex->lock();}

View File

@@ -1,3 +1,8 @@
/*! \file piobject.h
* \brief Base object
*
* This file declare PIObject class and associated macros
*/
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
@@ -22,31 +27,166 @@
#include "pistring.h"
/// declare event handler \"event\" inside class \"obj\" with name \"name\", ret name()
#define EVENT_HANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} ret name()
#define EVENT_HANDLER1(obj, ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((obj*)o)->name(n0);} ret name(a0 n0)
#define EVENT_HANDLER2(obj, ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((obj*)o)->name(n0, n1);} ret name(a0 n0, a1 n1)
#define EVENT_HANDLER3(obj, ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((obj*)o)->name(n0, n1, n2);} ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_HANDLER4(obj, ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((obj*)o)->name(n0, n1, n2, n3);} ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#ifdef DOXYGEN
/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER
#define PIOBJECT(name)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\", ret name()
#define EVENT_HANDLER0(ret, name) ret name()
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\", ret name(type0 var0)
#define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\", ret name(type0 var0, type1 var1)
#define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\", ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3)
/// \relatesalso PIObject \brief EVENT_HANDLER is synonym of EVENT_HANDLER0
#define EVENT_HANDLER EVENT_HANDLER0
/// declare virtual event handler \"event\" inside class \"obj\" with name \"name\", virtual ret name()
#define EVENT_VHANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name()
#define EVENT_VHANDLER1(obj, ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((obj*)o)->name(n0);} virtual ret name(a0 n0)
#define EVENT_VHANDLER2(obj, ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((obj*)o)->name(n0, n1);} virtual ret name(a0 n0, a1 n1)
#define EVENT_VHANDLER3(obj, ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((obj*)o)->name(n0, n1, n2);} virtual ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_VHANDLER4(obj, ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((obj*)o)->name(n0, n1, n2, n3);} virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\", virtual ret name()
#define EVENT_VHANDLER0(ret, name) virtual ret name()
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\", virtual ret name(type0 var0)
#define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\", virtual ret name(type0 var0, type1 var1)
#define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\", virtual ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
/// \relatesalso PIObject \brief EVENT_VHANDLER is synonym of EVENT_VHANDLER0
#define EVENT_VHANDLER EVENT_VHANDLER0
/// declare event \"event\" inside class \"obj\" with name \"name\", void name();
#define EVENT0(obj, name) EVENT_HANDLER0(obj, void, name) {PIObject::raiseEvent(this, #name);}
#define EVENT1(obj, name, a0, n0) EVENT_HANDLER1(obj, void, name, a0, n0) {PIObject::raiseEvent(this, #name, n0);}
#define EVENT2(obj, name, a0, n0, a1, n1) EVENT_HANDLER2(obj, void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, #name, n0, n1);}
#define EVENT3(obj, name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(obj, void, name, a0, n0, a1, n1, a2, n2) {PIObject::raiseEvent(this, #name, n0, n1, n2);}
#define EVENT4(obj, name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(obj, void, name, a0, n0, a1, n1, a2, n2, a3, n3) {PIObject::raiseEvent(this, #name, n0, n1, n2, n3);}
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name();
#define EVENT0(name) void name();
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0);
#define EVENT1(name, type0, var0) void name(type0 var0);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1);
#define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2);
#define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
#define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);
/// \relatesalso PIObject \brief EVENT is synonym of EVENT0
#define EVENT EVENT0
#define RAISE_EVENT0(src, event)
#define RAISE_EVENT1(src, event, v0)
#define RAISE_EVENT2(src, event, v0, v1)
#define RAISE_EVENT3(src, event, v0, v1, v2)
#define RAISE_EVENT4(src, event, v0, v1, v2, v3)
#define RAISE_EVENT RAISE_EVENT0
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" with check of event and handler exists
#define CONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" with check of event and handler exists
#define CONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" with check of event and handler exists
#define CONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" with check of event and handler exists
#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" with check of event and handler exists
#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief CONNECT is synonym of CONNECT0
#define CONNECT CONNECT0
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" without check of event exists
#define WEAK_CONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" without check of event exists
#define WEAK_CONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" without check of event exists
#define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" without check of event exists
#define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dest\" without check of event exists
#define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief WEAK_CONNECT is synonym of WEAK_CONNECT0
#define WEAK_CONNECT WEAK_CONNECT0
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dest\"
#define DISCONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dest\"
#define DISCONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dest\"
#define DISCONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dest\"
#define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dest\"
#define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief DISCONNECT is synonym of DISCONNECT0
#define DISCONNECT DISCONNECT0
/// \relatesalso PIObject \brief Returns pointer to events handler \"handler\"
#define HANDLER(handler)
#else
#define PIOBJECT(obj) typedef obj __PIObject__;
#define EVENT_HANDLER0(ret, name) static ret __stat_eh_##name##__(void * o) {return ((__PIObject__*)o)->name();} ret name()
#define EVENT_HANDLER1(ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((__PIObject__*)o)->name(n0);} ret name(a0 n0)
#define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((__PIObject__*)o)->name(n0, n1);} ret name(a0 n0, a1 n1)
#define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)o)->name(n0, n1, n2);} ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)o)->name(n0, n1, n2, n3);} ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_HANDLER EVENT_HANDLER0
#define EVENT_VHANDLER0(ret, name) static ret __stat_eh_##name##__(void * o) {return ((__PIObject__*)o)->name();} virtual ret name()
#define EVENT_VHANDLER1(ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((__PIObject__*)o)->name(n0);} virtual ret name(a0 n0)
#define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((__PIObject__*)o)->name(n0, n1);} virtual ret name(a0 n0, a1 n1)
#define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)o)->name(n0, n1, n2);} virtual ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)o)->name(n0, n1, n2, n3);} virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_VHANDLER EVENT_VHANDLER0
#define EVENT0(name) EVENT_HANDLER0(void, name) {PIObject::raiseEvent(this, #name);}
#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {PIObject::raiseEvent(this, #name, n0);}
#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, #name, n0, n1);}
#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {PIObject::raiseEvent(this, #name, n0, n1, n2);}
#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) {PIObject::raiseEvent(this, #name, n0, n1, n2, n3);}
#define EVENT EVENT0
/// raise event \"event\" from object \"src\"
#define RAISE_EVENT0(src, event) (src)->event();
#define RAISE_EVENT1(src, event, v0) (src)->event(v0);
#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1);
@@ -54,31 +194,62 @@
#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
#define RAISE_EVENT RAISE_EVENT0
/// connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dst\" with check of event and handler exists
#define CONNECT0(ret, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__));
#define CONNECT1(ret, a0, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__));
#define CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__));
#define CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__));
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__));
#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__));
#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__));
#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__));
#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__));
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__));
#define CONNECT CONNECT0
/// connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dst\" without check of event exists
#define WEAK_CONNECT0(ret, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__));
#define WEAK_CONNECT1(ret, a0, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__));
#define WEAK_CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__));
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__));
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__));
#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
#define WEAK_CONNECT WEAK_CONNECT0
/// piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dst\"
#define DISCONNECT0(ret, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__));
#define DISCONNECT1(ret, a0, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__));
#define DISCONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__));
#define DISCONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__));
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__));
#define DISCONNECT0(ret, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT1(ret, a0, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT DISCONNECT0
class PIObject
#define HANDLER(handler) __stat_eh_##handler##__
#endif
typedef void (*Handler)(void * );
/** \brief This is base class for any classes which use events -> handlers mechanism.
* \details
* \section PIObject_sec0 Events and Event handlers
* %PIObject provide notification mechanism similar Qt but implemented
* on language capabilities without any special preprocessors or compilers.
* Any class inherits PIObject should use macro \a PIOBJECT() immediate
* after declaration to proper compile.
*
* Event is a some abstract event that can be raised at any time.
* Event is a function but declared with special macro \a EVENT().
* To raise event simply execute event function.
*
* Event handler is a function but declared with special macro
* \a EVENT_HANDLER(). You can use event handlers as ordinary functions.
*
* Main goal of this mechanism is perform abstract connections between
* various objects. This functionality provide macro \a CONNECT() which
* connect some event of first object to some event handler or event of
* second object. Each event can be connected any times to any event handlers.
*
* Example: \snippet piobject.cpp main
* Result:
* \code{.cpp}
* handler B: 2 , 0.5
* handler A: event to handler
* handler A: event to event
* \endcode
*/
class PIP_EXPORT PIObject
{
friend class PIObjectManager;
public:
@@ -145,6 +316,25 @@ public:
}
}
}
static void piDisconnect(PIObject * src, const PIString & sig, void * dest) {
for (int i = 0; i < src->connections.size_s(); ++i) {
Connection & cc(src->connections[i]);
if (cc.event == sig && cc.dest == dest) {
src->connections.remove(i);
i--;
}
}
}
static void piDisconnect(PIObject * src, const PIString & sig) {
for (int i = 0; i < src->connections.size_s(); ++i) {
Connection & cc(src->connections[i]);
if (cc.event == sig) {
src->connections.remove(i);
i--;
}
}
}
static void piDisconnect(PIObject * src) {src->connections.clear();}
//static void piConnect(PIObject & src, const PIString & sig, PIObject * dest, void * ev_h) {src.connections << Connection(ev_h, sig, dest);}
//static void piConnect(PIObject * src, const PIString & sig, PIObject & dest, void * ev_h) {src->connections << Connection(ev_h, sig, &dest);}
//static void piConnect(PIObject & src, const PIString & sig, PIObject & dest, void * ev_h) {src.connections << Connection(ev_h, sig, &dest);}

1
pip.h
View File

@@ -29,3 +29,4 @@
#include "pisystemmonitor.h"
#include "pipeer.h"
#include "picrc.h"
#include "pistatemachine.h"

125
pip.pro
View File

@@ -2,65 +2,82 @@
# Automatically generated by qmake (2.01a) ?? ???. 5 22:55:18 2011
######################################################################
TEMPLATE = app
TARGET = pip_test
TEMPLATE = lib
TARGET = pip
DEPENDPATH += .
INCLUDEPATH += .
QT -= core gui
LIBS = -lpthread -lrt
CONFIG -= qt
CONFIG += dll
VERSION = 0.3.4
# Input
HEADERS += pibitarray.h \
pibytearray.h \
pichar.h \
picli.h \
picodec.h \
piconfig.h \
piconsole.h \
picontainers.h \
pidir.h \
piethernet.h \
pievaluator.h \
pifile.h \
pigeometry.h \
piincludes.h \
pikbdlistener.h \
pimath.h \
pimonitor.h \
pimultiprotocol.h \
pimutex.h \
piobject.h \
pip.h \
piprocess.h \
piprotocol.h \
piserial.h \
pisignals.h \
pistring.h \
pisystemmonitor.h \
pithread.h \
HEADERS += \
pivariable.h \
pitimer.h \
pivariable.h
pithread.h \
pisystemtests.h \
pisystemmonitor.h \
pistring.h \
pisignals.h \
piserial.h \
piprotocol.h \
piprocess.h \
pipeer.h \
pipacketextractor.h \
pip.h \
piobject.h \
pimutex.h \
pimultiprotocol.h \
pimonitor.h \
pimath.h \
pikbdlistener.h \
piiodevice.h \
piincludes.h \
pigeometry.h \
pifile.h \
pievaluator.h \
piethernet.h \
pidir.h \
picrc.h \
picontainers.h \
piconsole.h \
piconfig.h \
picodec.h \
picli.h \
pichar.h \
pibytearray.h \
pibitarray.h
SOURCES += main.cpp \
pibytearray.cpp \
picli.cpp \
picodec.cpp \
piconfig.cpp \
piconsole.cpp \
pidir.cpp \
piethernet.cpp \
pievaluator.cpp \
pifile.cpp \
pikbdlistener.cpp \
pimath.cpp \
pimonitor.cpp \
pimultiprotocol.cpp \
piobject.cpp \
piprocess.cpp \
piprotocol.cpp \
piserial.cpp \
pisignals.cpp \
pistring.cpp \
pisystemmonitor.cpp \
pithread.cpp \
pivariable.cpp \
pitimer.cpp \
pivariable.cpp
pithread.cpp \
pisystemtests.cpp \
pisystemmonitor.cpp \
pistring.cpp \
pisignals.cpp \
piserial.cpp \
piprotocol.cpp \
piprocess.cpp \
pipeer.cpp \
pipacketextractor.cpp \
piobject.cpp \
pimonitor.cpp \
pimath.cpp \
pikbdlistener.cpp \
piiodevice.cpp \
piincludes.cpp \
pifile.cpp \
pievaluator.cpp \
piethernet.cpp \
pidir.cpp \
piconsole.cpp \
piconfig.cpp \
picodec.cpp \
picli.cpp \
pibytearray.cpp
win32 {
LIBS += -lws2_32 -lIphlpapi
} else {
LIBS = -lpthread -lrt
}

View File

@@ -26,7 +26,7 @@
// Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false.
typedef bool (*HeaderCheckFunc)(void * , uchar * , uchar * , int );
class PIPacketExtractor: public PIIODevice
class PIP_EXPORT PIPacketExtractor: public PIIODevice
{
public:
PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0);

View File

@@ -22,8 +22,9 @@
#include "piethernet.h"
class PIPeer: public PIEthernet
class PIP_EXPORT PIPeer: public PIEthernet
{
PIOBJECT(PIPeer)
struct PeerInfo;
friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v);
friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v);
@@ -37,7 +38,7 @@ protected:
bool threadedRead(uchar * readed, int size);
private:
EVENT_HANDLER2(PIPeer, void, timerEvent, void * , data, int, delim);
EVENT_HANDLER2(void, timerEvent, void * , data, int, delim);
static bool func_readed(void * peer, uchar * data, int size);
struct PeerInfo {

View File

@@ -141,12 +141,12 @@ void PIProcess::run() {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
} else
piCout << "[PIProcess] \"CreateProcess\" error, " << errorString() << endl;
piCout << "[PIProcess] \"CreateProcess\" error, " << errorString();
#else
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
if (execve(str.c_str(), a, e) < 0)
piCout << "[PIProcess] \"execve\" error, " << errorString() << endl;
piCout << "[PIProcess] \"execve\" error, " << errorString();
} else {
msleep(1);
//cout << "wait" << endl;

View File

@@ -40,11 +40,12 @@
/// bool exec(const PIString & program, const PIStringList & args)
/// void terminate()
/// bool waitForFinish(int timeout_msecs = 60000)
class PIProcess: private PIThread
class PIP_EXPORT PIProcess: private PIThread
{
PIOBJECT(PIProcess)
public:
PIProcess();
~PIProcess();
virtual ~PIProcess();
int exitCode() const {return exit_code;}
#ifdef WINDOWS
@@ -65,18 +66,18 @@ public:
PIString workingDirectory() const {return wd;}
void setWorkingDirectory(const PIString & path) {wd = path;}
void resetWorkingDirectory() {wd.clear();}
EVENT_HANDLER1(PIProcess, void, exec, const PIString & , program) {args.clear(); args << program; exec_();}
EVENT_HANDLER2(PIProcess, void, exec, const PIString & , program, const PIString & , arg) {args.clear(); args << program << arg; exec_();}
EVENT_HANDLER3(PIProcess, void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2) {args.clear(); args << program << arg1 << arg2; exec_();}
EVENT_HANDLER4(PIProcess, void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2, const PIString & , arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();}
EVENT_HANDLER2(PIProcess, void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();}
EVENT_HANDLER1(void, exec, const PIString & , program) {args.clear(); args << program; exec_();}
EVENT_HANDLER2(void, exec, const PIString & , program, const PIString & , arg) {args.clear(); args << program << arg; exec_();}
EVENT_HANDLER3(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2) {args.clear(); args << program << arg1 << arg2; exec_();}
EVENT_HANDLER4(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2, const PIString & , arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();}
EVENT_HANDLER2(void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();}
#ifdef WINDOWS
EVENT_HANDLER(PIProcess, void, terminate) {if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;}
EVENT_HANDLER(void, terminate) {if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;}
#else
EVENT_HANDLER(PIProcess, void, terminate) {if (is_exec) kill(pid, SIGKILL); pid = 0;}
EVENT_HANDLER(void, terminate) {if (is_exec) kill(pid, SIGKILL); pid = 0;}
#endif
EVENT_HANDLER(PIProcess, bool, waitForFinish) {return waitForFinish(60000);}
EVENT_HANDLER1(PIProcess, bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);}
EVENT_HANDLER(bool, waitForFinish) {return waitForFinish(60000);}
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);}
PIByteArray readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();}
PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();}
@@ -92,8 +93,8 @@ public:
static int currentPID() {return getpid();}
#endif
EVENT1(PIProcess, execStarted, PIString, program)
EVENT2(PIProcess, execFinished, PIString, program, int, exit_code)
EVENT1(execStarted, PIString, program)
EVENT2(execFinished, PIString, program, int, exit_code)
private:
virtual void run();

View File

@@ -26,7 +26,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
PIObject::setName(name);
PIConfig conf(config, PIIODevice::ReadOnly);
if (!conf.isOpened()) {
piCout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!";
devReceiverState = devSenderState = "Config error";
return;
}
@@ -41,7 +41,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
/// receiver section
if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -50,7 +50,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -59,7 +59,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -74,7 +74,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -85,18 +85,18 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
eth->setReopenTimeout(freq * 1000);
}
if (recDataPtr == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
if (recDataSize == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
} else {
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" or \"" << name << ".port\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" or \"" << name << ".port\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -106,7 +106,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -115,7 +115,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -124,7 +124,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -135,7 +135,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -154,7 +154,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -162,11 +162,11 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
}
has_dev = true;
if (recDataPtr == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
if (recDataSize == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
} else {
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -176,7 +176,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) history_write_rec = ghist;
if (gok && ok && (history_write_rec != ghist)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -187,7 +187,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
history_id_rec = rb.getValue("historyID", 0, &ok);
if (!ok) {
history_id_rec = protName.toByteArray().checksumCRC16();
piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver history ID defined, write with ID = " << history_id_rec << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver history ID defined, write with ID = " << history_id_rec;
}
history_file_rec.open(history_path_rec, PIIODevice::WriteOnly);
}
@@ -196,21 +196,21 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
gfreq = b.getValue("frequency", -1.f, &gok);
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
if (freq > 0.f && !has_dev)
piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!";
float tm = b.getValue("disconnectTimeout", 3.f);
if (tm <= 0.f)
piCout << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!";
timeout_ = (tm < 0.f) ? 0.f : tm;
setExpectedFrequency(freq);
/// sender section
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -220,7 +220,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -229,7 +229,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -243,7 +243,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -254,18 +254,18 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
eth->setReopenTimeout(freq * 1000);
}
if (sendDataPtr_ == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
if (sendDataSize_ == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
} else {
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" or \"" << name << ".port\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" or \"" << name << ".port\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -275,7 +275,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -284,7 +284,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -293,7 +293,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -304,14 +304,14 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
pp.setFlag(PISerial::TwoStopBits, flag);
}
} else {
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -322,16 +322,16 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
ser->setParameters(pp);
has_dev = true;
if (sendDataPtr_ == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
if (sendDataSize_ == 0)
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
}
history_write_send = sb.getValue("writeHistory", false, &ok);
ghist = b.getValue("writeHistory", false, &gok);
if (ok || gok) {
if (gok && !ok) history_write_send = ghist;
if (gok && ok && (history_write_send != ghist)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -342,7 +342,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
history_id_send = sb.getValue("historyID", 0, &ok);
if (!ok) {
history_id_send = protName.toByteArray().checksumCRC16() + 1;
piCout << "[PIProtocol \"" << name << "\"] Warning: no sender history ID defined, write with ID = " << history_id_send << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: no sender history ID defined, write with ID = " << history_id_send;
}
history_file_send.open(history_path_send, PIIODevice::WriteOnly);
}
@@ -351,12 +351,12 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
gfreq = b.getValue("frequency", -1.f, &gok);
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
if (freq > 0.f && !has_dev)
piCout << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!";
setSenderFrequency(freq);
headerPtr = (uchar * )recHeaderPtr;
@@ -643,7 +643,7 @@ void PIProtocol::calc_diag() {
else if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average;
else diag = PIProtocol::Good;
if (diag != net_diag) {
qualityChanged(net_diag, diag);
qualityChanged(diag, net_diag);
net_diag = diag;
}
}

View File

@@ -29,7 +29,7 @@
class PIProtocol;
class PIMultiProtocolBase
class PIP_EXPORT PIMultiProtocolBase
{
friend class PIProtocol;
public:
@@ -65,12 +65,12 @@ typedef void (*ReceiveFunc)(void * );
/// void stop()
/// void send()
/// void send(const void * data, int size, bool direct = false)
class PIProtocol: public PIObject
class PIP_EXPORT PIProtocol: public PIObject
{
PIOBJECT(PIProtocol)
friend class PIMultiProtocolBase;
friend class PIMultiProtocol;
enum Type {None, Serial, Ethernet};
public:
PIProtocol(): PIObject() {init();}
PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0,
@@ -79,9 +79,9 @@ public:
enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5};
EVENT_HANDLER0(PIProtocol, void, startReceive) {startReceive(-1.f);}
EVENT_HANDLER1(PIProtocol, void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value
EVENT_HANDLER0(PIProtocol, void, stopReceive);
EVENT_HANDLER0(void, startReceive) {startReceive(-1.f);}
EVENT_HANDLER1(void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value
EVENT_HANDLER0(void, stopReceive);
void setExpectedFrequency(float frequency); // for connection quality diagnostic
void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setPacketData(headerPtr, headerSize, dataSize);}
@@ -91,9 +91,9 @@ public:
void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;}
float expectedFrequency() const {return exp_freq;}
EVENT_HANDLER0(PIProtocol, void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value
EVENT_HANDLER1(PIProtocol, void, startSend, float, frequency); // if "frequency = -1" used last passed value
EVENT_HANDLER0(PIProtocol, void, stopSend) {sendTimer->stop(); senderStopped();}
EVENT_HANDLER0(void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value
EVENT_HANDLER1(void, startSend, float, frequency); // if "frequency = -1" used last passed value
EVENT_HANDLER0(void, stopSend) {sendTimer->stop(); senderStopped();}
void setSenderFrequency(float frequency) {send_freq = frequency;}
void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;}
@@ -103,11 +103,11 @@ public:
void setSenderParameters(PIFlags<PISerial::Parameters> parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
float senderFrequency() const {return send_freq;}
EVENT_HANDLER0(PIProtocol, void, start) {startReceive(); startSend();}
EVENT_HANDLER0(PIProtocol, void, stop) {stopReceive(); stopSend();}
EVENT_HANDLER0(PIProtocol, void, send);
EVENT_HANDLER2(PIProtocol, void, send, const void *, data, int, size) {send(data, size, false);}
EVENT_HANDLER3(PIProtocol, void, send, const void *, data, int, size, bool, direct);
EVENT_HANDLER0(void, start) {startReceive(); startSend();}
EVENT_HANDLER0(void, stop) {stopReceive(); stopSend();}
EVENT_HANDLER0(void, send);
EVENT_HANDLER2(void, send, const void *, data, int, size) {send(data, size, false);}
EVENT_HANDLER3(void, send, const void *, data, int, size, bool, direct);
void setName(const PIString & name) {protName = name; PIObject::setName(name);}
PIString name() const {return protName;}
@@ -161,12 +161,12 @@ public:
PIPacketExtractor * packetExtractor() {return packet_ext;}
PIByteArray lastHeader() {return packet_ext->lastHeader();}
EVENT0(PIProtocol, receiverStarted)
EVENT0(PIProtocol, receiverStopped)
EVENT0(PIProtocol, senderStarted)
EVENT0(PIProtocol, senderStopped)
EVENT1(PIProtocol, received, bool, validate_is_ok)
EVENT2(PIProtocol, qualityChanged, PIProtocol::Quality, old_quality, PIProtocol::Quality, new_quality)
EVENT0(receiverStarted)
EVENT0(receiverStopped)
EVENT0(senderStarted)
EVENT0(senderStopped)
EVENT1(received, bool, validate_is_ok)
EVENT2(qualityChanged, PIProtocol::Quality, new_quality, PIProtocol::Quality, old_quality)
protected:
virtual bool receive(uchar * data, int size) {if (dataPtr != 0) memcpy(dataPtr, data, size); return true;} // executed when raw data received, break if 'false' return

View File

@@ -67,14 +67,14 @@ bool PISerial::setPin(int number, bool on) {
case 3: return setST(on); break;
case 4: return setDTR(on); break;
case 5:
piCout << "[PISerial] Pin number 5 is ground" << endl;
piCout << "[PISerial] Pin number 5 is ground";
return false;
case 6: return setDSR(on); break;
case 7: return setRTS(on); break;
case 8: return setCTS(on); break;
case 9: return setRNG(on); break;
default:
piCout << "[PISerial] Pin number " << number << " doesn`t exists!" << endl;
piCout << "[PISerial] Pin number " << number << " doesn`t exists!";
return false;
}
return false;
@@ -93,7 +93,7 @@ bool PISerial::isPin(int number) const {
case 8: return isCTS(); break;
case 9: return isRNG(); break;
default:
piCout << "[PISerial] Pin number " << number << " doesn`t exists!" << endl;
piCout << "[PISerial] Pin number " << number << " doesn`t exists!";
return false;
}
return false;
@@ -103,7 +103,7 @@ bool PISerial::isPin(int number) const {
bool PISerial::setBit(int bit, bool on, const PIString & bname) {
#ifndef WINDOWS
if (fd < 0) {
piCout << "[PISerial] set" << bname << " error: \"" << path_ << "\" is not opened!" << endl;
piCout << "[PISerial] set" << bname << " error: \"" << path_ << "\" is not opened!";
return false;
}
if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) {
@@ -112,7 +112,7 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) {
}
return true;
#else
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl;
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
return false;
#endif
}
@@ -121,7 +121,7 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) {
bool PISerial::isBit(int bit, const PIString & bname) const {
#ifndef WINDOWS
if (fd < 0) {
piCout << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!" << endl;
piCout << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!";
return false;
}
int ret = 0;
@@ -129,7 +129,7 @@ bool PISerial::isBit(int bit, const PIString & bname) const {
piCout << "[PISerial] is" << bname << " error: " << errorString();
return ret & bit;
#else
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl;
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
return false;
#endif
}
@@ -301,7 +301,7 @@ bool PISerial::openDevice() {
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
hCom = CreateFileA(path_.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(hCom == INVALID_HANDLE_VALUE) {
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
piCout << "[PISerial] Unable to open \"" << path_ << "\"";
return false;
}
fd = 0;
@@ -312,7 +312,7 @@ bool PISerial::openDevice() {
times.WriteTotalTimeoutConstant = 1;
times.WriteTotalTimeoutMultiplier = 0;
if (SetCommTimeouts(hCom, &times) == -1) {
piCout << "[PISerial] Unable to set timeouts for \"" << path_ << "\"" << endl;
piCout << "[PISerial] Unable to set timeouts for \"" << path_ << "\"";
CloseHandle(hCom);
fd = -1;
return false;
@@ -330,7 +330,7 @@ bool PISerial::openDevice() {
}
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
if (SetCommState(hCom, &desc) == -1) {
piCout << "[PISerial] Unable to set comm state for \"" << path_ << "\"" << endl;
piCout << "[PISerial] Unable to set comm state for \"" << path_ << "\"";
CloseHandle(hCom);
fd = -1;
return false;
@@ -345,7 +345,7 @@ bool PISerial::openDevice() {
//cout << "init ser " << path_ << " mode " << om << " param " << params << endl;
fd = ::open(path_.data(), O_NOCTTY | om);
if(fd == -1) {
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
piCout << "[PISerial] Unable to open \"" << path_ << "\"";
return false;
}
@@ -371,20 +371,20 @@ bool PISerial::openDevice() {
fcntl(fd, F_SETFL, 0);
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl;
piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"";
::close(fd);
return false;
}
//piCout << "[PISerial] Initialized " << path_ << endl;
//piCout << "[PISerial] Initialized " << path_;
#endif
return true;
}
int PISerial::write(const void * data, int max_size, bool wait) {
//piCout << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size) << endl;
//piCout << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size);
if (fd == -1 || !canWrite()) {
//piCout << "[PISerial] Can`t write to uninitialized COM" << endl;
//piCout << "[PISerial] Can`t write to uninitialized COM";
return -1;
}
#ifdef WINDOWS
@@ -402,6 +402,6 @@ int PISerial::write(const void * data, int max_size, bool wait) {
if (wait) tcdrain(fd);
#endif
return (int)wrote;
//piCout << "[PISerial] Error while sending" << endl;
//piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl;
//piCout << "[PISerial] Error while sending";
//piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_;
}

View File

@@ -29,7 +29,7 @@
# ifndef B50
# define B50 0000001
# endif
# ifndef B50
# ifndef B75
# define B75 0000002
# endif
# ifndef B1500000
@@ -83,8 +83,11 @@
# define B3500000 3500000
# define B4000000 4000000
#endif
#ifndef CRTSCTS
# define CRTSCTS 020000000000
#endif
class PISerial: public PIIODevice {
class PIP_EXPORT PISerial: public PIIODevice {
public:
// slot is any function format "bool <func>(void*, uchar*, int)"
// slot_header is any function format "bool <func>(void*, uchar*, uchar*, int)"

View File

@@ -23,7 +23,7 @@
#include "picontainers.h"
#include <csignal>
class PISignals
class PIP_EXPORT PISignals
{
public:
enum Signal {

View File

@@ -20,6 +20,41 @@
#include "pistring.h"
/*! \class PIString
* \brief String class
* \details PIP use this class for use string information.
*
* \section PIString_sec0 Synopsis
* This class based on \a PIVector to store information.
* String is a sequence of \a PIChar and can contain multibyte
* symbols. Therefore real memory size of string is symbols count * 4.
* String can be constucted from many types of data and can be converted
* to many types. There are man operators and handly functions to use
* string as you wish.
*
* \section PIString_sec1 To/from data convertions
* Most common constructor is \a PIString(const char * str), where "str"
* is null-terminated string, e.g. \c "string". This is 7 chars with last char = 0.
* Also you can constructs \a PIString from single \a PIChar, \a PIByteArray,
* other \a PIString or sequency of the same characters with custom length.\n \n
* This class has implicit conversions to <tt>const char * </tt> and
* \c std::string. Also there are functions to make same convertions:
* * \a data() - to <tt>const char * </tt>,
* * \a stdString() - to \c std::string,
* * \a toByteArray() - to \a PIByteArray.
*
* \section PIString_sec2 Numeric operations
* You can get symbolic representation of any numeric value with function
* \a setNumber(any integer value, int base = 10, bool * ok = 0). Default
* arguments are set for decimal base system, but you can choose any system
* from 2 to 40. There are the same static functions \a fromNumber(), that
* returns \a PIString. \n
* Also there is function \a setReadableSize() which is set human-readable
* size in bytes, Kb, Mb, Gb or Pb. Static analog is \a readableSize().
*
*/
const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
@@ -346,25 +381,24 @@ int PIString::lengthAscii() const {
const char * PIString::data() const {
PIByteArray & d_(*(const_cast<PIByteArray * >(&data_)));
d_.clear();
data_.clear();
int wc;
uchar tc;
for (int i = 0, j = 0; i < size_s(); ++i) {
wc = at(i).toInt();
while (tc = wc & 0xFF, tc) {
d_.push_back(uchar(tc)); ++j;
data_.push_back(uchar(tc)); ++j;
wc >>= 8;
}
/*if (at(i).isAscii())
d_.push_back(uchar(at(i).toAscii()));
data_.push_back(uchar(at(i).toAscii()));
else {
d_.push_back((at(i).toCharPtr()[0])); ++j;
d_.push_back((at(i).toCharPtr()[1]));
data_.push_back((at(i).toCharPtr()[0])); ++j;
data_.push_back((at(i).toCharPtr()[1]));
}*/
}
d_.push_back(uchar('\0'));
return (const char * )d_.data();
data_.push_back(uchar('\0'));
return (const char * )data_.data();
}
@@ -439,25 +473,29 @@ llong PIString::toLLong() const {
}
*/
PIString & PIString::setReadableSize(long bytes) {
PIString & PIString::setReadableSize(llong bytes) {
clear();
if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;}
double fres = bytes / 1024.;
long res = bytes / 1024;
llong res = bytes / 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " kB"); return *this;}
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " kB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " MB"); return *this;}
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " MB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " GB"); return *this;}
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " GB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " PB");
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " TB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " PB");
return *this;
}
@@ -476,6 +514,7 @@ inline char chrLwr(char c) {
}
PIStringList& PIStringList::removeDuplicates() {
PIStringList l;
PIString s;

View File

@@ -1,3 +1,8 @@
/*! \file pistring.h
* \brief String
*
* This file declare string and string list classes
*/
/*
PIP - Platform Independent Primitives
String
@@ -26,13 +31,14 @@
class PIStringList;
class PIString: public PIVector<PIChar>
class PIP_EXPORT PIString: public PIVector<PIChar>
{
public:
PIString() {piMonitor.strings++; piMonitor.containers--;}
//! Contructs an empty string
PIString() {reserve(256); piMonitor.strings++; piMonitor.containers--;}
//inline PIString & operator +=(const char c) {push_back(c); return *this;}
PIString & operator +=(const PIChar c) {push_back(c); return *this;}
PIString & operator +=(const PIChar & c) {push_back(c); return *this;}
PIString & operator +=(const char * str);
PIString & operator +=(const wchar_t * str);
PIString & operator +=(const string & str) {appendFromChars(str.c_str(), str.length()); return *this;}
@@ -43,107 +49,335 @@ public:
#endif
//PIString(const char c) {*this += c;}
PIString(const PIChar c) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;}
//! Contructs string with single symbol "c"
PIString(const PIChar & c) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;}
/*! \brief Contructs string from c-string "str"
* \details "str" should be null-terminated\n
* Example: \snippet pistring.cpp PIString(char * ) */
PIString(const char * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
/*! \brief Contructs string from \c wchar_t c-string "str"
* \details "str" should be null-terminated\n
* Example: \snippet pistring.cpp PIString(wchar_t * ) */
PIString(const wchar_t * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
//! Contructs string from std::string "str"
PIString(const string & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
#ifdef HAS_LOCALE
PIString(const wstring & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
#endif
//! Contructs string from byte array "ba"
PIString(const PIByteArray & ba) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;}
/*! \brief Contructs string from "len" characters of buffer "str"
* \details Example: \snippet pistring.cpp PIString(char * , int) */
PIString(const char * str, const int len) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += string(str, len);}
/*! \brief Contructs string as sequence of characters "c" of buffer with length "len"
* \details Example: \snippet pistring.cpp PIString(int, char) */
PIString(const int len, const char c) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
/*! \brief Contructs string as sequence of symbols "c" of buffer with length "len"
* \details Example: \snippet pistring.cpp PIString(int, PIChar) */
PIString(const int len, const PIChar & c) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
//! Contructs string from other string "str"
PIString(const PIString & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
~PIString() {piMonitor.strings--; piMonitor.containers++;}
/*! \brief Return c-string representation of string
* \details Converts content of string to c-string and return
* pointer to first char. This buffer is valid until new convertion
* or execution \a data() or \a toByteArray().\n
* Example: \snippet pistring.cpp PIString::char* */
operator const char*() {return data();}
//! Return std::string representation of string
operator const string() {if (size() == 0) return string(); string s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toAscii()); return s;}
//! Return symbol at index "pos"
PIChar operator [](const int pos) const {return at(pos);}
//! Return const reference symbol at index "pos"
PIChar & operator [](const int pos) {return at(pos);}
//! Compare operator
bool operator ==(const PIString & str) const;
//! Compare operator
bool operator ==(const PIChar c) const {return *this == PIString(c);}
//inline bool operator ==(const char c) const {return *this == PIString(c);}
//! Compare operator
bool operator ==(const char * str) const {return *this == PIString(str);}
//! Compare operator
bool operator ==(const string & str) const {return *this == PIString(str);}
//! Compare operator
bool operator !=(const PIString & str) const;
//! Compare operator
bool operator !=(const PIChar c) const {return *this != PIString(c);}
//inline bool operator !=(const char c) const {return *this != PIString(c);}
//! Compare operator
bool operator !=(const char * str) const {return *this != PIString(str);}
//! Compare operator
bool operator !=(const string & str) const {return *this != PIString(str);}
//! Compare operator
bool operator <(const PIString & str) const;
//! Compare operator
bool operator <(const PIChar c) const {return *this < PIString(c);}
//inline bool operator <(const char c) const {return *this < PIString(c);}
//! Compare operator
bool operator <(const char * str) const {return *this < PIString(str);}
//! Compare operator
bool operator <(const string & str) const {return *this < PIString(str);}
//! Compare operator
bool operator >(const PIString & str) const;
//! Compare operator
bool operator >(const PIChar c) const {return *this > PIString(c);}
//inline bool operator >(const char c) const {return *this > PIString(c);}
//! Compare operator
bool operator >(const char * str) const {return *this > PIString(str);}
//! Compare operator
bool operator >(const string & str) const {return *this > PIString(str);}
//! Compare operator
bool operator <=(const PIString & str) const {return !(*this > str);}
//! Compare operator
bool operator <=(const PIChar c) const {return *this <= PIString(c);}
//inline bool operator <=(const char c) const {return *this <= PIString(c);}
//! Compare operator
bool operator <=(const char * str) const {return *this <= PIString(str);}
//! Compare operator
bool operator <=(const string & str) const {return *this <= PIString(str);}
//! Compare operator
bool operator >=(const PIString & str) const {return !(*this < str);}
//! Compare operator
bool operator >=(const PIChar c) const {return *this >= PIString(c);}
//inline bool operator >=(const char c) const {return *this >= PIString(c);}
//! Compare operator
bool operator >=(const char * str) const {return *this >= PIString(str);}
//! Compare operator
bool operator >=(const string & str) const {return *this >= PIString(str);}
/*! \brief Append string "str" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(PIString) */
PIString & operator <<(const PIString & str) {*this += str; return *this;}
//inline PIString & operator <<(const char c) {*this += c; return *this;}
PIString & operator <<(const PIChar c) {*this += c; return *this;}
/*! \brief Append symbol "c" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(PIChar) */
PIString & operator <<(const PIChar & c) {*this += c; return *this;}
/*! \brief Append c-string "str" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(char * ) */
PIString & operator <<(const char * str) {*this += str; return *this;}
/*! \brief Append \c wchar_t c-string "str" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(wchar_t * ) */
PIString & operator <<(const wchar_t * str) {*this += str; return *this;}
//! Append std::string "str" at the end of string
PIString & operator <<(const string & str) {*this += str; return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Return part of string from symbol at index "start" and maximum length "len"
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid
* \sa \a left(), \a right() */
PIString mid(const int start, const int len = -1) const;
/*! \brief Return part of string from left and maximum length "len"
* \details Example: \snippet pistring.cpp PIString::left
* \sa \a mid(), \a right() */
PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);}
/*! \brief Return part of string from right and maximum length "len"
* \details Example: \snippet pistring.cpp PIString::right
* \sa \a mid(), \a left() */
PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);}
/*! \brief Remove part of string from symbol as index "start" and maximum length "len"
* and return this string
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::cutMid
* \sa \a cutLeft(), \a cutRight() */
PIString & cutMid(const int start, const int len);
/*! \brief Remove part of string from left and maximum length "len" and return this string
* \details Example: \snippet pistring.cpp PIString::cutLeft
* \sa \a cutMid(), \a cutRight() */
PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);}
/*! \brief Remove part of string from right and maximum length "len" and return this string
* \details Example: \snippet pistring.cpp PIString::cutRight
* \sa \a cutMid(), \a cutLeft() */
PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);}
/*! \brief Remove spaces at the start and at the end of string and return this string
* \details Example: \snippet pistring.cpp PIString::trim
* \sa \a trimmed() */
PIString & trim();
/*! \brief Return copy of this string without spaces at the start and at the end
* \details Example: \snippet pistring.cpp PIString::trimmed
* \sa \a trim() */
PIString trimmed() const;
/*! \brief Replace part of string from index "from" and maximum length "len"
* with string "with" and return this string
* \details Example: \snippet pistring.cpp PIString::replace_0
* \sa \a replaced(), \a replaceAll() */
PIString & replace(const int from, const int count, const PIString & with);
/*! \brief Replace part copy of this string from index "from" and maximum length "len"
* with string "with" and return copied string
* \details Example: \snippet pistring.cpp PIString::replaced_0
* \sa \a replace(), \a replaceAll() */
PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;}
/*! \brief Replace first founded substring "what" with string "with" and return this string
* \details If "ok" is not null, it set to "true" if something was replaced\n
* Example: \snippet pistring.cpp PIString::replace_1
* \sa \a replaced(), \a replaceAll() */
PIString & replace(const PIString & what, const PIString & with, bool * ok = 0);
/*! \brief Replace first founded substring "what" with string "with" and return copied string
* \details If "ok" is not null, it set to "true" if something was replaced\n
* Example: \snippet pistring.cpp PIString::replaced_1
* \sa \a replaced(), \a replaceAll() */
PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;}
/*! \brief Replace all founded substrings "what" with strings "with" and return this string
* \details Example: \snippet pistring.cpp PIString::replaceAll
* \sa \a replace(), \a replaced() */
PIString & replaceAll(const PIString & what, const PIString & with);
PIString replaceAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;}
/*! \brief Insert symbol "c" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_0 */
PIString & insert(const int index, const PIChar & c) {PIVector<PIChar>::insert(index, c); return *this;}
/*! \brief Insert symbol "c" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_1 */
PIString & insert(const int index, const char & c) {return insert(index, PIChar(c));}
/*! \brief Insert string "str" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_2 */
PIString & insert(const int index, const PIString & str);
/*! \brief Insert string "str" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_2 */
PIString & insert(const int index, const char * c) {return insert(index, PIString(c));}
/*! \brief Enlarge string to length "len" by addition sequence of symbols
* "c" at the end of string, and return this string
* \details Example: \snippet pistring.cpp PIString::expandRightTo
* \sa \a expandLeftTo() */
PIString & expandRightTo(const int len, const PIChar & c) {if (len > length()) resize(len, c); return *this;}
/*! \brief Enlarge string to length "len" by addition sequence of symbols
* "c" at the beginning of string, and return this string
* \details Example: \snippet pistring.cpp PIString::expandLeftTo
* \sa \a expandRightTo() */
PIString & expandLeftTo(const int len, const PIChar & c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;}
/*! \brief Reverse string and return this string
* \details Example: \snippet pistring.cpp PIString::reverse
* \sa \a reversed() */
PIString & reverse() {PIString str(*this); clear(); piForeachR (const PIChar & c, str) push_back(c); return *this;}
/*! \brief Reverse copy of this string and return it
* \details Example: \snippet pistring.cpp PIString::reversed
* \sa \a reverse() */
PIString reversed() const {PIString str(*this); str.reverse(); return str;}
//const char * data() {return convertToStd().c_str();}
/*! \brief Return real bytes count of this string
* \details It`s equivalent length os char sequence
* returned by function \a data() \n
* Example: \snippet pistring.cpp PIString::lengthAscii
* \sa \a data() */
int lengthAscii() const;
/*! \brief Return \c char * representation of this string
* \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n
* Example: \snippet pistring.cpp PIString::data
* \sa \a lengthAscii() */
const char * data() const;
//! \brief Return \c std::string representation of this string
const string stdString() const {return convertToStd();}
#ifdef HAS_LOCALE
wstring stdWString() const {return convertToWString();}
#endif
//! \brief Return \a PIByteArray contains \a data() of this string
PIByteArray toByteArray() const {const char * d = data(); return PIByteArray(d, lengthAscii());}
/*! \brief Split string with delimiter "delim" to \a PIStringList and return it
* \details Example: \snippet pistring.cpp PIString::split */
PIStringList split(const PIString & delim) const;
//! \brief Convert each symbol in copyed string to upper case and return it
PIString toUpperCase() const;
//! \brief Convert each symbol in copyed string to lower case and return it
PIString toLowerCase() const;
#ifdef HAS_LOCALE
PIString toNativeDecimalPoints() const {PIString s(*this); if (currentLocale == 0) return s; return s.replaceAll(".", currentLocale->decimal_point);}
@@ -151,60 +385,199 @@ public:
PIString toNativeDecimalPoints() const {PIString s(*this); return s;}
#endif
//! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \details Example: \snippet pistring.cpp PIString::find
int find(const char str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \details Example: \snippet pistring.cpp PIString::find
int find(const PIString str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \details Example: \snippet pistring.cpp PIString::find
int find(const char * str, const int start = 0) const {return find(PIString(str), start);}
//! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \details Example: \snippet pistring.cpp PIString::find
int find(const string str, const int start = 0) const {return find(PIString(str), start);}
//! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const char str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const PIString str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);}
//! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const string str, const int start = 0) const {return findLast(PIString(str), start);}
//! \brief Return symbols length of string
int length() const {return size();}
//! \brief Return \c true if string is empty, i.e. length = 0
bool isEmpty() const {return (size() == 0 || *this == "");}
//! \brief Return \c true if string equal "true" or "on" or positive numeric value
bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true" || s.trimmed().toLowerCase() == "on") return true; return false;}
//! \brief Return \c char numeric value of string
char toChar() const;
//! \brief Return \c short numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));}
//! \brief Return \c ushort numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));}
//! \brief Return \c int numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));}
//! \brief Return \c uint numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));}
//! \brief Return \c long numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));}
//! \brief Return \c ulong numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));}
//! \brief Return \c llong numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);}
//! \brief Return \c ullong numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));}
//! \brief Return \c float numeric value of string
//! \details Example: \snippet pistring.cpp PIString::toFloat
float toFloat() const {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().data());}
//! \brief Return \c double numeric value of string
//! \details Example: \snippet pistring.cpp PIString::toFloat
double toDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
//! \brief Return \c ldouble numeric value of string
//! \details Example: \snippet pistring.cpp PIString::toFloat
ldouble toLDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
//inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
PIString & setNumber(const llong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
PIString & setNumber(const ullong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::setFloat
PIString & setNumber(const float value) {clear(); *this += ftos(value); return *this;}
PIString & setNumber(const double value) {clear(); *this += dtos(value); return *this;}
PIString & setNumber(const ldouble value) {clear(); *this += dtos(value); return *this;}
PIString & setReadableSize(long bytes);
//! \brief Set string content to numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::setFloat
PIString & setNumber(const double & value) {clear(); *this += dtos(value); return *this;}
//! \brief Set string content to numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::setFloat
PIString & setNumber(const ldouble & value) {clear(); *this += dtos(value); return *this;}
//! \brief Set string content to human readable size in B/kB/MB/GB/TB
//! \details Example: \snippet pistring.cpp PIString::setReadableSize
PIString & setReadableSize(llong bytes);
//inline static PIString fromNumber(const char value) {return PIString(itos(value));}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
static PIString fromNumber(const llong value, int base = 10, bool * ok = 0) {return fromNumberBase(value, base, ok);}
static PIString fromNumber(const ullong value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBase(value, base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::fromFloat
static PIString fromNumber(const float value) {return PIString(ftos(value));}
static PIString fromNumber(const double value) {return PIString(dtos(value));}
static PIString fromNumber(const ldouble value) {return PIString(dtos(value));}
//! \brief Return string contains numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::fromFloat
static PIString fromNumber(const double & value) {return PIString(dtos(value));}
//! \brief Return string contains numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::fromFloat
static PIString fromNumber(const ldouble & value) {return PIString(dtos(value));}
//! \brief Return "true" or "false"
static PIString fromBool(const bool value) {return PIString(value ? "true" : "false");}
static PIString readableSize(long bytes) {PIString s; s.setReadableSize(bytes); return s;}
//! \brief Return string contains human readable size in B/kB/MB/GB/TB
//! \details Example: \snippet pistring.cpp PIString::readableSize
static PIString readableSize(llong bytes) {PIString s; s.setReadableSize(bytes); return s;}
private:
static const char toBaseN[];
@@ -254,45 +627,92 @@ private:
wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;}
#endif
PIByteArray data_;
mutable PIByteArray data_;
//string std_string;
//wstring std_wstring;
};
//! \relatesalso PIString \brief Output operator to std::ostream (cout)
inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
//! \relatesalso PIString \brief Input operator from std::istream (cin)
inline std::istream & operator >>(std::istream & s, PIString & v) {string ss; s >> ss; v << PIString(ss); return s;}
//! \relatesalso PIString \relatesalso PICout \brief Output operator to PICout
inline PICout operator <<(PICout s, const PIString & v) {s.space(); s.quote(); s.setControl(0, true); for (int i = 0; i < v.length(); ++i) s << v[i]; s.restoreControl(); s.quote(); return s;}
//! \relatesalso PIString \relatesalso PIByteArray \brief Output operator to PIByteArray
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.size_s(); for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
//! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;}
//inline PIString operator +(const PIString & f, const char c) {PIString s(f); s.push_back(c); return s;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const PIString & f, const string & str) {PIString s(f); s += str; return s;}
//inline PIString operator +(const char c, const PIString & f) {return PIString(c) + f;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const string & str, const PIString & f) {return PIString(str) + f;}
inline char chrUpr(char c);
inline char chrLwr(char c);
class PIStringList: public PIVector<PIString>
/*!\brief Strings array class
* \details This class is based on \a PIVector<PIString> and
* expand it functionality. */
class PIP_EXPORT PIStringList: public PIVector<PIString>
{
public:
//! Contructs empty strings list
PIStringList() {;}
//! Contructs strings list with one string "str"
PIStringList(const PIString & str) {push_back(str);}
//! Contructs empty strings list with strings "s0" and "s1"
PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);}
//! Contructs empty strings list with strings "s0", "s1" and "s2"
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);}
//! Contructs empty strings list with strings "s0", "s1", "s2" and "s3"
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);}
//! \brief Join all strings in one with delimiter "delim" and return it
//! \details Example: \snippet pistring.cpp PIStringList::join
PIString join(const PIString & delim) const {PIString s; for (uint i = 0; i < size(); ++i) {s += at(i); if (i < size() - 1) s += delim;} return s;}
//! \brief Remove all strings equal "value" and return this
//! \details Example: \snippet pistring.cpp PIStringList::removeStrings
PIStringList & removeStrings(const PIString & value) {for (uint i = 0; i < size(); ++i) {if (at(i) == value) {remove(i); --i;}} return *this;}
PIStringList & remove(uint num) {PIVector<PIString>::remove(num); return *this;}
PIStringList & remove(uint num, uint count) {PIVector<PIString>::remove(num, count); return *this;}
//! \brief Remove duplicated strings and return this
//! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates
PIStringList & removeDuplicates();
//! Return sum of lengths of all strings
uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;}
PIStringList & operator <<(const PIString & str) {push_back(str); return *this;}
@@ -308,6 +728,10 @@ public:
};
//! \relatesalso PIStringList \brief Output operator to std::ostream (cout)
inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << '\"' << v[i] << '\"'; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
//! \relatesalso PIStringList \relatesalso PICout \brief Output operator to PICout
inline PICout operator <<(PICout s, const PIStringList & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << '\"' << v[i] << '\"'; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
#endif // PISTRING_H

View File

@@ -42,7 +42,7 @@ bool PISystemMonitor::startOnProcess(int pID) {
file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIIODevice::ReadOnly);
filem.open("/proc/" + PIString::fromNumber(pID_) + "/statm", PIIODevice::ReadOnly);
if (!file.isOpened()) {
piCout << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!" << endl;
piCout << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!";
return false;
}
cycle = -1;

View File

@@ -23,7 +23,7 @@
#include "pithread.h"
#include "piprocess.h"
class PISystemMonitor: public PIThread
class PIP_EXPORT PISystemMonitor: public PIThread
{
public:
PISystemMonitor();

View File

@@ -23,9 +23,9 @@
#include "piconfig.h"
namespace PISystemTests {
extern long time_resolution_ns;
extern long time_elapsed_ns;
extern long usleep_offset_us;
PIP_EXPORT extern long time_resolution_ns;
PIP_EXPORT extern long time_elapsed_ns;
PIP_EXPORT extern long usleep_offset_us;
class PISystemTestReader {
public:

View File

@@ -31,6 +31,36 @@ void piUSleep(int usecs) {
}
/*! \class PIThread
* \brief Thread class
* \details This class allow you exec your code in separate thread.
*
* \section PIThread_sec0 Synopsis
* Multithread .
*
* \section PIThread_sec1 To/from data convertions
* Most common constructor is \a PIThread(const char * str), where "str"
* is null-terminated string, e.g. \c "string". This is 7 chars with last char = 0.
* Also you can constructs \a PIThread from single \a PIChar, \a PIByteArray,
* other \a PIThread or sequency of the same characters with custom length.\n \n
* This class has implicit conversions to <tt>const char * </tt> and
* \c std::string. Also there are functions to make same convertions:
* * \a data() - to <tt>const char * </tt>,
* * \a stdString() - to \c std::string,
* * \a toByteArray() - to \a PIByteArray.
*
* \section PIThread_sec2 Numeric operations
* You can get symbolic representation of any numeric value with function
* \a setNumber(any integer value, int base = 10, bool * ok = 0). Default
* arguments are set for decimal base system, but you can choose any system
* from 2 to 40. There are the same static functions \a fromNumber(), that
* returns \a PIThread. \n
* Also there is function \a setReadableSize() which is set human-readable
* size in bytes, Kb, Mb, Gb or Pb. Static analog is \a readableSize().
*
*/
PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay): PIObject() {
piMonitor.threads++;
data_ = data;
@@ -58,12 +88,14 @@ PIThread::~PIThread() {
#ifndef WINDOWS
pthread_cancel(thread);
#else
TerminateThread(thread, 0);
CloseHandle(thread);
#endif
}
bool PIThread::start(int timer_delay) {
if (running) return false;
terminating = running = false;
timer = timer_delay;
#ifndef WINDOWS
@@ -88,6 +120,7 @@ bool PIThread::start(int timer_delay) {
bool PIThread::startOnce() {
if (running) return false;
terminating = running = false;
#ifndef WINDOWS
pthread_attr_t attr;
@@ -110,13 +143,13 @@ bool PIThread::startOnce() {
}
void PIThread::terminate(bool hard) {
void PIThread::terminate() {
if (thread == 0) return;
running = false;
#ifndef WINDOWS
if (hard) kill((ullong)thread, SIGKILL);
else pthread_cancel(thread);
pthread_cancel(thread);
#else
TerminateThread(thread, 0);
CloseHandle(thread);
#endif
thread = 0;
@@ -125,6 +158,10 @@ void PIThread::terminate(bool hard) {
void * PIThread::thread_function(void * t) {
#ifndef WINDOWS
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
#endif
PIThread & ct = *((PIThread * )t);
ct.running = true;
ct.begin();
@@ -150,6 +187,10 @@ void * PIThread::thread_function(void * t) {
void * PIThread::thread_function_once(void * t) {
#ifndef WINDOWS
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
#endif
PIThread & ct = *((PIThread * )t);
ct.running = true;
ct.begin();

View File

@@ -1,3 +1,8 @@
/*! \file pithread.h
* \brief Thread
*
* This file declare thread class and some wait functions
*/
/*
PIP - Platform Independent Primitives
Thread
@@ -24,37 +29,49 @@
#include "pimutex.h"
#include "piobject.h"
#ifdef DOXYGEN
//! \brief Sleep for "msecs" milliseconds
void msleep(int msecs);
#else
# ifdef WINDOWS
inline void msleep(int msecs) {Sleep(msecs);}
# else
inline void msleep(int msecs) {usleep(msecs * 1000);}
# endif
#endif
/*! \brief Precise sleep for "usecs" microseconds
* \details This function consider \c "usleep" offset
* on QNX/Linux/Mac, which is calculated with
* \a pip_sys_test program. If there is correct
* offset value in system config, this function
* wait \b exactly "usecs" microseconds. */
void piUSleep(int usecs); // on !Windows consider constant "usleep" offset
/*! \brief Precise sleep for "msecs" milliseconds
* \details This function exec \a piUSleep (msecs * 1000). */
inline void piMSleep(int msecs) {piUSleep(msecs * 1000);} // on !Windows consider constant "usleep" offset
typedef void (*ThreadFunc)(void * );
/// events:
/// void started()
/// void stopped()
///
/// handlers:
/// bool start(int timer_delay = -1)
/// bool start(ThreadFunc func, int timer_delay = -1)
/// bool startOnce()
/// bool startOnce(ThreadFunc func)
/// void stop(bool wait = false)
/// void terminate(bool hard = false)
/// bool waitForStart(int timeout_msecs = -1)
/// bool waitForFinish(int timeout_msecs = -1)
/// void lock()
/// void unlock()
class PIThread: public PIObject {
class PIP_EXPORT PIThread: public PIObject
{
PIOBJECT(PIThread)
public:
PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1);
PIThread(bool startNow = false, int timer_delay = -1);
virtual ~PIThread();
#ifdef DOXYGEN
//! Priority of thread
enum Priority {piHighest /** Highest */,
piHigh /** High */,
piNormal /** Normal, default */,
piLow /** Low */,
piLowerst /** Lowest */
};
#else
# ifdef QNX
enum Priority {piHighest = 12,
piHigh = 11,
@@ -67,43 +84,133 @@ public:
piNormal = 0,
piLow = 1,
piLowerst = 2 };
# endif
#endif
//bool start(int timer_delay = -1);
EVENT_HANDLER0(PIThread, bool, start) {return start(-1);}
EVENT_HANDLER1(PIThread, bool, start, int, timer_delay);
EVENT_HANDLER1(PIThread, bool, start, ThreadFunc, func) {ret_func = func; return start(-1);}
EVENT_HANDLER2(PIThread, bool, start, ThreadFunc, func, int, timer_delay) {ret_func = func; return start(timer_delay);}
EVENT_HANDLER0(PIThread, bool, startOnce);
EVENT_HANDLER1(PIThread, bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();}
EVENT_HANDLER0(PIThread, void, stop) {stop(false);}
EVENT_HANDLER1(PIThread, void, stop, bool, wait) {terminating = true; if (wait) waitForFinish();}
EVENT_HANDLER0(PIThread, void, terminate) {terminate(false);}
EVENT_HANDLER1(PIThread, void, terminate, bool, hard);
EVENT_HANDLER0(bool, start) {return start(-1);}
EVENT_HANDLER1(bool, start, int, timer_delay);
EVENT_HANDLER1(bool, start, ThreadFunc, func) {ret_func = func; return start(-1);}
EVENT_HANDLER2(bool, start, ThreadFunc, func, int, timer_delay) {ret_func = func; return start(timer_delay);}
EVENT_HANDLER0(bool, startOnce);
EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();}
EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, wait) {terminating = true; if (wait) waitForFinish();}
EVENT_HANDLER0(void, terminate);
//! \brief Set common data passed to external function
void setData(void * d) {data_ = d;}
//! \brief Set external function that will be executed after every \a run()
void setSlot(ThreadFunc func) {ret_func = func;}
//! \brief Set priority of thread
void setPriority(PIThread::Priority prior);
//! \brief Return priority of thread
PIThread::Priority priority() const {return priority_;}
//! \brief Return \c true if thread is running
bool isRunning() const {return running;}
EVENT_HANDLER0(PIThread, bool, waitForFinish) {return waitForFinish(-1);}
EVENT_HANDLER1(PIThread, bool, waitForFinish, int, timeout_msecs);
EVENT_HANDLER0(PIThread, bool, waitForStart) {return waitForStart(-1);}
EVENT_HANDLER1(PIThread, bool, waitForStart, int, timeout_msecs);
bool isStopping() const {return running && terminating;}
EVENT_HANDLER0(bool, waitForStart) {return waitForStart(-1);}
EVENT_HANDLER1(bool, waitForStart, int, timeout_msecs);
EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);}
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs);
//! \brief Set necessity of lock every \a run with internal mutex
void needLockRun(bool need) {lockRun = need;}
EVENT_HANDLER0(PIThread, void, lock) {mutex_.lock();}
EVENT_HANDLER0(PIThread, void, unlock) {mutex_.unlock();}
EVENT_HANDLER0(void, lock) {mutex_.lock();}
EVENT_HANDLER0(void, unlock) {mutex_.unlock();}
//! \brief Return internal mutex
PIMutex & mutex() {return mutex_;}
EVENT(PIThread, started)
EVENT(PIThread, stopped)
EVENT(started)
EVENT(stopped)
//! \handlers
//! \{
/** \fn bool start(int timer_delay = -1)
* \brief Start thread
* \details Start execution of \a run() in internal loop with
* "timer_delay" delay in milliseconds. If "timer_delay" <= 0
* there is no delay in loop. Thread also exec external function
* set by \a setSlot() if it`s not null
*
* \return \c false if thread already started or can`t start thread */
/** \fn bool start(ThreadFunc func, int timer_delay = -1)
* \brief Start thread
* \details Overloaded function. Set external function "func" before start
*
* \return \c false if thread already started or can`t start thread */
/** \fn bool startOnce()
* \brief Start thread without internal loop
* \details Start execution of \a run() once. Thread also exec
* external function set by \a setSlot() if it`s not null
*
* \return \c false if thread already started or can`t start thread */
/** \fn bool startOnce(ThreadFunc func)
* \brief Start thread without internal loop
* \details Overloaded function. Set external function "func" before start
*
* \return \c false if thread already started or can`t start thread */
/** \fn void stop(bool wait = false)
* \brief Stop thread
* \details Stop execution of thread and wait for it finish
* if "wait" is \c true. This function can block for infinite
* time if "wait" is \c true and any of thread function is
* busy forever */
/** \fn void terminate()
* \brief Strongly stop thread
* \details Stop execution of thread immediately */
/** \fn bool waitForStart(int timeout_msecs = -1)
* \brief Wait for thread start
* \details This function block until thread finish for "timeout_msecs"
* or forever if "timeout_msecs" < 0
*
* \return \c false if timeout is exceeded */
/** \fn bool waitForFinish(int timeout_msecs = -1)
* \brief Wait for thread finish
* \details This function block until thread start for "timeout_msecs"
* or forever if "timeout_msecs" < 0
*
* \return \c false if timeout is exceeded */
//! \fn void lock()
//! \brief Lock internal mutex
//! \fn void unlock()
//! \brief Unlock internal mutex
//! \}
//! \events
//! \{
//! \fn void started()
//! \brief Raise on thread start
//! \fn void stopped()
//! \brief Raise on thread stop
//! \}
protected:
static void * thread_function(void * t);
static void * thread_function_once(void * t);
virtual void begin() {;} // executed at start
virtual void run() {;} // main loop executed with "timer_delay" timeout
virtual void end() {;} // executed at finish
virtual void begin() {;}
virtual void run() {;}
virtual void end() {;}
volatile bool terminating, running, lockRun;
int timer, policy;

View File

@@ -20,6 +20,73 @@
#include "pitimer.h"
#include "pisystemtests.h"
bool operator ==(const PITime & t0, const PITime & t1) {
return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
}
bool operator <(const PITime & t0, const PITime & t1) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds < t1.seconds;
} else return t0.minutes < t1.minutes;
} else return t0.hours < t1.hours;
}
bool operator >(const PITime & t0, const PITime & t1) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds > t1.seconds;
} else return t0.minutes > t1.minutes;
} else return t0.hours > t1.hours;
}
bool operator ==(const PIDate & t0, const PIDate & t1) {
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day);
}
bool operator <(const PIDate & t0, const PIDate & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
return t0.day < t1.day;
} else return t0.month < t1.month;
} else return t0.year < t1.year;
}
bool operator >(const PIDate & t0, const PIDate & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
return t0.day > t1.day;
} else return t0.month > t1.month;
} else return t0.year > t1.year;
}
bool operator ==(const PIDateTime & t0, const PIDateTime & t1) {
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day &&
t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
}
bool operator <(const PIDateTime & t0, const PIDateTime & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
if (t0.day == t1.day) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds < t1.seconds;
} else return t0.minutes < t1.minutes;
} else return t0.hours < t1.hours;
} else return t0.day < t1.day;
} else return t0.month < t1.month;
} else return t0.year < t1.year;
}
bool operator >(const PIDateTime & t0, const PIDateTime & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
if (t0.day == t1.day) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds > t1.seconds;
} else return t0.minutes > t1.minutes;
} else return t0.hours > t1.hours;
} else return t0.day > t1.day;
} else return t0.month > t1.month;
} else return t0.year > t1.year;
}
#ifdef PIP_TIMER_RT
PITimer::TimerPool * pool = 0;
@@ -34,17 +101,20 @@ PITimer::PITimer(TimerEvent slot, void * data_, bool threaded_)
#endif
ret_func = slot;
data = data_;
running_ = false;
interval_ = 0.;
#ifdef PIP_TIMER_RT
piMonitor.timers++;
ti = -1;
threaded = threaded_;
running = false;
memset(&se, 0, sizeof(se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = this;
se.sigev_notify_function = PITimer::timer_event;
se.sigev_notify_attributes = 0;
lockRun = false;
#else
deferred_ = false;
#endif
reset();
}
@@ -58,17 +128,20 @@ PITimer::PITimer(bool threaded_)
#endif
ret_func = 0;
data = 0;
running_ = false;
interval_ = 0.;
#ifdef PIP_TIMER_RT
piMonitor.timers++;
ti = -1;
threaded = threaded_;
running = false;
memset(&se, 0, sizeof(se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = this;
se.sigev_notify_function = PITimer::timer_event;
se.sigev_notify_attributes = 0;
lockRun = false;
#else
deferred_ = false;
#endif
reset();
}
@@ -84,14 +157,15 @@ PITimer::~PITimer() {
#ifdef PIP_TIMER_RT
void PITimer::start(double msecs) {
if (ti != -1 || msecs < 0 || running) return;
if (ti != -1 || msecs < 0 || running_) return;
interval_ = msecs;
if (!threaded) {
ticks = int(msecs);
if (pool == 0) pool = new TimerPool();
pool->add(this);
//cout << "not threaded timer start " << msecs << " msecs\n";
if (!pool->isRunning()) pool->start();
running = true;
running_ = true;
return;
}
spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000;
@@ -100,16 +174,17 @@ void PITimer::start(double msecs) {
ti = timer_create(CLOCK_REALTIME, &se, &timer);
//cout << "***create timer " << msecs << " msecs\n";
if (ti == -1) {
piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString() << endl;
piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString();
return;
}
timer_settime(timer, 0, &spec, 0);
running = true;
running_ = true;
}
void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
if (ti != -1 || interval_msecs < 0 || running) return;
if (ti != -1 || interval_msecs < 0 || running_) return;
interval_ = interval_msecs;
spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000;
spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000);
spec.it_value.tv_nsec = ((int)(delay_msecs * 1000) % 1000000) * 1000;
@@ -117,16 +192,17 @@ void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
ti = timer_create(CLOCK_REALTIME, &se, &timer);
//cout << "***create timer\n";
if (ti == -1) {
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString() << endl;
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
return;
}
timer_settime(timer, 0, &spec, 0);
running = true;
running_ = true;
}
void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) {
if (ti != -1 || interval_msecs < 0 || running) return;
if (ti != -1 || interval_msecs < 0 || running_) return;
interval_ = interval_msecs;
spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000;
spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000);
struct tm dtm;
@@ -142,11 +218,11 @@ void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_date
ti = timer_create(CLOCK_REALTIME, &se, &timer);
//cout << "***create timer\n";
if (ti == -1) {
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString() << endl;
piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
return;
}
timer_settime(timer, TIMER_ABSTIME, &spec, 0);
running = true;
running_ = true;
}
@@ -170,7 +246,7 @@ void PITimer::TimerPool::begin() {
sa.sa_handler = empty_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGALRM, &sa, 0) == -1) {
piCout << "[PITimer] sigaction error: " << errorString() << endl;
piCout << "[PITimer] sigaction error: " << errorString();
stop();
return;
}*/
@@ -184,12 +260,12 @@ void PITimer::TimerPool::begin() {
spec.it_value = spec.it_interval;
//cout << "***create pool timer\n";
if (timer_create(CLOCK_REALTIME, &se, &timer) == -1) {
piCout << "[PITimer] Can`t create timer for pool: " << errorString() << endl;
piCout << "[PITimer] Can`t create timer for pool: " << errorString();
stop();
return;
}
if (timer_settime(timer, 0, &spec, 0) == -1) {
piCout << "[PITimer] Can`t set timer for pool: " << errorString() << endl;
piCout << "[PITimer] Can`t set timer for pool: " << errorString();
stop();
return;
}
@@ -221,8 +297,8 @@ void PITimer::TimerPool::run() {
void PITimer::stop() {
if (!running) return;
running = false;
if (!running_) return;
running_ = false;
if (!threaded) {
if (pool != 0) {
pool->remove(this);
@@ -231,12 +307,13 @@ void PITimer::stop() {
}
if (ti != -1) timer_delete(timer);
ti = -1;
interval_ = 0.;
}
void PITimer::timer_event(sigval e) {
PITimer * ct = (PITimer * )e.sival_ptr;
if (!ct->running) return;
if (!ct->running_) return;
if (ct->lockRun) ct->lock();
if (ct->ret_func != 0) ct->ret_func(ct->data, 1);
ct->timeout(ct->data, 1);
@@ -255,12 +332,12 @@ void PITimer::timer_event(sigval e) {
bool PITimer::waitForFinish(int timeout_msecs) {
if (timeout_msecs < 0) {
while (running)
while (running_)
msleep(1);
return true;
}
int cnt = 0;
while (running && cnt < timeout_msecs) {
while (running_ && cnt < timeout_msecs) {
msleep(1);
++cnt;
}
@@ -270,18 +347,65 @@ bool PITimer::waitForFinish(int timeout_msecs) {
#else
void PITimer::start(double msecs) {
if (msecs < 0 || running) return;
if (msecs < 0 || running_) return;
interval_ = msecs;
inc_time = PISystemTime::fromMilliseconds(msecs);
st_time = currentSystemTime() + inc_time;
deferred_ = false;
running_ = true;
PIThread::start();
}
void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
//piCout << "defStart exec with" << delay_msecs << interval_msecs;
if (interval_msecs < 0 || running_) return;
interval_ = interval_msecs;
PISystemTime cst = currentSystemTime();
inc_time = PISystemTime::fromMilliseconds(interval_msecs);
st_time = currentSystemTime() + PISystemTime::fromMilliseconds(delay_msecs);
if (st_time < cst) st_time = cst;
running_ = deferred_ = true;
PIThread::start();
//piCout << "timer start def";
}
void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) {
//piCout << "defStart exec to" << start_datetime.toString() << interval_msecs;
if (interval_msecs < 0 || running_) return;
interval_ = interval_msecs;
PISystemTime cst = currentSystemTime();
inc_time = PISystemTime::fromMilliseconds(interval_msecs);
st_time = start_datetime.toSystemTime();
if (st_time < cst) st_time = cst;
running_ = deferred_ = true;
PIThread::start();
//piCout << "timer start def";
}
void PITimer::run() {
if (!running) return;
if (!running_) return;
while (deferred_) {
PISystemTime tst = st_time - currentSystemTime();
if (tst.seconds > 0) {
piMSleep(100);
if (!running_) return;
continue;
}
if (tst.nanoseconds > 100000000) {
piMSleep(100);
if (!running_) return;
continue;
}
tst.sleep();
deferred_ = false;
if (!running_) return;
}
(st_time - currentSystemTime()).sleep();
st_time += inc_time;
if (lockRun) lock();
//if (lockRun) lock();
if (ret_func != 0) ret_func(data, 1);
timeout(data, 1);
tick(data, 1);
@@ -293,7 +417,7 @@ void PITimer::run() {
timeout(data, i.delim);
tick(data, i.delim);
}
if (lockRun) unlock();
//if (lockRun) unlock();
}
#endif
@@ -524,7 +648,7 @@ PISystemTime currentSystemTime() {
}
PIString PITime::toString(const PIString & format) {
PIString PITime::toString(const PIString & format) const {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(hours));
@@ -532,11 +656,14 @@ PIString PITime::toString(const PIString & format) {
ts.replace("m", PIString::fromNumber(minutes));
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(seconds));
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
ts.replace("z", PIString::fromNumber(milliseconds));
return ts;
}
PIString PIDate::toString(const PIString & format) {
PIString PIDate::toString(const PIString & format) const {
PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).right(2));
@@ -549,14 +676,8 @@ PIString PIDate::toString(const PIString & format) {
}
PIString PIDateTime::toString(const PIString & format) {
PIString PIDateTime::toString(const PIString & format) const {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(hours));
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(minutes));
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(seconds));
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).right(2));
ts.replace("y", PIString::fromNumber(year).right(1));
@@ -564,10 +685,45 @@ PIString PIDateTime::toString(const PIString & format) {
ts.replace("M", PIString::fromNumber(month));
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(day));
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(hours));
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(minutes));
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(seconds));
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
ts.replace("z", PIString::fromNumber(milliseconds));
return ts;
}
time_t PIDateTime::toSecondSinceEpoch() const {
tm pt;
pt.tm_sec = seconds;
pt.tm_min = minutes;
pt.tm_hour = hours;
pt.tm_mday = day;
pt.tm_mon = month - 1;
pt.tm_year = year - 1900;
return mktime(&pt);
}
PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) {
tm * pt = localtime(&sec);
PIDateTime dt;
dt.seconds = pt->tm_sec;
dt.minutes = pt->tm_min;
dt.hours = pt->tm_hour;
dt.day = pt->tm_mday;
dt.month = pt->tm_mon + 1;
dt.year = pt->tm_year + 1900;
return dt;
}
PIString time2string(const PITime & time, const PIString & format) {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0'));

121
pitimer.h
View File

@@ -28,7 +28,7 @@
typedef void (*TimerEvent)(void * , int );
class PISystemTime {
class PIP_EXPORT PISystemTime {
public:
PISystemTime() {seconds = nanoseconds = 0;}
PISystemTime(long s, long ns) {seconds = s; nanoseconds = ns; checkOverflows();}
@@ -71,29 +71,65 @@ private:
inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PISystemTime & v) {s >> v.seconds >> v.nanoseconds; return s;}
struct PITime {
struct PIP_EXPORT PITime {
PITime() {hours = minutes = seconds = milliseconds = 0;}
int milliseconds;
int seconds;
int minutes;
int hours;
PIString toString(const PIString & format = "h:mm:ss");
PIString toString(const PIString & format = "h:mm:ss") const;
};
PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1);
PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1);
PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1);
inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);}
inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);}
inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);}
struct PIDate {
struct PIP_EXPORT PIDate {
PIDate() {year = month = day = 0;}
int day;
int month;
int year;
PIString toString(const PIString & format = "d.MM.yyyy");
PIString toString(const PIString & format = "d.MM.yyyy") const;
};
PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1);
PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1);
PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1);
inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);}
inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);}
inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);}
struct PIDateTime {
struct PIP_EXPORT PIDateTime {
PIDateTime() {year = month = day = hours = minutes = seconds = 0;}
PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;}
PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
int milliseconds;
int seconds;
int minutes;
int hours;
int day;
int month;
int year;
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy");
PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());}
void normalize() {*this = normalized();}
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const;
time_t toSecondSinceEpoch() const;
PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);}
void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();}
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
static PIDateTime fromSecondSinceEpoch(const time_t sec);
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
};
inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();}
inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();}
PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1);
PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1);
PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1);
inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);}
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
/// events:
/// void timeout(void * data, int delimiter)
@@ -108,13 +144,14 @@ struct PIDateTime {
/// void clearDelimiters()
/// void lock()
/// void unlock()
class PITimer
class PIP_EXPORT PITimer
#ifndef PIP_TIMER_RT
: public PIThread
#else
: public PIObject
#endif
{
PIOBJECT(PITimer)
public:
PITimer(TimerEvent slot = 0, void * data = 0, bool threaded = true);
PITimer(bool threaded);
@@ -122,53 +159,53 @@ public:
void setData(void * data_) {data = data_;}
void setSlot(TimerEvent slot) {ret_func = slot;}
double interval() const {return interval_;}
#ifndef PIP_TIMER_RT
# ifdef WINDOWS
EVENT_HANDLER0(PITimer, void, reset) {t_st = GetCurrentTime();}
EVENT_HANDLER1(PIThread, bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
EVENT_HANDLER1(PITimer, void, start, double, msecs);
EVENT_HANDLER0(void, reset) {t_st = GetCurrentTime();}
# elif defined(MAC_OS)
EVENT_HANDLER0(PITimer, void, reset) {clock_get_time(__pi_mac_clock, &t_st);}
EVENT_HANDLER1(PIThread, bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
EVENT_HANDLER1(PITimer, void, start, double, msecs);
EVENT_HANDLER0(void, reset) {clock_get_time(__pi_mac_clock, &t_st);}
# else
EVENT_HANDLER0(PITimer, void, reset) {clock_gettime(0, &t_st);}
EVENT_HANDLER1(PIThread, bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
EVENT_HANDLER1(PITimer, void, start, double, msecs);
EVENT_HANDLER0(void, reset) {clock_gettime(0, &t_st);}
# endif
EVENT_HANDLER1(bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
EVENT_HANDLER1(void, start, double, msecs);
EVENT_HANDLER0(void, stop) {running_ = false;}
EVENT_HANDLER2(void, deferredStart, double, interval_msecs, double, delay_msecs);
EVENT_HANDLER2(void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime);
#else
EVENT_HANDLER0(PITimer, void, reset) {clock_gettime(0, &t_st);}
EVENT_HANDLER1(PITimer, void, start, double, msecs);
EVENT_HANDLER2(PITimer, void, deferredStart, double, interval_msecs, double, delay_msecs);
EVENT_HANDLER2(PITimer, void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime);
EVENT_HANDLER0(PITimer, void, stop);
EVENT_HANDLER0(PITimer, bool, waitForFinish) {return waitForFinish(-1);}
EVENT_HANDLER1(PITimer, bool, waitForFinish, int, timeout_msecs);
bool isRunning() const {return running;}
EVENT_HANDLER0(void, reset) {clock_gettime(0, &t_st);}
EVENT_HANDLER1(void, start, double, msecs);
EVENT_HANDLER2(void, deferredStart, double, interval_msecs, double, delay_msecs);
EVENT_HANDLER2(void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime);
EVENT_HANDLER0(void, stop);
EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);}
EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs);
bool isRunning() const {return running_;}
void needLockRun(bool need) {lockRun = need;}
EVENT_HANDLER0(PITimer, void, lock) {mutex_.lock();}
EVENT_HANDLER0(PITimer, void, unlock) {mutex_.unlock();}
EVENT_HANDLER0(void, lock) {mutex_.lock();}
EVENT_HANDLER0(void, unlock) {mutex_.unlock();}
#endif
void addDelimiter(int delim, TimerEvent slot = 0) {ret_funcs << TimerSlot(slot, delim);}
void removeDelimiter(int delim) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}}
void removeDelimiter(TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot) {ret_funcs.remove(i); i--;}}
void removeDelimiter(int delim, TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot && ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}}
EVENT_HANDLER0(PITimer, void, clearDelimiters) {ret_funcs.clear();}
EVENT_HANDLER0(void, clearDelimiters) {ret_funcs.clear();}
double elapsed_n(); // nanoseconds
double elapsed_u(); // microseconds
double elapsed_m(); // miliseconds
double elapsed_m(); // milliseconds
double elapsed_s(); // seconds
double reset_time_n(); // nanoseconds
double reset_time_u(); // microseconds
double reset_time_m(); // miliseconds
double reset_time_m(); // milliseconds
double reset_time_s(); // seconds
PISystemTime reset_time();
static double elapsed_system_n(); // nanoseconds
static double elapsed_system_u(); // microseconds
static double elapsed_system_m(); // miliseconds
static double elapsed_system_m(); // milliseconds
static double elapsed_system_s(); // seconds
@@ -200,7 +237,7 @@ public:
int ticks;
#endif
EVENT2(PITimer, timeout, void * , data, int, delimiter)
EVENT2(timeout, void * , data, int, delimiter)
protected:
virtual void tick(void * data, int delimiter) {;}
@@ -208,10 +245,12 @@ protected:
private:
#ifndef PIP_TIMER_RT
void run();
void end() {interval_ = 0.;}
PISystemTime st_time, inc_time;
bool deferred_;
#else
bool running, threaded;
bool threaded;
volatile bool lockRun;
PIMutex mutex_;
int ti;
@@ -219,6 +258,8 @@ private:
timer_t timer;
sigevent se;
#endif
bool running_;
double interval_;
#ifdef WINDOWS
long
@@ -246,12 +287,12 @@ private:
extern PITimer::TimerPool * pool;
#endif
PITime currentTime();
PIDate currentDate();
PIDateTime currentDateTime();
PISystemTime currentSystemTime();
PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead
PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead
PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead
PIP_EXPORT PITime currentTime();
PIP_EXPORT PIDate currentDate();
PIP_EXPORT PIDateTime currentDateTime();
PIP_EXPORT PISystemTime currentSystemTime();
PIP_EXPORT PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead
PIP_EXPORT PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead
PIP_EXPORT PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead
#endif // PITIMER_H

View File

@@ -22,7 +22,7 @@
#include "piconfig.h"
class PIVariant {
class PIP_EXPORT PIVariant {
friend class PIVariable;
public:
enum Type {Bool, Char, Short, Int, Long, LLong, UChar, UShort, UInt, ULong, ULLong, Float, Double, LDouble, String, StringList};
@@ -128,7 +128,7 @@ private:
inline std::ostream & operator <<(std::ostream & s, const PIVariant & v) {s << v.typeName() << ": " << v.stringValue(); return s;}
class PIVariable {
class PIP_EXPORT PIVariable {
public:
PIVariable() {;}
PIVariable(const PIString & str) {setVariable(str);}
@@ -169,7 +169,7 @@ private:
* "double value = struct["pi"].value();"
*/
class PIStruct {
class PIP_EXPORT PIStruct {
public:
PIStruct() {;}
PIStruct(const PIString & str) {parseFile(str);}
@@ -193,8 +193,3 @@ private:
};
#endif // PIVARIABLE_H
#/** PhEDIT attribute block
#-11:16777215
#0:7338:monospace10:-3:-3:0
#** PhEDIT attribute block ends (-0000117)**/