15.10.2012 - version 0.2.0 - PIIODevice - base of file, ethernet, serial and packets extractor. PIEthernet now support also TCP (client and server). PIConsole now can align labels in each column individually.

This commit is contained in:
peri4
2012-10-15 23:36:18 +04:00
parent 5558add03e
commit cfc5eed75e
64 changed files with 1879 additions and 867 deletions

View File

@@ -2,14 +2,17 @@
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00p\x00i\x00p)
[CMake]
BuildDirs=/home/peri4/pprojects/pip/
Build Directory Count=1
CMakeDir=/usr/share/cmake/Modules
Current CMake Binary=file:///usr/bin/cmake
CurrentBuildDir=file:///home/peri4/pprojects/pip/
CurrentBuildType=Debug
CurrentInstallDir=
Current Build Directory Index=0
ProjectRootRelative=./
[CMake][CMake Build Directory 0]
Build Directory Path=file:///home/peri4/pprojects/pip/
Build Type=
CMake Binary=file:///usr/bin/cmake
Install Directory=file:///usr/local
[Launch]
Launch Configurations=Launch Configuration 0
@@ -24,15 +27,15 @@ Arguments=
Dependencies=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00p\x00i\x00p)
Dependency Action=Build
EnvironmentGroup=default
Executable=
Executable=file:///home/peri4/pprojects/pip/pip_test
External Terminal=konsole --noclose --workdir %workdir -e %exe
Project Target=pip,pip_test
Project Target=
Use External Terminal=false
Working Directory=
isExecutable=false
isExecutable=true
[MakeBuilder]
Number Of Jobs=5
Number Of Jobs=8
[Project]
VersionControlSupport=kdevgit

View File

@@ -1,6 +1,7 @@
project(pip)
find_package(Qt4)
cmake_minimum_required(VERSION 2.6)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} .)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} . ${QT_INCLUDES})
file(GLOB CPPS "pi*.cpp")
if (${WIN32})
add_definitions(-Wall -O2)
@@ -17,5 +18,5 @@ add_executable(pip_test "main.cpp")
if (${WIN32})
target_link_libraries(pip_test pthread ws2_32 pip)
else (${WIN32})
target_link_libraries(pip_test pthread rt pip)
target_link_libraries(pip_test pthread rt pip ${QT_QTCORE_LIBRARY})
endif (${WIN32})

107
main.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Test program
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -117,66 +117,67 @@ public:
};
#pragma pack(push, 1)
struct Data {
ushort header;
int counter;
float f0;
float f1;
ushort checksum;
};
#pragma pack(pop)
class Prot: public PIProtocol {
public:
Prot() {
setReceiverDevice("/dev/ttyS0", PISerial::S115200, true);
setReceiverDataHeader(&rec, 2);
setReceiverData(&rec.counter, sizeof(rec) - 2);
setSenderData(&send, sizeof(send));
setExpectedFrequency(20.f);
setSenderFrequency(20.f);
send.header = 0xAABB;
rec.header = 0xAABB;
start();
}
virtual bool validate() {
if (rec.checksum != PIByteArray(&rec, sizeof(rec)-2).checksumCRC16()) return false;
return true;
}
virtual bool aboutSend() {
send.counter++;
send.checksum = PIByteArray(&send, sizeof(send)-2).checksumCRC16();
return true;
}
Data send, rec;
struct Packet {
int from;
int to;
float data;
int cs;
};
Prot p;
bool retH(void * d, uchar * src, uchar * rec, int size) {
return (*((int*)rec)) == 1;
};
void key(char k, void*) {
switch (k) {
case '0': p.setSenderData(&p.send, sizeof(p.send)); break;
case '1': p.setSenderData(&p.send, sizeof(p.send) - 1); break;
case '2': p.send.header = 0xAABB; break;
case '3': p.send.header = 0xACBD; break;
}
}
bool retF(void * d, uchar * data, int size) {
cout << "rec " << size << endl;
return true;
};
PIConsole c(false, key);
int main(int argc, char * argv[]) {
c.enableExitCapture();
c.addVariable("prot", &p);
if (argc > 1) c.start();
c.waitForFinish();
c.stop();
/*Packet p, mp;
p.from = mp.from = 1;
p.to = mp.to = 2;
PISerial ser("/dev/ttyS0");
ser.setSpeed(PISerial::S115200);
ser.open();
ser.setReadIsBlocking(true);
PIPacketExtractor pe(&ser, &mp, 8, 8);
pe.setThreadedReadSlot(retF);
pe.setHeaderCheckSlot(retH);
pe.startThreadedRead();
ser.write(&p, sizeof(p));
p.from = 2;
ser.write(&p, sizeof(p));
msleep(1000);
exit(0);*/
PICodec codec;
exit(0);
/*
vec<int> my_v; vector<int> stl_v; QVector<int> qt_v;
double el;
PITimer tm;
tm.reset();
for (uint i = 0; i < 500000; ++i)
my_v.push_back(i);
el = tm.elapsed_m();
cout << el << endl;
tm.reset();
for (uint i = 0; i < 500000; ++i)
stl_v.push_back(i);
el = tm.elapsed_m();
cout << el << endl;
tm.reset();
for (uint i = 0; i < 500000; ++i)
qt_v.append(i);
el = tm.elapsed_m();
cout << el << endl;
exit(0);
*/
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;
@@ -239,7 +240,7 @@ int main(int argc, char * argv[]) {
else cout << "== Fail ==" << endl;
cout << endl << "== File test ==" << endl;
PIFile file(" file_test", PIFile::New | PIFile::ReadWrite);
PIFile file(" file_test", PIIODevice::ReadWrite);
cout << " file \"" << file.path() << "\" is ";
if (!file.isOpened()) cout << "not ";
cout << "opened" << endl;

2
pibitarray.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Bit array
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pibytearray.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Byte array
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

4
pibytearray.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Byte array
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -96,6 +96,8 @@ public:
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]);}
PIByteArray resized(int new_size) {PIByteArray tv(*this); tv.resize(new_size); return tv;}
PIByteArray & convertToBase64();
PIByteArray & convertFromBase64();
PIByteArray toBase64() {PIByteArray ba(*this); ba.convertToBase64(); return ba;}

2
pichar.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Unicode char
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

4
picli.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Command-Line Parser
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -69,7 +69,7 @@ void PICLI::parse() {
_args_opt << cra;
continue;
}
cout << "[PICli] Arguments overflow, \"" << cra << "\" ignored" << endl;
piCout << "[PICli] Arguments overflow, \"" << cra << "\" ignored" << endl;
}
if (last == 0 ? false : last->has_value) {
last->value = cra;

2
picli.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Command-Line Parser
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
picodec.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Text codings coder, based on "iconv"
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

6
picodec.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Text codings coder, based on "iconv"
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,8 +25,8 @@
class PICodec: private PIProcess
{
public:
PICodec(): PIProcess() {setGrabOutput(true); tf = PIFile::openTemporary(PIFile::New | PIFile::Read | PIFile::Write); tf.open();}
PICodec(const PIString & from, const PIString & to): PIProcess() {setCodings(from, to); tf = PIFile::openTemporary(PIFile::New | PIFile::Read | PIFile::Write);}
PICodec(): PIProcess() {setGrabOutput(true); tf = PIFile::openTemporary(PIIODevice::ReadWrite); tf.open();}
PICodec(const PIString & from, const PIString & to): PIProcess() {setCodings(from, to); tf = PIFile::openTemporary(PIIODevice::ReadWrite);}
~PICodec() {tf.remove();}
void setFromCoding(const PIString & from) {c_from = from;}

16
piconfig.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Config parser
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -171,13 +171,13 @@ bool PIConfig::Entry::entryExists(const Entry * e, const PIString & name) const
}
PIConfig::PIConfig(const PIString & path, PIFlags<Mode> mode): PIFile(path, mode) {
PIConfig::PIConfig(const PIString & path, PIIODevice::DeviceMode mode): PIFile(path, mode) {
delim = ".";
root.delim = delim;
empty.delim = delim;
empty._parent = 0;
if (!isOpened() && (mode[Write] || mode[New]))
open(path, Read | Write | New);
if (!isOpened())
open(path, mode);
parse();
}
@@ -233,7 +233,7 @@ void PIConfig::addEntry(const PIString & name, const PIString & value, const PIS
} else entry = te;
}
PIConfig::Branch ch = entry->_children;
std::sort(ch.begin(), ch.end(), PIConfig::Entry::compare);
ch.sort(PIConfig::Entry::compare);
te = (entry->isLeaf() ? 0 : ch.back());
ce = new Entry();
ce->delim = delim;
@@ -249,7 +249,7 @@ void PIConfig::addEntry(const PIString & name, const PIString & value, const PIS
if (toRoot) ce->_line = other.size_s() - 1;
else {
ch = entry->_parent->_children;
std::sort(ch.begin(), ch.end(), PIConfig::Entry::compare);
ch.sort(PIConfig::Entry::compare);
ce->_line = ch.back()->_line + 1;
}
}
@@ -369,8 +369,8 @@ void PIConfig::removeEntry(Branch & b, PIConfig::Entry * e) {
if (b[i] == e) found = true;
}
if (!leaf) return;
e->_parent->_children.remove(e);
b.remove(e);
e->_parent->_children.removeOne(e);
b.removeOne(e);
delete e;
}

11
piconfig.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Config parser
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -54,8 +54,8 @@ class PIConfig: public PIFile
friend class Entry;
friend class Branch;
public:
PIConfig(const PIString & path, PIFlags<Mode> mode = Read | Write);
~PIConfig() {piForeach (Entry * i, root._children) deleteEntry(i);}
PIConfig(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
~PIConfig() {piForeach (Entry * i, root._children) deleteEntry(i); close();}
class Entry;
@@ -151,7 +151,8 @@ public:
operator PIStringList() {return _value.split("%|%");}
private:
static bool compare(const PIConfig::Entry * f, const PIConfig::Entry * s) {return f->_line < s->_line;}
typedef PIConfig::Entry * EntryPtr;
static int compare(const EntryPtr * f, const EntryPtr * s) {return (*f)->_line == (*s)->_line ? 0 : (*f)->_line < (*s)->_line ? -1 : 1;}
bool entryExists(const Entry * e, const PIString & name) const;
void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;}
void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;}
@@ -196,7 +197,7 @@ public:
bool isEntryExists(const PIString & name) const {return entryExists(&root, name);}
Branch allTree() {Branch b; piForeach (Entry * i, root._children) b << i; return b;}
Branch allLeaves() {Branch b; allLeaves(b, &root); std::sort(b.begin(), b.end(), Entry::compare); return b;}
Branch allLeaves() {Branch b; allLeaves(b, &root); b.sort(Entry::compare); return b;}
int entryIndex(const PIString & name);
PIString getName(uint number) {return entryByIndex(number)._name;}

197
piconsole.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Console output/input
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@ PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() {
ret_func = slot;
num_format = 0;
cur_tab = width = height = pwidth = pheight = my = 0;
def_align = Nothing;
#ifdef WINDOWS
ulcoord.X = ulcoord.Y = 0;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -142,7 +143,7 @@ void PIConsole::stop(bool clear) {
if (clear) clearScreen();
moveTo(0, my + 4);
showCursor();
couts(fstr(Normal).stdString());
couts(fstr(Normal));
#ifdef WINDOWS
SetConsoleMode(hOut, smode);
SetConsoleTextAttribute(hOut, dattr);
@@ -243,7 +244,7 @@ PIString PIConsole::fstr(PIFlags<PIConsole::Format> f) {
#define fprint(x) switch (num_format) {case (3): return printf("%e", x); break; default: return printf("%.5g", x); break;}
#define dprint(x) switch (num_format) {case (3): return printf("%le", x); break; default: return printf("%.5lg", x); break;}
inline int PIConsole::couts(const string v) {return printf("%s", v.c_str());}
inline int PIConsole::couts(const PIString & v) {return printf("%s", v.data());}
inline int PIConsole::couts(const char * v) {return printf("%s", v);}
inline int PIConsole::couts(const bool v) {return (v ? printf("true") : printf("false"));}
inline int PIConsole::couts(const char v) {return printf("%c", v);}
@@ -289,14 +290,15 @@ void PIConsole::run() {
}
pwidth = width;
pheight = height;
col_cnt = vars().size();
col_cnt = columns().size();
col_wid = (col_cnt > 0) ? width / col_cnt : width;
for (uint i = 0; i < col_cnt; ++i) {
PIVector<Variable> & cvars(tabs[cur_tab].columns[i].variables);
cx = col_wid * i;
toUpperLeft();
if (my < vars()[i].size()) my = vars()[i].size();
if (my < cvars.size()) my = cvars.size();
j = 0;
piForeachC (Variable & tv, vars()[i]) {
piForeachC (Variable & tv, cvars) {
if (j > height - 3) continue;
j++;
moveRight(cx);
@@ -338,7 +340,7 @@ void PIConsole::run() {
void PIConsole::fillLabels() {
uint cx, cy, my = 0;
uint cx, cy, my = 0, mx = 0, dx;
#ifdef WINDOWS
GetConsoleScreenBufferInfo(hOut, &sbi);
width = sbi.srWindow.Right - sbi.srWindow.Left;
@@ -349,21 +351,31 @@ void PIConsole::fillLabels() {
width = ws.ws_col;
height = ws.ws_row;
#endif
col_cnt = vars().size();
col_cnt = columns().size();
col_wid = (col_cnt > 0) ? width / col_cnt : width;
for (uint i = 0; i < col_cnt; ++i) {
Column & ccol(tabs[cur_tab].columns[i]);
PIVector<Variable> & cvars(ccol.variables);
if (ccol.alignment != Nothing) {
mx = 0;
piForeachC (Variable & j, cvars)
if (j.type != 0 && j.s != 0)
if (mx < j.name.size())
mx = j.name.size();
mx += 2;
}
cx = col_wid * i;
cy = 1;
toUpperLeft();
for (uint j = 0; j < vars()[i].size(); ++j) {
for (uint j = 0; j < cvars.size(); ++j) {
if (int(j) > height - 3) continue;
if (my < j) my = j;
moveRight(cx);
tv = vars()[i][j];
vars()[i][j].nx = cx;
vars()[i][j].ny = cy;
Variable & tv(cvars[j]);
cvars[j].nx = cx;
cvars[j].ny = cy;
if (tv.name.size() == 0) {
vars()[i][j].offset = 0;
cvars[j].offset = 0;
clearLine();
newLine();
cy++;
@@ -371,16 +383,33 @@ void PIConsole::fillLabels() {
}
clearLine();
if (tv.type == 0 && tv.s == 0) {
vars()[i][j].offset = vars()[i][j].name.length();
vars()[i][j].nx += vars()[i][j].offset;
cvars[j].offset = cvars[j].name.length();
cvars[j].nx += cvars[j].offset;
printLine(tv.name, cx, tv.format);
newLine();
cy++;
continue;
}
vars()[i][j].offset = (tv.name + ": ").length();
vars()[i][j].nx += vars()[i][j].offset;
printValue(tv.name + ": ", tv.format);
switch (ccol.alignment) {
case Nothing:
cvars[j].offset = (tv.name + ": ").length();
cvars[j].nx += cvars[j].offset;
printValue(tv.name + ": ", tv.format);
break;
case Left:
cvars[j].offset = mx;
cvars[j].nx += cvars[j].offset;
printValue(tv.name + ": ", tv.format);
break;
case Right:
cvars[j].offset = mx;
cvars[j].nx += cvars[j].offset;
dx = mx - (tv.name + ": ").length();
moveRight(dx);
printValue(tv.name + ": ", tv.format);
moveLeft(dx);
break;
}
newLine();
cy++;
}
@@ -428,70 +457,70 @@ int PIConsole::bitsValue(void * src, int offset, int count) {
return ret;
}
#define ADD_VAR_BODY tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; checkColumn(column);
#define ADD_VAR_BODY tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; checkColumn(col);
void PIConsole::addString(const PIString & name, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = 0; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, PIString* ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, bool * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 1; tv.b = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, int * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 2; tv.i = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, long * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 3; tv.l = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, char * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 4; tv.c = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, float * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 5; tv.f = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, double * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 6; tv.d = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, short * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 7; tv.sh = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, uint * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 8; tv.ui = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, ulong * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 9; tv.ul = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, ushort * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 10; tv.ush = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, uchar * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 11; tv.uc = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, llong * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 12; tv.ll = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, ullong * ptr, int column, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 13; tv.ull = ptr; vars()[column - 1].push_back(tv);}
void PIConsole::addVariable(const PIString & name, PIProtocol * ptr, int column, PIFlags<PIConsole::Format> format) {
addString("protocol " + name, column, format | PIConsole::Bold);
addVariable("Rec :" + ptr->receiverDeviceName() + " ", ptr->receiverDeviceState_ptr(), column, format);
addVariable("Send:" + ptr->senderDeviceName() + " ", ptr->senderDeviceState_ptr(), column, format);
addVariable("Sended count", ptr->sendCount_ptr(), column, format);
addVariable("Received count", ptr->receiveCount_ptr(), column, format);
addVariable("Invalid count", ptr->wrongCount_ptr(), column, format);
addVariable("Missed count", ptr->missedCount_ptr(), column, format);
addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), column, format);
addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), column, format);
addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), column, format);
addVariable("Receiver history size", ptr->receiverHistorySize_ptr(), column, format);
addVariable("Sender history size", ptr->senderHistorySize_ptr(), column, format);
addVariable("Quality", ptr->quality_ptr(), column, format);
void PIConsole::addString(const PIString & name, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = 0; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, PIString* ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, bool * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 1; tv.b = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, int * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 2; tv.i = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, long * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 3; tv.l = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, char * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 4; tv.c = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, float * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 5; tv.f = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, double * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 6; tv.d = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, short * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 7; tv.sh = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, uint * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 8; tv.ui = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, ulong * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 9; tv.ul = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, ushort * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 10; tv.ush = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, uchar * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 11; tv.uc = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, llong * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 12; tv.ll = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, ullong * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 13; tv.ull = ptr; column(col).push_back(tv);}
void PIConsole::addVariable(const PIString & name, PIProtocol * ptr, int col, PIFlags<PIConsole::Format> format) {
addString("protocol " + name, col, format | PIConsole::Bold);
addVariable("Rec :" + ptr->receiverDeviceName() + " ", ptr->receiverDeviceState_ptr(), col, format);
addVariable("Send:" + ptr->senderDeviceName() + " ", ptr->senderDeviceState_ptr(), col, format);
addVariable("Sended count", ptr->sendCount_ptr(), col, format);
addVariable("Received count", ptr->receiveCount_ptr(), col, format);
addVariable("Invalid count", ptr->wrongCount_ptr(), col, format);
addVariable("Missed count", ptr->missedCount_ptr(), col, format);
addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format);
addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format);
addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format);
addVariable("Receiver history size", ptr->receiverHistorySize_ptr(), col, format);
addVariable("Sender history size", ptr->senderHistorySize_ptr(), col, format);
addVariable("Quality", ptr->quality_ptr(), col, format);
}
void PIConsole::addVariable(const PIString & name, PISystemMonitor * ptr, int column, PIFlags<PIConsole::Format> format) {
addString("monitor " + name, column, format | PIConsole::Bold);
addVariable("state ", &(ptr->statistic().state), column, format);
addVariable("threads ", &(ptr->statistic().threads), column, format);
addVariable("priority", &(ptr->statistic().priority), column, format);
addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), column, format);
addVariable("memory shared ", &(ptr->statistic().share_memsize_readable), column, format);
addVariable("cpu load", &(ptr->statistic().cpu_load_system), column, format);
void PIConsole::addVariable(const PIString & name, PISystemMonitor * ptr, int col, PIFlags<PIConsole::Format> format) {
addString("monitor " + name, col, format | PIConsole::Bold);
addVariable("state ", &(ptr->statistic().state), col, format);
addVariable("threads ", &(ptr->statistic().threads), col, format);
addVariable("priority", &(ptr->statistic().priority), col, format);
addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format);
addVariable("memory shared ", &(ptr->statistic().share_memsize_readable), col, format);
addVariable("cpu load", &(ptr->statistic().cpu_load_system), col, format);
}
void PIConsole::addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int column, PIFlags<PIConsole::Format> format) {
void PIConsole::addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int col, PIFlags<PIConsole::Format> format) {
tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format;
checkColumn(column); vars()[column - 1].push_back(tv);}
void PIConsole::addEmptyLine(int column, uint count) {
checkColumn(col); column(col).push_back(tv);}
void PIConsole::addEmptyLine(int col, uint count) {
tv.name = ""; tv.type = 0; tv.d = 0; tv.format = Normal;
for (uint i = 0; i < count; ++i) {
checkColumn(column);
vars()[column - 1].push_back(tv);
checkColumn(col);
column(col).push_back(tv);
}
}
@@ -521,15 +550,15 @@ PIString PIConsole::getString(int x, int y) {
PIString PIConsole::getString(const PIString & name) {
piForeachC (PIVector<Variable> & i, tabs[cur_tab].variables)
piForeachC (Variable & j, i)
piForeachC (Column & i, tabs[cur_tab].columns)
piForeachC (Variable & j, i.variables)
if (j.name == name)
return getString(j.nx + 1, j.ny);
return PIString();
}
#define PRINT_VAR_BODY couts(fstr(format).stdString()); int ret = couts(value); couts(fstr(PIConsole::Dec).stdString()); return ret;
#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); couts(fstr(PIConsole::Dec)); return ret;
inline void PIConsole::printLine(const PIString & value, int dx, PIFlags<PIConsole::Format> format) {
int i = width - value.length() - dx;
@@ -537,15 +566,15 @@ inline void PIConsole::printLine(const PIString & value, int dx, PIFlags<PIConso
--i;
#endif
PIString ts = fstr(format);
couts(ts.stdString());
couts(ts);
if (i >= 0) ts = value + PIString(i, ' ');
else ts = value.left(value.size() + i);
couts(ts.stdString());
couts(fstr(Dec).stdString());
couts(ts);
couts(fstr(Dec));
}
inline int PIConsole::printValue(const PIString & value, PIFlags<PIConsole::Format> format) {
couts(fstr(format).stdString());
int ret = couts(value.stdString());
couts(fstr(format));
int ret = couts(value);
fstr(PIConsole::Dec);
return ret;
}

34
piconsole.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Console output/input
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -61,6 +61,7 @@ public:
Hex = 0x2000000,
Oct = 0x4000000,
Scientific = 0x8000000};
enum Alignment {Nothing, Left, Right};
void addString(const PIString & name, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, PIString * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
@@ -106,9 +107,13 @@ public:
void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;}
void clearCustomStatus() {tabs[cur_tab].status.clear();}
Alignment defaultAlignment() const {return def_align;}
void setDefaultAlignment(Alignment align) {def_align = align;}
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();} vars().clear();}
EVENT_HANDLER1(PIConsole, 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);}
@@ -156,7 +161,7 @@ private:
void showCursor() {printf("\e[?25h");}
#endif
void status();
void checkColumn(uint col) {if (vars().size() < col) {vars().resize(col);}}
void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));}
int bitsValue(void * src, int offset, int count);
inline void printLine(const PIString & str, int dx = 0, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const PIString & str, PIFlags<PIConsole::Format> format = PIConsole::Normal);
@@ -203,21 +208,33 @@ private:
void * ptr;
};
void operator =(const Variable & src) {name = src.name; format = src.format; type = src.type; offset = src.offset;
bitFrom = src.bitFrom; bitCount = src.bitCount; c = src.c; nx = src.nx; ny = src.ny;}
bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny;}
};
struct Column {
PIVector<Variable> variables;
Alignment alignment;
Column(Alignment align = PIConsole::Right) { alignment = align;}
uint size() const {return variables.size();}
Variable & operator [](int index) {return variables[index];}
const Variable & operator [](int index) const {return variables[index];}
void push_back(const Variable & v) {variables.push_back(v);}
void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;}
};
struct Tab {
PIVector<PIVector<Variable> > variables;
PIVector<Column> columns;
PIString name;
PIString status;
char key;
Tab() {;}
Tab() {}
Tab(PIString n, char k) {name = n; key = k;}
~Tab() {;}
};
PIVector<PIVector<Variable> > & vars() {return tabs[cur_tab].variables;}
inline int couts(const string v);
PIVector<Column> & columns() {return tabs[cur_tab].columns;}
Column & column(int index) {return tabs[cur_tab].columns[index - 1];}
inline int couts(const PIString & v);
inline int couts(const char * v);
inline int couts(const bool v);
inline int couts(const char v);
@@ -246,6 +263,7 @@ private:
PIVector<Tab> tabs;
Variable tv;
PIKbdListener * listener;
Alignment def_align;
KBFunc ret_func;
int width, height, pwidth, pheight, ret, col_wid, num_format;
uint my;

247
picontainers.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Generic containers, based on STL
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -124,7 +124,7 @@ template <typename T> inline _PIForeachC<T> * _PIForeachCastC(_PIForeachBase & c
#define piForeachRC piForeachCR
#define piForTimes(c) for(int i = 0; i < c; ++i)
#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
template<typename Enum>
class PIFlags {
@@ -133,27 +133,243 @@ public:
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 = flags | f.flags;}
void operator |=(const Enum & e) {flags = flags | e;}
void operator |=(const int i) {flags = flags | i;}
void operator &=(const PIFlags & f) {flags = flags & f.flags;}
void operator &=(const Enum & e) {flags = flags & e;}
void operator &=(const int i) {flags = 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) {return (flags & e) == e;}
operator int() const {return flags;}
private:
int flags;
};
/*
template <typename T>
class PIVector {
public:
PIVector(uint size = 0, const T & f = T()): data_(0), size_(0), rsize_(0) {resize(size, f);}
PIVector(T * d, uint size): data_(0), size_(0), rsize_(0) {alloc(size); for (uint i = 0; i < size; ++i) data_[i] = d[i];}
~PIVector() {dealloc();}
typedef T value_type;
class iterator {
friend class PIVector<T>;
private:
iterator(PIVector<T> * v, int p): parent(v), pos(p) {}
PIVector<T> * parent;
int pos;
public:
iterator(): parent(0) {}
T & operator *() {return (*parent)[pos];}
const T & operator *() const {return (*parent)[pos];}
void operator ++() {++pos;}
void operator ++(int) {++pos;}
void operator --() {--pos;}
void operator --(int) {--pos;}
bool operator ==(const iterator & it) const {return (pos == it.pos);}
bool operator !=(const iterator & it) const {return (pos != it.pos);}
};
class const_iterator {
friend class PIVector<T>;
private:
const_iterator(const PIVector<T> * v, int p): parent(v), pos(p) {}
const PIVector<T> * parent;
int pos;
public:
const_iterator(): parent(0) {}
//T & operator *() {return (*parent)[pos];}
const T & operator *() const {return (*parent)[pos];}
void operator ++() {++pos;}
void operator ++(int) {++pos;}
void operator --() {--pos;}
void operator --(int) {--pos;}
bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
};
class reverse_iterator {
friend class PIVector<T>;
private:
reverse_iterator(PIVector<T> * v, int p): parent(v), pos(p) {}
PIVector<T> * parent;
int pos;
public:
reverse_iterator(): parent(0) {}
T & operator *() {return (*parent)[pos];}
const T & operator *() const {return (*parent)[pos];}
void operator ++() {--pos;}
void operator ++(int) {--pos;}
void operator --() {++pos;}
void operator --(int) {++pos;}
bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
};
class const_reverse_iterator {
friend class PIVector<T>;
private:
const_reverse_iterator(const PIVector<T> * v, int p): parent(v), pos(p) {}
const PIVector<T> * parent;
int pos;
public:
const_reverse_iterator(): parent(0) {}
//T & operator *() {return (*parent)[pos];}
const T & operator *() const {return (*parent)[pos];}
void operator ++() {--pos;}
void operator ++(int) {--pos;}
void operator --() {++pos;}
void operator --(int) {++pos;}
bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
};
iterator begin() {return iterator(this, 0);}
iterator end() {return iterator(this, size_);}
const_iterator begin() const {return const_iterator(this, 0);}
const_iterator end() const {return const_iterator(this, size_);}
reverse_iterator rbegin() {return reverse_iterator(this, size_ - 1);}
reverse_iterator rend() {return reverse_iterator(this, -1);}
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size_ - 1);}
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
uint size() const {return size_;}
int size_s() const {return size_;}
int length() const {return size_;}
bool isEmpty() const {return (size_ == 0);}
T & operator [](int index) {return data_[index];}
T & at(uint index) {return data_[index];}
const T & operator [](int index) const {return data_[index];}
const T & at(uint index) const {return data_[index];}
T & back() {return data_[size_ - 1];}
const T & back() const {return data_[size_ - 1];}
T & front() {return data_[0];}
const T & front() const {return data_[0];}
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;}
T * data(int index = 0) {return &(data_[index]);}
const T * data(int index = 0) const {return &(data_[index]);}
PIVector<T> & clear() {resize(0); return *this;}
PIVector<T> & fill(const T & f = T()) {
if (sizeof(T) == 1) memset(data_, f, size_);
else for (uint i = 0; i < size_; ++i) memcpy(&(data_[i]), &f, sizeof(T));
return *this;
}
PIVector<T> & assign(const T & f = T()) {return fill(f);}
PIVector<T> & resize(uint new_size, const T & f = T()) {
if (new_size < size_) {
size_ = new_size;
return *this;
}
if (new_size > size_) {
os = size_;
alloc(new_size);
uint ds = size_ - os;
//if (sizeof(T) == 1) memset(&(data_[os]), f, ds);
for (uint i = 0; i < ds; ++i) data_[os + i] = f;
return *this;
}
return *this;
}
PIVector<T> & insert(int index, const T & v = T()) {
push_back(v);
if (index >= int(size_ - 1)) return *this;
os = size_ - index;
T * pd = new T[os * sizeof(T)];
memcpy(pd, &(data_[index]), os * sizeof(T));
memcpy(&(data_[index + 1]), pd, os * sizeof(T));
delete[] pd;
data_[index] = v;
return *this;
}
PIVector<T> & remove(int index, int count = 1) {
if (index + count >= int(size_)) {
resize(index);
return *this;
}
os = size_ - index - count;
T * pd = new T[os * sizeof(T)];
memcpy(pd, &(data_[index + count]), os * sizeof(T));
memcpy(&(data_[index]), pd, os * sizeof(T));
delete[] pd;
resize(size_ - count);
return *this;
}
typedef int (*CompareFunc)(const T * , const T * );
static int compare_func(const T * t0, const T * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
PIVector<T> & sort(CompareFunc compare = compare_func) {qsort(data_, size_, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
PIVector<T> & removeOne(const T & v) {for (uint i = 0; i < size_; ++i) if (data_[i] == v) {remove(i); return *this;} return *this;}
PIVector<T> & removeAll(const T & v) {for (uint i = 0; i < size_; ++i) if (data_[i] == v) {remove(i); --i;} return *this;}
PIVector<T> & push_back(const T & v) {alloc(size_ + 1); data_[size_ - 1] = v; return *this;}
PIVector<T> & append(const T & v) {return push_back(v);}
PIVector<T> & operator <<(const T & v) {return push_back(v);}
PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
PIVector<T> & prepend(const T & v) {return push_front(v);}
//PIVector<T> & operator <<(const T & v) {return push_back(v);}
PIVector<T> & pop_back() {if (size_ == 0) return *this; resize(size_ - 1); return *this;}
PIVector<T> & pop_front() {if (size_ == 0) return *this; remove(0); return *this;}
private:
uint asize(uint s) {if (s == 0) return 0; if (rsize_ + rsize_ >= s && rsize_ < s) return rsize_ + rsize_; uint t = 0, s_ = s - 1; while (s_ >> t) ++t; return (1 << t);}
void dealloc() {if (data_ != 0) delete[] data_; data_ = 0;}
void alloc(uint new_size) {
if (new_size <= rsize_) {
size_ = new_size;
return;
}
os = size_;
size_ = new_size;
uint as = asize(new_size);
if (as == rsize_) return;
T * pd = 0;
if (os > 0) {
pd = new T[os * sizeof(T)];
memcpy(pd, data_, os * sizeof(T));
}
rsize_ = as;
dealloc();
data_ = new T[rsize_ * sizeof(T)];
if (os > 0) {
memcpy(data_, pd, size_ * sizeof(T));
delete[] pd;
}
}
T * data_;
uint size_, rsize_, os;
};
*/
template<typename Type, typename Allocator = std::allocator<Type> >
class PIVector: public vector<Type, Allocator> {
typedef PIVector<Type, Allocator> _CVector;
@@ -172,15 +388,20 @@ 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();}
typedef int (*CompareFunc)(const Type * , const Type * );
static int compare_func(const Type * t0, const Type * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
_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;}
_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(const Type & t) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) {_stlc::erase(i); --i;} return *this;}
_CVector & removeOne(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
_CVector & removeAll(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
_CVector & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
_CVector & operator <<(const Type & t) {_stlc::push_back(t); return *this;}
_CVector & operator <<(const _CVector & t) {for (typename _stlc::iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
_CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
bool operator !=(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return 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;}
@@ -212,7 +433,7 @@ public:
_CList & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + 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, Allocator> toVector() {PIVector<Type, Allocator> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
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> >
@@ -232,7 +453,7 @@ public:
_CSet & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;}
_CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;}
bool operator [](const Type & t) {return _stlc::find(t);}
PIVector<Type, Allocator> toVector() {PIVector<Type, Allocator> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
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>
@@ -265,7 +486,7 @@ public:
int size_s() const {return static_cast<int>(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
_CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;}
PIVector<Type, Allocator> toVector() {PIVector<Type, Allocator> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
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>

4
pidir.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Directory
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@ PIDir::PIDir() {
PIDir::PIDir(const PIString & dir) {
path_ = dir.stdString();
path_ = dir;
dir_ = 0;
open();
}

2
pidir.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Directory
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

309
piethernet.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Ethernet, UDP
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,182 +20,217 @@
#include "piethernet.h"
PIEthernet::PIEthernet(PIString ip, int port, void * data_, EthernetFunc slot): PIThread() {
PIEthernet::PIEthernet(void * data, ReadRetFunc slot): PIIODevice("", ReadWrite) {
piMonitor.ethernets++;
setPriority(piHigh);
data = data_;
ip_ = ip_s = ip;
port_ = port_s = port;
sock = sock_s = -1;
ret_func = slot;
tries = 0;
//buffer_ = new char[BUFFER_SIZE];
type_ = UDP;
ret_data_ = data;
ip_ = ip_s = "";
port_ = port_s = 0;
sock = -1;
ret_func_ = slot;
connected_ = false;
server_thread_.setData(this);
setThreadedReadBufferSize(65536);
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
init();
}
PIEthernet::PIEthernet(PIEthernet::Type type, void * data, ReadRetFunc slot): PIIODevice("", ReadWrite) {
piMonitor.ethernets++;
setPriority(piHigh);
type_ = type;
ret_data_ = data;
ip_ = ip_s = "";
port_ = port_s = 0;
sock = -1;
ret_func_ = slot;
connected_ = false;
server_thread_.setData(this);
setThreadedReadBufferSize(65536);
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
init();
}
PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
piMonitor.ethernets++;
setPriority(piHigh);
type_ = TCP_Client;
parseAddress(ip_port, &ip_s, &port_s);
sock = sock_;
server_thread_.setData(this);
init_ = opened_ = connected_ = true;
setThreadedReadBufferSize(65536);
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
initSend();
}
PIEthernet::~PIEthernet() {
piMonitor.ethernets--;
terminate();
if (server_thread_.isRunning()) server_thread_.terminate();
closeSocket(sock);
#ifdef WINDOWS
WSACleanup();
#endif
if (sock != -1) {
shutdown(sock, SHUT_RDWR);
#ifdef WINDOWS
closesocket(sock);
#else
close(sock);
#endif
sock = -1;
}
if (sock_s != -1) {
shutdown(sock_s, SHUT_RDWR);
#ifdef WINDOWS
closesocket(sock_s);
#else
close(sock_s);
#endif
sock_s = -1;
}
//if (buffer_ != 0) delete buffer_;
//buffer_ = 0;
}
void PIEthernet::terminate() {
if (!receiverInitialized()) return;
if (isRunning()) {
stop();
PIThread::terminate();
}
tries = 0;
/*if (sock != -1) {
shutdown(sock, SHUT_RDWR);
shutdown(sock, SHUT_RDWR);
close(sock);
sock = -1;
}
if (sock_s != -1) {
shutdown(sock_s, SHUT_RDWR);
close(sock_s);
sock_s = -1;
}*/
}
void PIEthernet::begin() {
if (!init()) stop();
}
void PIEthernet::run() {
/*#ifdef WINDOWS
int addr_len = sizeof(sockaddr);
#else
socklen_t addr_len = sizeof(sockaddr_storage);
#endif*/
//cout << "[PIEthernet] reading from " << &addr_ << endl;
readed = recv(sock, buffer_, BUFFER_SIZE, 0/*, (sockaddr * )&addr_, &addr_len*/);
//cout << WSAGetLastError() << endl;
if (readed < 0) {
cout << "[PIEthernet] Error while reading, " << errorString() << endl;
//stop();
//init();
return;
}
if (ret_func != 0) ret_func(data, buffer_, readed);
}
void PIEthernet::end() {
terminate();
}
bool PIEthernet::init() {
//cout << "init " << type_ << endl;
closeSocket(sock);
int st = 0, so = 1;
if (type_ == UDP) st = SOCK_DGRAM;
if (type_ == TCP_Client || type_ == TCP_Server) st = SOCK_STREAM;
sock = socket(PF_INET, st, 0);
if (sock == -1) {
piCout << "[PIEthernet] Cant`t create socket, " << errorString() << endl;
return false;
}
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so, sizeof(so));
//fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/);
return true;
}
void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
if (ip != 0) *ip = ipp.left(ipp.find(":"));
if (port != 0) *port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt();
}
bool PIEthernet::openDevice() {
if (connected_) return true;
if (sock == -1) init();
if (sock == -1) return false;
//cout << " bind to " << path_ << " ..." <<endl;
parseAddress(path_, &ip_, &port_);
addr_.sin_port = htons(port_);
addr_.sin_addr.s_addr = inet_addr(ip_.data());
addr_.sin_family = PF_INET;
addr_.sin_port = htons(port_);
#ifdef WINDOWS
closesocket(sock);
#else
close(sock);
#endif
sock = socket(PF_INET, SOCK_DGRAM, 0);
//cout << "openDevice\n";
if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) {
tries++;
if (tries < 10) {
if (init()) {
tries = 0;
return true;
} else return false;
} else
cout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl;
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl;
return false;
}
//cout << "!" << endl;
return true;
}
bool PIEthernet::initSend() {
#ifdef WINDOWS
closesocket(sock_s);
#else
close(sock_s);
#endif
sock_s = socket(PF_INET, SOCK_DGRAM, 0);
if (sock_s == -1) {
tries++;
if (tries < 10) {
if (init()) {
tries = 0;
return true;
} else return false;
} else
cout << "[PIEthernet] Unable to create socket, " << errorString() << endl;
return false;
}
bool PIEthernet::closeDevice() {
//cout << "close\n";
if (sock != -1) shutdown(sock, SHUT_RDWR);
closeSocket(sock);
piForeach (PIEthernet * i, clients_)
delete i;
clients_.clear();
if (server_thread_.isRunning()) server_thread_.terminate();
connected_ = false;
return true;
}
bool PIEthernet::send(PIString ip, int port, char * data, int size) {
if (sock_s == -1) {
//cout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
bool PIEthernet::connect(PIString ip, int port) {
if (sock == -1) return false;
addr_.sin_port = htons(port);
addr_.sin_addr.s_addr = inet_addr(ip.data());
addr_.sin_family = PF_INET;
//piCout << "[PIEthernet] connect to " << ip << ":" << port << endl;
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
if (!connected_)
piCout << "[PIEthernet] Cant`t connect to " << ip << ":" << port << ", " << errorString() << endl;
opened_ = connected_;
return connected_;
}
bool PIEthernet::listen() {
if (sock == -1) init();
if (sock == -1) return false;
parseAddress(path_, &ip_, &port_);
addr_.sin_port = htons(port_);
addr_.sin_addr.s_addr = inet_addr(ip_.data());
addr_.sin_family = PF_INET;
if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) {
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl;
return false;
}
saddr_.sin_port = htons(port);
saddr_.sin_addr.s_addr = inet_addr(ip.data());
saddr_.sin_family = PF_INET;
wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
if (wrote != size) {
//cout << "[PIEthernet] Error while sending" << endl;
if (::listen(sock, 64) == -1) {
piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << errorString() << endl;
return false;
}
//cout << "[PIEthernet] Wrote " << wrote << " bytes in " << devName << endl;
//piCout << "[PIEthernet] listen on " << ip_ << ":" << port_ << endl;
server_thread_.start(server_func);
return true;
}
bool PIEthernet::send(uchar * data, int size) {
if (sock_s == -1) {
//cout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
return false;
int PIEthernet::read(void * read_to, int max_size) {
//cout << "read " << sock << endl;
if (sock == -1) init();
if (sock == -1) return -1;
//piCout << "[PIEthernet] read from " << ip_ << ":" << port_ << endl;
switch (type_) {
case UDP: case TCP_Client:
return recv(sock, read_to, max_size, 0);
//return ::read(sock, read_to, max_size);
default: break;
//return ::read(sock, (char * )read_to, max_size);
}
saddr_.sin_port = htons(port_s);
saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
saddr_.sin_family = PF_INET;
//cout << "[PIEthernet] sending in " << sock_s << endl;
wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
if (wrote != size) {
//cout << "[PIEthernet] Error while sending" << endl;
return false;
}
//cout << "[PIEthernet] Wrote " << wrote << " bytes" << endl;
return true;
return -1;
}
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;
return -1;
}
//piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes" << endl;
switch (type_) {
case UDP:
saddr_.sin_port = htons(port_s);
saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
saddr_.sin_family = PF_INET;
return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
case TCP_Client:
return ::write(sock, data, max_size);
default: break;
//return ::read(sock, read_to, max_size);
}
return -1;
}
void PIEthernet::server_func(void * eth) {
PIEthernet * ce = (PIEthernet * )eth;
sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr);
int s;
s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
if (s == -1) {
piCout << "[PIEthernet] Cant`t accept new connection, " << errorString() << endl;
return;
}
PIString ip(inet_ntoa(client_addr.sin_addr));
ip += ":" + PIString::fromNumber(htons(client_addr.sin_port));
ce->clients_ << new PIEthernet(s, ip);
cout << "connected " << ip << endl;
//char d[256];
//cout << " recv " << recv(s, d, 256, 0) << endl;
//cout << recv(ce->clients_.back()->sock, d, 256, 0) << endl;
}

83
piethernet.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Ethernet, UDP
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,12 +20,13 @@
#ifndef PIETHERNET_H
#define PIETHERNET_H
#include "pithread.h"
#include "pistring.h"
#include "pitimer.h"
#include "piiodevice.h"
#ifndef WINDOWS
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/socket.h>
# include <fcntl.h>
#else
# ifdef CC_VC
# include <winsock.h>
@@ -36,42 +37,66 @@
# endif
#endif
#define BUFFER_SIZE 4096
typedef bool (*EthernetFunc)(void * , uchar * , int );
class PIEthernet: public PIThread
class PIEthernet: public PIIODevice
{
public:
// slot is any function format "bool <func>(void*, uchar*, int)"
PIEthernet(PIString ip = "", int port = 0, void * data = 0, EthernetFunc slot = 0);
PIEthernet(void * data, ReadRetFunc slot);
enum Type {UDP, TCP_Client, TCP_Server};
PIEthernet(Type type = UDP, void * data = 0, ReadRetFunc slot = 0);
~PIEthernet();
void setSlot(EthernetFunc func) {ret_func = func;}
void setData(void * d) {data = d;}
void setReadAddress(PIString ip, int port) {ip_ = ip; port_ = port;}
void setReadAddress(PIString ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);}
void setReadAddress(PIString ip_port) {path_ = ip_port;}
void setSendAddress(PIString ip, int port) {ip_s = ip; port_s = port;}
void setSendAddress(PIString ip_port) {parseAddress(ip_port, &ip_s, &port_s);}
Type type() const {return type_;}
bool connect(PIString ip, int port);
bool connect(PIString ip_port) {parseAddress(ip_port, &ip_c, &port_c); return connect(ip_c, port_c);}
bool isConnected() const {return connected_;}
bool listen();
bool listen(PIString ip, int port) {setReadAddress(ip, port); return listen();}
bool listen(PIString ip_port) {setReadAddress(ip_port); return listen();}
PIEthernet * client(int index) {return clients_[index];}
int clientsCount() const {return clients_.size_s();}
PIVector<PIEthernet * > clients() {return clients_;}
bool send(PIString ip, int port, const void * data, int size) {ip_s = ip; port_s = port; return send(data, size);}
bool send(PIString ip_port, const void * data, int size) {parseAddress(ip_port, &ip_s, &port_s); return send(data, size);}
bool send(const void * data, int size) {return (write(data, size) == size);}
int read(void * read_to, int max_size);
int write(const void * data, int max_size);
protected:
PIEthernet(int sock, PIString ip_port);
bool send(PIString ip, int port, char * data, int size);
bool send(uchar * data, int size);
bool init();
bool initSend();
bool receiverInitialized() const {return sock != -1;}
bool senderInitialized() const {return sock_s != -1;}
void terminate();
const uchar * buffer() const {return buffer_;}
bool openDevice();
bool closeDevice();
#ifdef WINDOWS
void closeSocket(int & sd) {if (sd != -1) closesocket(sd); sd = -1;}
#else
void closeSocket(int & sd) {if (sd != -1) ::close(sd); sd = -1;}
#endif
void parseAddress(const PIString & ipp, PIString * ip, int * port);
int sock, port_, port_s, port_c, wrote;
bool connected_;
sockaddr_in addr_, saddr_;
PIString ip_, ip_s, ip_c;
PIThread server_thread_;
PIVector<PIEthernet * > clients_;
Type type_;
private:
void begin();
void run();
void end();
int sock, sock_s, port_, port_s, wrote, readed, tries;
sockaddr_in addr_, saddr_;
PIString ip_, ip_s;
EthernetFunc ret_func;
void * data;
uchar buffer_[BUFFER_SIZE];
static void server_func(void * eth);
};

2
pievaluator.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Evaluator designed for stream computing
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pievaluator.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Evaluator designed for stream computing
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

88
pifile.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
File
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,35 +20,46 @@
#include "pifile.h"
bool PIFile::open(const PIString & path_, PIFlags<Mode> mode_) {
cpath = path_;
cmode = mode_;
string st = cpath.stdString();
if (cmode[New]) {
stream.open(st.c_str(), fstream::in | fstream::out | fstream::trunc | fstream::binary);
stream.close();
cmode &= ~New;
stream.open(st.c_str(), (fstream::openmode)(int)cmode | fstream::binary);
} else stream.open(st.c_str(), (fstream::openmode)(int)cmode | fstream::binary);
return isOpened();
bool PIFile::openDevice() {
if (opened_) close();
if (path_.isEmpty()) return false;
//cout << "fopen " << path_.data() << ": " << strType(mode_).data() << endl;
fd = fopen(path_.data(), strType(mode_).data());
opened_ = (fd != 0);
seekToBegin();
return opened_;
}
bool PIFile::closeDevice() {
if (!opened_) return true;
return (fclose(fd) != 0);
}
PIString PIFile::readLine() {
char * buff = new char[4096];
stream.getline(buff, 4096);
return PIString(buff);
PIString str;
if (!opened_) return str;
char cc;
int cp = 0;
while (!isEnd() && cp < 4095) {
cc = char(fgetc(fd));
if (cc == '\n') break;
str.push_back(cc);
}
//cout << "readline: " << buff << endl;
return str;
}
llong PIFile::readAll(void * data) {
llong cp = pos(), s = size(), i = -1;
stream.seekg(0);
seekToBegin();
if (s < 0) {
while (!stream.eof())
stream.read(&(((char*)data)[++i]), 1);
while (!isEnd())
read(&(((char*)data)[++i]), 1);
} else
stream.read((char * )data, s);
read((char * )data, s);
seek(cp);
return s;
}
@@ -56,14 +67,11 @@ llong PIFile::readAll(void * data) {
PIByteArray PIFile::readAll(bool forceRead) {
llong cp = pos(), s = size();
char c;
PIByteArray a;
if (s < 0) {
if (!forceRead) return a;
while (!stream.eof()) {
stream.read(&c, 1);
a.push_back(c);
}
while (!isEnd())
a.push_back(readChar());
seek(cp);
return a;
}
@@ -75,12 +83,11 @@ PIByteArray PIFile::readAll(bool forceRead) {
llong PIFile::size() {
if (!stream.is_open()) return -1;
llong s, cp = stream.tellg();
stream.seekg(0, fstream::end);
s = stream.tellg();
stream.seekg(cp, fstream::beg);
stream.clear();
if (!opened_) return -1;
llong s, cp = pos();
seekToEnd();
s = pos();
seek(cp);
return s;
}
@@ -91,23 +98,18 @@ void PIFile::resize(llong new_size, char fill_) {
if (ds > 0) {
char * buff = new char[ds];
memset(buff, fill_, ds);
stream.write(buff, ds);
delete buff;
write(buff, ds);
delete[] buff;
return;
}
cout << "[PIFile] Downsize is not support yet :-(" << endl;
piCout << "[PIFile] Downsize is not support yet :-(" << endl;
}
llong PIFile::pos() {
if (cmode[Write]) return stream.tellp();
if (cmode[Read]) return stream.tellg();
return -1;
}
PIFile PIFile::openTemporary(PIFlags<PIFile::Mode> mode) {
char * rc;
rc = tmpnam(0);
return PIFile(PIString(rc), mode);
bool PIFile::isExists(const PIString & path) {
FILE * f = fopen(PIString(path).data(), "r");
bool ok = (f != 0);
if (ok) fclose(f);
return ok;
}

139
pifile.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
File
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,100 +20,89 @@
#ifndef PIFILE_H
#define PIFILE_H
#include "piobject.h"
#include <fstream>
#include "piiodevice.h"
#include <cstdio>
using std::fstream;
class PIFile: public PIObject
class PIFile: public PIIODevice
{
public:
PIFile(): PIObject() {;}
PIFile(const PIString & path = PIString(), DeviceMode type = ReadWrite): PIIODevice(path, type) {openDevice();}
enum Mode {Read = fstream::in, Write = fstream::out, Truncate = fstream::trunc, New = fstream::app, ReadWrite = Read | Write};
//PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;}
PIFile(const PIString & path, PIFlags<Mode> mode = ReadWrite): PIObject(path) {open(path, mode);}
PIFile(const PIFile & file): PIObject(file.cpath) {cpath = file.cpath; cmode = file.cmode;}
~PIFile() {close();}
PIFile & operator =(const PIFile & f) {cpath = f.cpath; cmode = f.cmode; return *this;}
EVENT_HANDLER2(PIFile, bool, open, const PIString & , path, PIFlags<Mode>, mode);
EVENT_HANDLER1(PIFile, bool, open, PIFlags<Mode>, mode) {return open(cpath, mode);}
EVENT_HANDLER1(PIFile, bool, open, const PIString & , path) {return open(path, cmode);}
EVENT_HANDLER0(PIFile, bool, open) {return open(cpath, cmode);}
EVENT_HANDLER0(PIFile, void, close) {stream.clear(); stream.close();}
EVENT_HANDLER0(PIFile, void, clear) {string st = cpath.stdString(); close(); stream.open(st.c_str(), fstream::trunc | fstream::binary | (fstream::openmode)(int)cmode);}
void seek(llong position) {stream.clear(); stream.seekg(position); stream.seekp(position);}
void seekToBegin() {stream.clear(); stream.seekg(0, fstream::beg); stream.seekp(0, fstream::beg);}
void seekToEnd() {stream.clear(); stream.seekg(0, fstream::end); stream.seekp(0, fstream::end);}
void seekToLine(llong line) {stream.clear(); seekToBegin(); piForTimes (line) readLine();} // line 0 - begin of file
void flush() {fflush(fd);}
EVENT_HANDLER(PIFile, void, clear) {close(); fd = fopen(path_.data(), "w"); close(); 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);
void fill(char c) {stream.fill(c);}
EVENT_HANDLER0(PIFile, void, flush) {stream.flush();}
//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(cpath.data());}
EVENT_HANDLER0(PIFile, void, remove) {close(); std::remove(path_.data());}
PIString path() const {return cpath;}
void setPath(const PIString & path) {cpath = path;}
PIFlags<Mode> mode() const {return cmode;}
void setPath(const PIString & path) {path_ = path; if (opened_) openDevice();}
llong size();
llong pos();
bool isOpened() {return stream.is_open();}
bool isEnd() {return stream.eof();}
llong pos() {if (!opened_) return -1; return ftell(fd);}
bool isEnd() {return (feof(fd) || ferror(fd));}
bool isEmpty() {return (size() <= 0);}
PIFile & writeData(const void * data, int size_) {stream.write((char * )data, size_); return *this;}
PIFile & readData(void * data, int size_) {stream.read((char * )data, size_); return *this;}
PIFile & writeToBinLog(ushort id, const void * data, int size) {writeBinary(id).writeBinary((ushort)size).writeData(data, size); flush(); return *this;}
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;}
PIFile & writeBinary(const char v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const short v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const int v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const long v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const uchar v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const ushort v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const uint v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const ulong v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const float v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const double v) {stream.write((char * )&v, sizeof(v)); return *this;}
PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;}
PIFile & operator <<(const char & v) {stream.write(&v, 1); return *this;}
//PIFile & operator <<(const string & v) {stream.write(v.c_str(), v.size()); return *this;}
PIFile & operator <<(const PIString & v) {string s = v.stdString(); stream.write(s.c_str(), s.size()); return *this;}
PIFile & operator <<(const PIByteArray & v) {stream.write((char * )v.data(), v.size()); return *this;}
PIFile & operator <<(const short & v) {stream << v; return *this;}
PIFile & operator <<(const int & v) {stream << v; return *this;}
PIFile & operator <<(const long & v) {stream << v; return *this;}
PIFile & operator <<(const uchar & v) {stream << v; return *this;}
PIFile & operator <<(const ushort & v) {stream << v; return *this;}
PIFile & operator <<(const uint & v) {stream << v; return *this;}
PIFile & operator <<(const ulong & v) {stream << v; return *this;}
PIFile & operator <<(const float & v) {stream << v; return *this;}
PIFile & operator <<(const double & v) {stream << v; 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;}
PIFile & operator <<(short v) {if (!isWriteable()) return *this; fprintf(fd, "%hd", v); return *this;}
PIFile & operator <<(int v) {if (!isWriteable()) return *this; fprintf(fd, "%d", v); return *this;}
PIFile & operator <<(long v) {if (!isWriteable()) return *this; fprintf(fd, "%ld", v); return *this;}
PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; fprintf(fd, "%c", v); return *this;}
PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; fprintf(fd, "%hd", v); return *this;}
PIFile & operator <<(uint v) {if (!isWriteable()) return *this; fprintf(fd, "%d", v); return *this;}
PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; fprintf(fd, "%ld", v); return *this;}
PIFile & operator <<(float v) {if (!isWriteable()) return *this; fprintf(fd, "%f", v); return *this;}
PIFile & operator <<(double v) {if (!isWriteable()) return *this; fprintf(fd, "%lf", v); return *this;}
PIFile & operator >>(char & v) {stream >> v; return *this;}
PIFile & operator >>(short & v) {stream >> v; return *this;}
PIFile & operator >>(int & v) {stream >> v; return *this;}
PIFile & operator >>(long & v) {stream >> v; return *this;}
PIFile & operator >>(uchar & v) {stream >> v; return *this;}
PIFile & operator >>(ushort & v) {stream >> v; return *this;}
PIFile & operator >>(uint & v) {stream >> v; return *this;}
PIFile & operator >>(ulong & v) {stream >> v; return *this;}
PIFile & operator >>(float & v) {stream >> v; return *this;}
PIFile & operator >>(double & v) {stream >> v; return *this;}
PIFile & operator >>(char & v) {if (!isWriteable()) return *this; fscanf(fd, "%hhn", &v); return *this;}
PIFile & operator >>(short & v) {if (!isWriteable()) return *this; fscanf(fd, "%hn", &v); return *this;}
PIFile & operator >>(int & v) {if (!isWriteable()) return *this; fscanf(fd, "%n", &v); return *this;}
PIFile & operator >>(long & v) {if (!isWriteable()) return *this; fscanf(fd, "%ln", &v); return *this;}
PIFile & operator >>(uchar & v) {if (!isWriteable()) return *this; fscanf(fd, "%hhn", &v); return *this;}
PIFile & operator >>(ushort & v) {if (!isWriteable()) return *this; fscanf(fd, "%hn", &v); return *this;}
PIFile & operator >>(uint & v) {if (!isWriteable()) return *this; fscanf(fd, "%n", &v); return *this;}
PIFile & operator >>(ulong & v) {if (!isWriteable()) return *this; fscanf(fd, "%ln", &v); return *this;}
PIFile & operator >>(float & v) {if (!isWriteable()) return *this; fscanf(fd, "%f", &v); return *this;}
PIFile & operator >>(double & v) {if (!isWriteable()) return *this; fscanf(fd, "%lf", &v); return *this;}
static PIFile openTemporary(PIFlags<PIFile::Mode> mode = PIFile::ReadWrite);
static bool isExists(const PIString & path) {return std::ifstream(path.stdString().c_str()).good();}
static bool remove(const PIString & path) {return std::remove(path.stdString().c_str()) == 0;}
static PIFile openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite) {return PIFile(PIString(tmpnam(0)), mode);}
static bool isExists(const PIString & path);
static bool remove(const PIString & path) {return std::remove(path.data()) == 0;}
protected:
bool openDevice();
bool closeDevice();
private:
fstream stream;
PIString cpath;
PIFlags<Mode> cmode;
PIString strType(const PIIODevice::DeviceMode type) {switch (type) {case PIIODevice::ReadOnly: return "rb"; case WriteOnly: return "ab"; case ReadWrite: return "a+b";} return "rb";}
FILE * fd;
};

2
pigeometry.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Geometry
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

23
piincludes.cpp Normal file
View File

@@ -0,0 +1,23 @@
/*
PIP - Platform Independent Primitives
Global includes
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes.h"
bool isPIInit = false;
bool piDebug = true;

11
piincludes.h Normal file → Executable file
View File

@@ -20,10 +20,11 @@
#ifndef PIINCLUDES_H
#define PIINCLUDES_H
#define PIP_VERSION 0x000102
#define PIP_VERSION 0x000200
#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16
#define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8
#define PIP_VERSION_REVISION PIP_VERSION & 0xFF
#define PIP_VERSION_SUFFIX ""
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
# define WINDOWS
@@ -119,13 +120,17 @@ static locale_t currentLocale_t = 0;
typedef std::basic_string<wchar_t> wstring;
#endif
static bool isPIInit = false;
extern bool isPIInit;
extern bool piDebug;
#define piCout if (piDebug) cout
class PIInit {
public:
PIInit() {
if (isPIInit) return;
isPIInit = true;
//piDebug = true;
#ifdef LINUX
if (currentLocale_t != 0) {
freelocale(currentLocale_t);
@@ -215,6 +220,6 @@ inline string dtos(const double num) {
#endif
return string(ch); };
inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION);}
inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION) + PIP_VERSION_SUFFIX;}
#endif // PIINCLUDES_H

107
piiodevice.cpp Executable file
View File

@@ -0,0 +1,107 @@
/*
PIP - Platform Independent Primitives
Abstract input/output device
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piiodevice.h"
PIIODevice::PIIODevice(): PIThread() {
mode_ = ReadOnly;
opened_ = init_ = thread_started_ = false;
reopen_enabled_ = true;
reopen_timeout_ = 1000;
ret_func_ = 0;
ret_data_ = 0;
buffer_tr.resize(4096);
CONNECT2(void, void * , int, &timer, timeout, this, check_start);
init();
}
PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool initNow): PIThread() {
path_ = path;
mode_ = type;
opened_ = init_ = thread_started_ = false;
reopen_enabled_ = true;
reopen_timeout_ = 1000;
ret_func_ = 0;
ret_data_ = 0;
buffer_tr.resize(4096);
CONNECT2(void, void * , int, &timer, timeout, this, check_start);
if (initNow) init();
}
void PIIODevice::check_start(void * data, int delim) {
//cout << "check " << tread_started_ << endl;
if (open()) {
thread_started_ = true;
timer.stop();
}
}
void PIIODevice::terminate() {
thread_started_ = false;
if (!isInitialized()) return;
if (isRunning()) {
stop();
PIThread::terminate();
}
}
void PIIODevice::begin() {
//cout << " begin\n";
thread_started_ = false;
if (!opened_) {
if (open()) {
thread_started_ = true;
//cout << " open && ok\n";
return;
}
} else {
thread_started_ = true;
//cout << " ok\n";
return;
}
//init();
if (!timer.isRunning() && reopen_enabled_) timer.start(reopen_timeout_);
}
void PIIODevice::run() {
if (!isReadable()) {
//cout << "not readable\n";
stop();
return;
}
if (!thread_started_) {
msleep(1);
//cout << "not started\n";
return;
}
readed_ = read(buffer_tr.data(), buffer_tr.size_s());
if (readed_ <= 0) {
msleep(10);
//cout << readed_ << ", " << errno << ", " << errorString() << endl;
return;
}
threadedRead(buffer_tr.data(), readed_);
}

121
piiodevice.h Executable file
View File

@@ -0,0 +1,121 @@
/*
PIP - Platform Independent Primitives
Abstract input/output device
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIIODEVICE_H
#define PIIODEVICE_H
#include "pitimer.h"
// function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData
typedef bool (*ReadRetFunc)(void * , uchar * , int );
class PIIODevice: public PIThread {
public:
PIIODevice();
enum DeviceMode {ReadOnly = 0x01, WriteOnly = 0x02, ReadWrite = 0x03};
PIIODevice(const PIString & path, DeviceMode type = ReadWrite, bool initNow = true);
~PIIODevice() {if (opened_) closeDevice();}
DeviceMode mode() const {return mode_;}
PIString path() const {return path_;}
bool isReadable() const {return (mode_ & ReadOnly);}
bool isWriteable() const {return (mode_ & WriteOnly);}
bool isInitialized() const {return init_;}
bool isOpened() const {return opened_;}
bool isClosed() const {return !opened_;}
bool canRead() const {return opened_ && (mode_ & ReadOnly);}
bool canWrite() const {return opened_ && (mode_ & WriteOnly);}
// Enable timer to periodically open device until it will be opened
void setReopenEnabled(bool yes = true) {reopen_enabled_ = yes;}
void setReopenTimeout(int msecs = 1000) {reopen_timeout_ = msecs;}
bool isReopenEnabled() const {return reopen_enabled_;}
int reopenTimeout() {return reopen_timeout_;}
// set return function executed when successful read in thread
void setThreadedReadSlot(ReadRetFunc func) {ret_func_ = func;}
void setThreadedReadData(void * d) {ret_data_ = d;}
void setThreadedReadBufferSize(int new_size) {buffer_tr.resize(new_size);}
int threadedReadBufferSize() const {return buffer_tr.size_s();}
const uchar * threadedReadBuffer() const {return buffer_tr.data();}
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(); return opened_;}
EVENT_HANDLER1(PIIODevice, bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); return opened_;}
EVENT_HANDLER1(PIIODevice, bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); return opened_;}
EVENT_HANDLER2(PIIODevice, bool, open, const PIString &, _path, const DeviceMode &, _type) {path_ = _path; mode_ = _type; if (!init_) init(); opened_ = openDevice(); return opened_;}
EVENT_HANDLER(PIIODevice, bool, close) {opened_ = !closeDevice(); return !opened_;}
// Flush device
EVENT_VHANDLER(PIIODevice, void, flush) {;}
// 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;}
// 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;}
// 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);}
protected:
// Function executed before first openDevice() or from constructor
virtual bool init() {return true;}
// Functions to open and close device, return value will set to "opened_" variable
virtual bool openDevice() = 0; // use path_, type_, opened_, init_ variables
virtual bool closeDevice() {return true;} // use path_, type_, opened_, init_ variables
// Function executed when thread read some data, default implementation execute external slot "ret_func_"
virtual bool threadedRead(uchar * readed, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, readed, size); return true;}
PIString path_;
DeviceMode mode_;
ReadRetFunc ret_func_;
bool init_, opened_, thread_started_, reopen_enabled_;
int reopen_timeout_;
void * ret_data_;
private:
EVENT_HANDLER2(PIIODevice, void, check_start, void * , data, int, delim);
void terminate();
void begin();
void run();
void end() {terminate();}
PITimer timer;
PIByteArray buffer_in, buffer_tr;
int readed_;
};
#endif // PIIODEVICE_H

7
pikbdlistener.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Keyboard grabber for console
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -60,7 +60,10 @@ void PIKbdListener::run() {
#else
ret = read(0, &rc, 1);
#endif
if (exit_enabled && rc == exit_key) PIKbdListener::exiting = true;
if (exit_enabled && rc == exit_key) {
PIKbdListener::exiting = true;
return;
}
if (ret_func != 0 && ret > 0) ret_func(rc, data);
}

2
pikbdlistener.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Keyboard grabber for console
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pimath.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Math
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pimath.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Math
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pimonitor.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Counter of some PIP types
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pimonitor.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Counter of some PIP types
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pimultiprotocol.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Multiprotocol
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

10
pimultiprotocol.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Multiprotocol
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -62,14 +62,14 @@ private:
class PIRepeater: public PIMultiProtocol {
public:
PIRepeater(const PIString & config, const PIString & name) {
PIConfig conf(config, PIFile::Read);
PIConfig conf(config, PIIODevice::ReadOnly);
if (!conf.isOpened()) {
cout << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
piCout << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
return;
}
PIConfig::Entry & b(conf.getValue(name));
if (b.childCount() != 2) {
cout << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!" << endl;
piCout << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!" << endl;
return;
}
addProtocol(config, b.child(0)->fullName());
@@ -86,7 +86,7 @@ public:
ullong * sendCount_ptr() {if (count() == 2) return protocol(0)->sendCount_ptr(); return 0;}
private:
void received(PIProtocol * prot, bool , char * data, int size) {if (prot == protocol(0)) protocol(1)->send(data, size); else protocol(0)->send(data, size);}
void received(PIProtocol * prot, bool , uchar * data, int size) {if (prot == protocol(0)) protocol(1)->send(data, size); else protocol(0)->send(data, size);}
};

2
pimutex.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Mutex
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
piobject.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

11
piobject.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -39,6 +39,13 @@
#define EVENT_HANDLER4(obj, ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((obj*)o)->name(n0, n1, n2, n3);} ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_HANDLER EVENT_HANDLER0
#define EVENT_VHANDLER0(obj, ret, name) static ret __stat_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name()
#define EVENT_VHANDLER1(obj, ret, name, a0, n0) static ret __stat_##name##__(void * o, a0 n0) {return ((obj*)o)->name(n0);} virtual ret name(a0 n0)
#define EVENT_VHANDLER2(obj, ret, name, a0, n0, a1, n1) static ret __stat_##name##__(void * o, a0 n0, a1 n1) {return ((obj*)o)->name(n0, n1);} virtual ret name(a0 n0, a1 n1)
#define EVENT_VHANDLER3(obj, ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((obj*)o)->name(n0, n1, n2);} virtual ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_VHANDLER4(obj, ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((obj*)o)->name(n0, n1, n2, n3);} virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_VHANDLER EVENT_VHANDLER0
#define CONNECT0(ret, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_##handler##__));
#define CONNECT1(ret, a0, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_##handler##__));
#define CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_##handler##__));
@@ -51,7 +58,7 @@ class PIObject
friend class PIObjectManager;
public:
PIObject(const PIString & name = PIString()) {piMonitor.objects++; setName(name); objects << this;}
~PIObject() {piMonitor.objects--; objects.remove(this);}
~PIObject() {piMonitor.objects--; objects.removeAll(this);}
const PIString & name() const {return name_;}
void setName(const PIString & name) {name_ = name;}

2
pip.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
All includes
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,3 +1,3 @@
[Project]
Manager=
Manager=KDevCMakeManager
Name=pip

75
pipacketextractor.cpp Normal file
View File

@@ -0,0 +1,75 @@
/*
PIP - Platform Independent Primitives
Packets extractor
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pipacketextractor.h"
PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, void * recHeaderPtr, int recHeaderSize, int recDataSize) {
ret_func_header = 0;
setPacketData(recHeaderPtr, recHeaderSize, recDataSize);
setBufferSize(4096);
setDevice(device_);
allReaded = addSize = curInd = 0;
}
void PIPacketExtractor::setDevice(PIIODevice * device_) {
dev = device_;
if (dev == 0) return;
}
bool PIPacketExtractor::threadedRead(uchar * readed, int size_) {
//cout << "extractor readed " << size_ << endl;
memcpy(buffer.data(allReaded), readed, size_);
allReaded += size_;
if (allReaded < packetSize + addSize) return true;
if (headerSize > 0) {
if (allReaded + curInd >= buffer_size) {
memcpy(sbuffer.data(), buffer.data(), buffer_size);
memcpy(buffer.data(), sbuffer.data(buffer_size - packetSize), allReaded);
allReaded = packetSize;
addSize = curInd = 0;
}
while (!packetHeaderValidate((uchar * )headerPtr, buffer.data(curInd), headerSize)) {
curInd++; missed++;
if (packetSize > 0) missed_packets = missed / packetSize;
if (curInd > addSize) {
addSize += packetSize;
return true;
}
}
memcpy(mheader.data(), buffer.data(curInd + headerSize), headerSize);
if (!packetValidate(buffer.data(curInd + headerSize), dataSize)) {
curInd++; missed++;
if (packetSize > 0) missed_packets = missed / packetSize;
return true;
}
memcpy(sbuffer.data(), buffer.data(), allReaded);
memcpy(buffer.data(), sbuffer.data(packetSize + curInd), allReaded);
allReaded -= packetSize + curInd;
curInd = addSize = 0;
} else {
packetValidate(buffer.data(), dataSize);
memcpy(sbuffer.data(), buffer.data(), allReaded);
memcpy(buffer.data(), sbuffer.data(packetSize), allReaded);
allReaded -= packetSize;
}
return true;
}

71
pipacketextractor.h Normal file
View File

@@ -0,0 +1,71 @@
/*
PIP - Platform Independent Primitives
Packets extractor
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIPACKETEXTRACTOR_H
#define PIPACKETEXTRACTOR_H
#include "piiodevice.h"
// Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false.
typedef bool (*HeaderCheckFunc)(void * , uchar * , uchar * , int );
class PIPacketExtractor: public PIIODevice
{
public:
PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0);
PIIODevice * device() {return dev;}
void setDevice(PIIODevice * device_);
int bufferSize() const {return buffer_size;}
void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size);}
void setHeaderCheckSlot(HeaderCheckFunc f) {ret_func_header = f;}
void setPacketData(void * recHeaderPtr, int recHeaderSize, int recDataSize) {headerPtr = recHeaderPtr; headerSize = recHeaderSize; dataSize = recDataSize; packetSize = headerSize + dataSize; if (headerSize > 0) mheader.resize(headerSize);}
ullong missedBytes() const {return missed;}
ullong missedPackets() const {return missed / packetSize;}
const ullong * missedBytes_ptr() const {return &missed;}
const ullong * missedPackets_ptr() const {return &missed_packets;}
PIByteArray lastHeader() {return mheader;}
int read(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);}
int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);}
protected:
virtual bool packetValidate(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;}
virtual bool packetHeaderValidate(uchar * src, uchar * rec, int size) {if (ret_func_header != 0) return ret_func_header(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;}
private:
bool threadedRead(uchar * readed, int size);
bool openDevice() {if (dev == 0) return false; return dev->isOpened();}
PIIODevice * dev;
PIByteArray mheader, buffer, sbuffer;
HeaderCheckFunc ret_func_header;
void * headerPtr, * data;
int buffer_size, dataSize, headerSize, packetSize, allReaded, addSize, curInd;
ullong missed, missed_packets;
};
#endif // PIPACKETEXTRACTOR_H

22
piprocess.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Process
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@ void PIProcess::run() {
#ifdef WINDOWS
//args.pop_front();
piForeachC (PIString & i, args)
as += i.stdString().length() + 1;
as += i.lengthAscii() + 1;
char * a = new char[as];
memset(a, ' ', as - 1);
as = 0;
@@ -93,20 +93,20 @@ void PIProcess::run() {
/// files for stdin/out/err
t_in = t_out = t_err = false;
if (f_in.path().isEmpty()) {
f_in = PIFile::openTemporary(PIFile::New | PIFile::Read);
f_in = PIFile::openTemporary(PIIODevice::ReadWrite);
t_in = true;
}
f_in.open(PIFile::New | PIFile::Read); f_in.close();
f_in.open(PIIODevice::ReadWrite); f_in.close();
if (f_out.path().isEmpty()) {
f_out = PIFile::openTemporary(PIFile::New | PIFile::Write);
f_out = PIFile::openTemporary(PIIODevice::ReadWrite);
t_out = true;
}
f_out.open(PIFile::New | PIFile::Write); f_out.close();
f_out.open(PIIODevice::WriteOnly); f_out.close();
if (f_err.path().isEmpty()) {
f_err = PIFile::openTemporary(PIFile::New | PIFile::Write);
f_err = PIFile::openTemporary(PIIODevice::ReadWrite);
t_err = true;
}
f_err.open(PIFile::New | PIFile::Write); f_err.close();
f_err.open(PIIODevice::WriteOnly); f_err.close();
str = args.front().stdString();
is_exec = true;
@@ -114,7 +114,7 @@ void PIProcess::run() {
pid = fork();
if (pid == 0) {
#endif
FILE * tf;
FILE * tf = 0;
//cout << "exec" << endl;
//cout << f_out.path() << endl;
if (g_in) tf = freopen(f_in.path().data(), "r", stdin);
@@ -140,10 +140,10 @@ void PIProcess::run() {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
} else
cout << "[PIProcess] \"CreateProcess\" error, " << errorString() << endl;
piCout << "[PIProcess] \"CreateProcess\" error, " << errorString() << endl;
#else
if (execve(str.c_str(), a, e) < 0)
cout << "[PIProcess] \"execve\" error, " << errorString() << endl;
piCout << "[PIProcess] \"execve\" error, " << errorString() << endl;
} else {
msleep(1);
//cout << "wait" << endl;

6
piprocess.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Process
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -64,8 +64,8 @@ public:
void terminate() {if (is_exec) kill(pid, SIGKILL); pid = 0;}
#endif
bool waitForFinish(int timeout_msecs = 60000) {return PIThread::waitForFinish(timeout_msecs);}
PIByteArray readOutput() {f_out.open(PIFile::Read); return f_out.readAll();}
PIByteArray readError() {f_err.open(PIFile::Read); return f_err.readAll();}
PIByteArray readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();}
PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();}
PIStringList environment() {return env;}
void clearEnvironment() {env.clear();}

229
piprotocol.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Protocol, input/output channel (COM, UDP)
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,14 +24,15 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
init();
protName = name;
PIObject::setName(name);
PIConfig conf(config, PIFile::Read);
PIConfig conf(config, PIIODevice::ReadOnly);
if (!conf.isOpened()) {
cout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
devReceiverState = devSenderState = "Config error";
return;
}
int ps, gps;
bool ok, gok, flag, gflag, has_dev = false;
float freq, gfreq;
PIFlags<PISerial::Parameters> pp;
PIConfig::Entry & b(conf.getValue(name)),
& rb(b.getValue("receiver")),
@@ -40,7 +41,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
/// receiver section
if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -49,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -58,20 +59,44 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
type_rec = PIProtocol::Ethernet;
eth = new PIEthernet(dev, ps, this, receiveEvent);
eth = new PIEthernet();
packet_ext.setDevice(eth);
//setSenderAddress(dev, ps);
setReceiverAddress(dev, ps);
has_dev = true;
flag = rb.getValue("reconnectEnabled", true, &ok);
gflag = b.getValue("reconnectEnabled", true, &gok);
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
eth->setReopenEnabled(flag);
}
freq = rb.getValue("reconnectTimeout", 1., &ok);
gfreq = b.getValue("reconnectTimeout", 1., &gok);
if (ok || gok) {
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
eth->setReopenTimeout(freq * 1000);
}
if (recDataPtr == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
if (recDataSize == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
} else {
cout << "[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 << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -81,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -90,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -99,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -110,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -118,19 +143,30 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
}
type_rec = PIProtocol::Serial;
type_send = PIProtocol::Serial;
ser = new PISerial(dev, this, receiveEvent, headerValidateEvent);
ser = new PISerial(dev);
packet_ext.setDevice(ser);
//setSenderDevice(dev, (PISerial::Speed)ps);
setReceiverDevice(dev, (PISerial::Speed)ps);
setSenderDevice(dev, (PISerial::Speed)ps);
ser->setInSpeed((PISerial::Speed)ps);
ser->setParameters(pp);
ser->setReadData(recHeaderPtr, recHeaderSize, recDataSize);
ps = rb.getValue("vtime", 1, &ok);
gps = b.getValue("vtime", 1, &gok);
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
ser->setVTime(ps);
}
has_dev = true;
if (recDataPtr == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
if (recDataSize == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
} else {
cout << "[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 << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -140,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
@@ -151,29 +187,30 @@ 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();
cout << "[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 << endl;
}
history_file_rec.open(history_path_rec, PIFile::Write | PIFile::New);
history_file_rec.open(history_path_rec, PIIODevice::WriteOnly);
}
}
float freq = rb.getValue("frequency", -1.f, &ok), gfreq = b.getValue("frequency", -1.f, &gok);
freq = rb.getValue("frequency", -1.f, &ok);
gfreq = b.getValue("frequency", -1.f, &gok);
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
if (freq > 0.f && !has_dev)
cout << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!" << endl;
float tm = b.getValue("disconnectTimeout", 3.f);
if (tm <= 0.f)
cout << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!" << endl;
timeout_ = (tm < 0.f) ? 0.f : tm;
setExpectedFrequency(freq);
/// sender section
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
@@ -183,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
@@ -192,20 +229,43 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
type_send = PIProtocol::Ethernet;
if (eth == 0) eth = new PIEthernet(dev, ps, this, receiveEvent);
if (eth == 0) eth = new PIEthernet();
setSenderAddress(dev, ps);
//setReceiverAddress(dev, ps);
has_dev = true;
flag = sb.getValue("reconnectEnabled", true, &ok);
gflag = b.getValue("reconnectEnabled", true, &gok);
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
eth->setReopenEnabled(flag);
}
freq = sb.getValue("reconnectTimeout", 1., &ok);
gfreq = b.getValue("reconnectTimeout", 1., &gok);
if (ok || gok) {
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!" << endl;
devReceiverState = "Config error";
return;
}
eth->setReopenTimeout(freq * 1000);
}
if (sendDataPtr_ == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
if (sendDataSize_ == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
} else {
cout << "[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 << "\"!" << endl;
devSenderState = "Config error";
return;
}
@@ -215,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
@@ -224,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
@@ -233,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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
@@ -244,35 +304,34 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
pp |= PISerial::TwoStopBits;
}
} else {
cout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
type_send = PIProtocol::Serial;
if (ser == 0) ser = new PISerial(dev, this, receiveEvent, headerValidateEvent);
if (ser == 0) ser = new PISerial(dev);
setSenderDevice(dev, (PISerial::Speed)ps);
ser->setOutSpeed((PISerial::Speed)ps);
ser->setParameters(pp);
ser->setReadData(recHeaderPtr, recHeaderSize, recDataSize);
has_dev = true;
if (sendDataPtr_ == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
if (sendDataSize_ == 0)
cout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
}
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)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
@@ -283,21 +342,21 @@ 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;
cout << "[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 << endl;
}
history_file_send.open(history_path_send, PIFile::Write | PIFile::New);
history_file_send.open(history_path_send, PIIODevice::WriteOnly);
}
}
freq = sb.getValue("frequency", -1.f, &ok);
gfreq = b.getValue("frequency", -1.f, &gok);
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
cout << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!" << endl;
devSenderState = "Config error";
return;
}
if (freq > 0.f && !has_dev)
cout << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!" << endl;
piCout << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!" << endl;
setSenderFrequency(freq);
headerPtr = (uchar * )recHeaderPtr;
@@ -306,6 +365,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
dataSize = recDataSize;
sendDataPtr = (uchar * )sendDataPtr_;
sendDataSize = sendDataSize_;
packet_ext.setPacketData(recHeaderPtr, recHeaderSize, recDataSize);
if (type_rec == PIProtocol::Ethernet) {
if (recHeaderPtr != 0) {
dataPtr = (uchar * )recHeaderPtr;
@@ -341,6 +401,9 @@ PIProtocol::~PIProtocol() {
void PIProtocol::init() {
packet_ext.setThreadedReadData(this);
packet_ext.setThreadedReadSlot(receiveEvent);
packet_ext.setHeaderCheckSlot(headerValidateEvent);
work = new_mp_prot = history_write_rec = history_write_send = false;
eth = 0;
ser = 0;
@@ -379,7 +442,10 @@ void PIProtocol::init() {
void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force) {
if (force) {
type_send = type_rec = PIProtocol::Serial;
if (ser == 0) ser = new PISerial("", this, receiveEvent, headerValidateEvent);
if (ser == 0) {
ser = new PISerial();
packet_ext.setDevice(ser);
}
}
if (type_rec == PIProtocol::Serial && ser != 0) {
ser->setDevice(device);
@@ -393,7 +459,10 @@ void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed spee
void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) {
if (force) {
type_rec = PIProtocol::Ethernet;
if (eth == 0) eth = new PIEthernet("", 0, this, receiveEvent);
if (eth == 0) {
eth = new PIEthernet();
packet_ext.setDevice(eth);
}
}
if (type_rec == PIProtocol::Ethernet && eth != 0) {
eth->setReadAddress(ip, port);
@@ -406,11 +475,12 @@ void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) {
void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed, bool force) {
if (force) {
type_send = type_rec = PIProtocol::Serial;
if (ser == 0) ser = new PISerial("", this, receiveEvent, headerValidateEvent);
if (ser == 0) ser = new PISerial();
}
if (type_send == PIProtocol::Serial && ser != 0) {
ser->setDevice(device);
ser->setSpeed(speed);
ser->open();
devSenderName = device;
}
}
@@ -419,10 +489,11 @@ void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed,
void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) {
if (force) {
type_send = PIProtocol::Ethernet;
if (eth == 0) eth = new PIEthernet("", 0, this, receiveEvent);
if (eth == 0) eth = new PIEthernet();
}
if (type_send == PIProtocol::Ethernet && eth != 0) {
eth->setSendAddress(ip, port);
eth->open();
if (ip.isEmpty()) devSenderName = "no ip";
else devSenderName = ip + ":" + PIString::fromNumber(port);
}
@@ -444,9 +515,10 @@ void PIProtocol::changeDisconnectTimeout() {
void PIProtocol::startReceive(float exp_frequency) {
if (exp_frequency > 0.f) exp_freq = exp_frequency;
if (type_rec == PIProtocol::Serial) ser->start();
if (type_rec == PIProtocol::Ethernet) eth->start();
//if (type_rec == PIProtocol::Serial) ser->start();
//if (type_rec == PIProtocol::Ethernet) eth->start();
if (exp_freq <= 0.f) return;
packet_ext.startThreadedRead();
setExpectedFrequency(exp_freq);
diagTimer->start(1000. / exp_freq);
diagTimer->reset();
@@ -463,8 +535,9 @@ void PIProtocol::startSend(float frequency) {
void PIProtocol::stopReceive() {
if (type_rec == PIProtocol::Serial) ser->stop();
if (type_rec == PIProtocol::Ethernet) eth->stop();
//if (type_rec == PIProtocol::Serial) ser->stop();
//if (type_rec == PIProtocol::Ethernet) eth->stop();
packet_ext.stop();
diagTimer->stop();
raiseEvent(this, "receiver stopped");
}
@@ -508,7 +581,7 @@ void PIProtocol::diagEvent(void * t, int) {
p->calc_freq();
p->calc_diag();
p->check_state();
if (p->ser != 0) p->missed_count = p->ser->missedPackets();
if (p->ser != 0) p->missed_count = p->packet_ext.missedPackets();
}
@@ -558,47 +631,49 @@ void PIProtocol::calc_freq() {
void PIProtocol::check_state() {
if (type_rec == PIProtocol::Serial) {
if (ser != 0) {
if (ser->initialized()) devReceiverState = "Initialized";
else devReceiverState = "Uninitialized";
if (ser->isOpened()) devReceiverState = "Opened";
else devReceiverState = "Not opened";
}
else devReceiverState = "Uninitialized";
else devReceiverState = "Not exists";
}
if (type_rec == PIProtocol::Ethernet) {
if (eth != 0) {
if (eth->receiverInitialized()) devReceiverState = "Initialized";
else devReceiverState = "Uninitialized";
if (eth->isOpened()) devReceiverState = "Opened";
else devReceiverState = "Not opened";
}
else devReceiverState = "Uninitialized";
else devReceiverState = "Not exists";
}
if (type_send == PIProtocol::Serial) {
if (ser != 0) {
if (ser->initialized()) devSenderState = "Initialized";
else devSenderState = "Uninitialized";
if (ser->isOpened()) devSenderState = "Opened";
else devSenderState = "Not opened";
}
else devSenderState = "Uninitialized";
else devSenderState = "Not exists";
}
if (type_send == PIProtocol::Ethernet) {
if (eth != 0) {
if (eth->senderInitialized()) devSenderState = "Initialized";
else devSenderState = "Uninitialized";
if (eth->isOpened()) devSenderState = "Opened";
else devSenderState = "Not opened";
}
else devSenderState = "Uninitialized";
else devSenderState = "Not exists";
}
}
void PIProtocol::send(const void * data, int size) {
if (data == 0 || size == 0) return;
if (!aboutSend()) return;
void PIProtocol::send(const void * data, int size, bool direct) {
if (!direct) {
if (data == 0 || size == 0) return;
if (!aboutSend()) return;
}
if (history_write_send) {
history_file_send.writeToBinLog(history_id_send, data, size);
history_rsize_send.setReadableSize(history_file_send.pos());
}
if (type_send == PIProtocol::Serial)
if (ser->send((uchar * )data, size))
if (ser->send(data, size))
send_count++;
if (type_send == PIProtocol::Ethernet)
if (eth->send((uchar * )data, size))
if (eth->send(data, size))
send_count++;
}
@@ -607,16 +682,16 @@ void PIProtocol::send() {
//lock();
//memcpy(packet, sendDataPtr, sendDataSize);
//unlock();
if (sendDataPtr == 0 || sendDataSize == 0) return;
if (!aboutSend()) return;
if (sendDataPtr == 0 || sendDataSize == 0) return;
if (history_write_send) {
history_file_send.writeToBinLog(history_id_send, sendDataPtr, sendDataSize);
history_rsize_send.setReadableSize(history_file_send.pos());
}
if (type_send == PIProtocol::Serial)
if (ser->send((uchar * )sendDataPtr, sendDataSize))
if (ser->send(sendDataPtr, sendDataSize))
send_count++;
if (type_send == PIProtocol::Ethernet)
if (eth->send((uchar * )sendDataPtr, sendDataSize))
if (eth->send(sendDataPtr, sendDataSize))
send_count++;
}

14
piprotocol.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Protocol, input/output channel (COM, UDP)
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,10 +22,10 @@
#include "piserial.h"
#include "piethernet.h"
#include "pipacketextractor.h"
#include "pitimer.h"
#include "piconfig.h"
#include "math.h"
#include "piobject.h"
class PIProtocol;
@@ -67,8 +67,8 @@ public:
EVENT_HANDLER0(PIProtocol, void, stopReceive);
void setExpectedFrequency(float frequency); // for connection quality diagnostic
void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setReadData(headerPtr, headerSize, dataSize);}
void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setReadData(headerPtr, headerSize, dataSize);}
void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext.setPacketData(headerPtr, headerSize, dataSize);}
void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext.setPacketData(headerPtr, headerSize, dataSize);}
void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet
void setReceiverParameters(PIFlags<PISerial::Parameters> parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;}
@@ -87,7 +87,8 @@ public:
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);
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);
void setName(const PIString & name) {protName = name; PIObject::setName(name);}
PIString name() const {return protName;}
@@ -126,7 +127,7 @@ public:
void * receiveData() {return dataPtr;}
void * sendData() {return sendDataPtr;}
PIByteArray lastHeader() {if (ser != 0) return ser->lastHeader(); return PIByteArray();}
PIByteArray lastHeader() {return packet_ext.lastHeader();}
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
@@ -169,6 +170,7 @@ private:
void changeDisconnectTimeout();
ReceiveFunc ret_func;
PIPacketExtractor packet_ext;
PITimer * diagTimer, * sendTimer;
PIMultiProtocolBase * mp_owner;
PIProtocol::Type type_send, type_rec;

177
piserial.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
COM
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,32 +20,48 @@
#include "piserial.h"
PISerial::PISerial(PIString name, void * data_, SerialFunc slot, SerialHeaderFunc slot_header): PIThread() {
PISerial::PISerial(const PIString & device, void * data_, ReadRetFunc slot): PIIODevice(device, ReadWrite) {
piMonitor.serials++;
setPriority(piHigh);
path_ = device;
data = data_;
devName = name;
fd = -1;
missed = 0;
dataSize = headerSize = 0;
headerPtr = 0;
ret_func = slot;
ret_func_header = slot_header;
params = 0;
vtime = 1;
ret_func_ = slot;
#ifdef WINDOWS
hCom = 0;
#endif
ispeed = ospeed = S115200;
init();
}
PISerial::PISerial(void * data_, ReadRetFunc slot): PIIODevice("", ReadWrite) {
piMonitor.serials++;
setPriority(piHigh);
data = data_;
fd = -1;
headerPtr = 0;
params = 0;
vtime = 1;
ret_func_ = slot;
#ifdef WINDOWS
hCom = 0;
#endif
ispeed = ospeed = S115200;
init();
}
PISerial::~PISerial() {
piMonitor.serials--;
terminate();
}
void PISerial::terminate() {
if (!initialized()) return;
bool PISerial::closeDevice() {
if (!isInitialized()) return true;
if (isRunning()) {
stop();
PIThread::terminate();
@@ -60,10 +76,11 @@ void PISerial::terminate() {
#else
if (fd != -1) {
tcsetattr(fd, TCSANOW, &sdesc);
close(fd);
::close(fd);
fd = -1;
}
#endif
return true;
}
@@ -85,79 +102,51 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
}
void PISerial::begin() {
allReaded = addSize = curInd = 0;
first = false;
packetSize = headerSize + dataSize;
if (headerSize > 0) mheader.resize(headerSize);
if (!init()) stop();
}
void PISerial::run() {
if (dataSize == 0) return;
while (allReaded < packetSize + addSize) {
#ifdef WINDOWS
WaitCommEvent(hCom, 0, 0);
ReadFile(hCom, &buffer[allReaded], SERIAL_BUFFER_SIZE, &readed, 0);
#else
readed = read(fd, &buffer[allReaded], SERIAL_BUFFER_SIZE);
#endif
allReaded += readed;
}
if (headerSize > 0) {
if (allReaded + curInd >= SERIAL_BUFFER_SIZE) {
memcpy(sbuffer, buffer, SERIAL_BUFFER_SIZE);
memcpy(buffer, &sbuffer[SERIAL_BUFFER_SIZE - packetSize], allReaded);
allReaded = packetSize;
addSize = curInd = 0;
bool PISerial::read(void * data, int size, double timeout_ms) {
if (data == 0) return false;
int ret, all = 0;
if (timeout_ms > 0.) {
setReadIsBlocking(false);
all = ::read(fd, data, 1);
timer.reset();
while (all < size && timer.elapsed_m() < timeout_ms) {
ret = ::read(fd, &((uchar * )data)[all], size - all);
if (ret > 0) all += ret;
else msleep(1);
}
while (!ret_func_header(data, (uchar * )headerPtr, &buffer[curInd], headerSize)) {
curInd++; missed++;
if (curInd > addSize) {
addSize += packetSize;
return;
}
}
memcpy(mheader.data(), &buffer[curInd + headerSize], headerSize);
if (!ret_func(data, &buffer[curInd + headerSize], dataSize)) {
curInd++; missed++;
return;
}
memcpy(sbuffer, buffer, allReaded);
memcpy(buffer, &sbuffer[packetSize + curInd], allReaded);
allReaded -= packetSize + curInd;
curInd = addSize = 0;
return (all == size);
} else {
ret_func(data, buffer, dataSize);
memcpy(sbuffer, buffer, allReaded);
memcpy(buffer, &sbuffer[packetSize], allReaded);
allReaded -= packetSize;
setReadIsBlocking(true);
all = ::read(fd, data, 1);
while (all < size) {
ret = ::read(fd, &((uchar * )data)[all], size - all);
if (ret > 0) all += ret;
}
return (all == size);
}
return false;
}
void PISerial::end() {
terminate();
}
bool PISerial::init() {
bool PISerial::openDevice() {
#ifdef WINDOWS
hCom = CreateFileA(devName.stdString().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
DWORD da = 0, sm = 0;
if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;}
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
hCom = CreateFileA(path_.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(hCom == INVALID_HANDLE_VALUE) {
cout << "[PISerial] Unable to open \"" << devName << "\"" << endl;
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
return false;
}
fd = 0;
COMMTIMEOUTS times;
times.ReadIntervalTimeout = 1;
times.ReadIntervalTimeout = vtime;
times.ReadTotalTimeoutConstant = 1;
times.ReadTotalTimeoutMultiplier = 0;
times.WriteTotalTimeoutConstant = 0;
times.WriteTotalTimeoutMultiplier = 1;
times.WriteTotalTimeoutConstant = 1;
times.WriteTotalTimeoutMultiplier = 0;
if (SetCommTimeouts(hCom, &times) == -1) {
cout << "[PISerial] Unable to set timeouts for \"" << devName << "\"" << endl;
piCout << "[PISerial] Unable to set timeouts for \"" << path_ << "\"" << endl;
CloseHandle(hCom);
fd = -1;
return false;
@@ -175,15 +164,22 @@ bool PISerial::init() {
}
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
if (SetCommState(hCom, &desc) == -1) {
cout << "[PISerial] Unable to set comm state for \"" << devName << "\"" << endl;
piCout << "[PISerial] Unable to set comm state for \"" << path_ << "\"" << endl;
CloseHandle(hCom);
fd = -1;
return false;
}
#else
fd = open(devName.data(), O_NOCTTY | O_RDWR);
int om = 0;
switch (mode_) {
case PIIODevice::ReadOnly: om = O_RDONLY; break;
case PIIODevice::WriteOnly: om = O_WRONLY; break;
case PIIODevice::ReadWrite: om = O_RDWR; break;
}
//cout << "init ser " << path_ << " mode " << om << endl;
fd = ::open(path_.data(), O_NOCTTY | om);
if(fd == -1) {
cout << "[PISerial] Unable to open \"" << devName << "\"" << endl;
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
return false;
}
fcntl(fd, F_SETFL, 0);
@@ -191,48 +187,47 @@ bool PISerial::init() {
tcgetattr(fd, &desc);
sdesc = desc;
desc.c_iflag = desc.c_oflag = desc.c_lflag = 0;
desc.c_cflag = CLOCAL | CREAD | CSIZE;
desc.c_cflag = CLOCAL | CSIZE | CS8;
if (isReadable()) desc.c_cflag |= CREAD;
if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB;
if (params[PISerial::ParityControl]) {
desc.c_iflag |= INPCK;
desc.c_cflag |= PARENB;
if (params[PISerial::ParityOdd]) desc.c_cflag |= PARODD;
}
desc.c_cc[VMIN] = 0;
desc.c_cc[VTIME] = 1;
desc.c_cc[VMIN] = 1;
desc.c_cc[VTIME] = vtime;
cfsetispeed(&desc, convertSpeed(ispeed));
cfsetospeed(&desc, convertSpeed(ospeed));
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
cout << "[PISerial] Can`t set attributes for \"" << devName << "\"" << endl;
close(fd);
piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl;
::close(fd);
return false;
}
tcflush(fd, TCIOFLUSH);
//cout << "[PISerial] Initialized " << devName << endl;
//piCout << "[PISerial] Initialized " << path_ << endl;
#endif
return true;
}
bool PISerial::send(uchar * data, int size) {
//cout << "[PISerial] send size: " << sizeof(data) << endl;
if (fd == -1) {
//cout << "[PISerial] Can`t write to uninitialized COM" << endl;
return false;
int PISerial::write(const void * data, int max_size, bool wait) {
//piCout << "[PISerial] send size: " << sizeof(data) << endl;
if (fd == -1 || !canWrite()) {
//piCout << "[PISerial] Can`t write to uninitialized COM" << endl;
return -1;
}
#ifdef WINDOWS
DWORD wrote;
WriteFile(hCom, data, size, &wrote, 0);
WriteFile(hCom, data, max_size, &wrote, 0);
#else
int wrote;
wrote = write(fd, data, size);
wrote = ::write(fd, data, max_size);
if (wait) tcdrain(fd);
#endif
if ((int)wrote != size) {
//cout << "[PISerial] Error while sending" << endl;
return false;
}
//cout << "[PISerial] Wrote " << wrote << " bytes in " << devName << endl;
return true;
return (int)wrote;
//piCout << "[PISerial] Error while sending" << endl;
//piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl;
}

85
piserial.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
COM
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,8 +20,8 @@
#ifndef PISERIAL_H
#define PISERIAL_H
#include "pithread.h"
#include "pistring.h"
#include "pitimer.h"
#include "piiodevice.h"
#ifndef WINDOWS
# include <termios.h>
# include <fcntl.h>
@@ -42,16 +42,12 @@
# define B256000 256000
#endif
#define SERIAL_BUFFER_SIZE 4096
typedef bool (*SerialFunc)(void * , uchar * , int );
typedef bool (*SerialHeaderFunc)(void * , uchar * , uchar * , int );
class PISerial: public PIThread {
class 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)"
PISerial(PIString name = "serial", void * data = 0, SerialFunc slot = 0, SerialHeaderFunc slot_header = headerValidate);
PISerial(const PIString & device, void * data = 0, ReadRetFunc slot = 0);
PISerial(void * data = 0, ReadRetFunc slot = 0);
~PISerial();
enum Parameters {ParityControl = 0x01, ParityOdd = 0x02, TwoStopBits = 0x04};
@@ -69,31 +65,59 @@ public:
S115200 = 115200
};
void setSlot(SerialFunc func) {ret_func = func;}
void setData(void * d) {data = d;}
//void setSlot(SerialFunc func) {ret_func = func;}
void setSpeed(PISerial::Speed speed) {ospeed = ispeed = speed;}
void setOutSpeed(PISerial::Speed speed) {ospeed = speed;}
void setInSpeed(PISerial::Speed speed) {ispeed = speed;}
void setDevice(const PIString & dev) {devName = dev;}
void setDevice(const PIString & dev) {path_ = dev;}
void setParameters(PIFlags<PISerial::Parameters> parameters) {params = parameters;}
void setData(void * d) {data = d;}
void setReadData(void * headerPtr, int headerSize, int dataSize) {this->headerPtr = headerPtr; this->headerSize = headerSize; this->dataSize = dataSize;}
void setParameter(PISerial::Parameters parameter, bool on = true) {params.setFlag(parameter, on);}
void setVTime(int t) {vtime = t;}
bool send(uchar * data, int size);
bool init();
bool initialized() const {return fd != -1;}
void terminate();
#ifdef WINDOWS
void setReadIsBlocking(bool yes) {
COMMTIMEOUTS times;
times.ReadIntervalTimeout = yes ? vtime : MAXDWORD;
times.ReadTotalTimeoutConstant = yes ? 1 : 0;
times.ReadTotalTimeoutMultiplier = 0;
times.WriteTotalTimeoutConstant = 1;
times.WriteTotalTimeoutMultiplier = 0;
if (isOpened()) SetCommTimeouts(hCom, &times);
}
#else
void setReadIsBlocking(bool yes) {if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK);}
#endif
PIByteArray lastHeader() {return mheader;}
ullong missedBytes() const {return missed;}
ullong missedPackets() const {return (packetSize == 0 ? 0 : missed / packetSize);}
const PIString & device() const {return path_;}
PISerial::Speed outSpeed() const {return ospeed;}
PISerial::Speed inSpeed() const {return ispeed;}
int VTime() const {return vtime;}
private:
#ifdef WINDOWS
int read(void * read_to, int max_size) {
if (!canRead()) return -1;
WaitCommEvent(hCom, 0, 0);
ReadFile(hCom, read_to, max_size, &readed, 0);
return readed;
}
#else
int read(void * read_to, int max_size) {if (!canRead()) return -1; return ::read(fd, read_to, max_size);}
#endif
bool read(void * data, int size, double timeout_ms);
int write(const void * data, int max_size, bool wait);
int write(const void * data, int max_size) {return write(data, max_size, false);}
bool send(const void * data, int size, bool wait = false) {return (write(data, size, wait) == size);}
protected:
int convertSpeed(PISerial::Speed speed);
static bool headerValidate(void * d, uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;}
void begin();
void run();
void end();
bool openDevice();
bool closeDevice();
#ifdef WINDOWS
DCB desc, sdesc;
@@ -103,18 +127,11 @@ private:
termios desc, sdesc;
uint readed;
#endif
int fd;
int fd, vtime;
PISerial::Speed ospeed, ispeed;
PIString devName;
SerialFunc ret_func;
SerialHeaderFunc ret_func_header;
uchar buffer[SERIAL_BUFFER_SIZE], sbuffer[SERIAL_BUFFER_SIZE];
PIByteArray mheader;
PITimer timer;
void * headerPtr, * data;
int dataSize, headerSize, packetSize, allReaded, addSize, curInd;
ullong missed;
PIFlags<PISerial::Parameters> params;
bool first;
};

2
pisignals.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Signals
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

2
pisignals.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Signals
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

54
pistring.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
String
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -83,7 +83,7 @@ PIString & PIString::operator +=(const wchar_t * str) {
break;
}
}
delete c;
delete[] c;
return *this;
}
@@ -313,6 +313,30 @@ PIString PIString::toLowerCase() const {
}
int PIString::lengthAscii() const {
int j = 0;
for (int i = 0; i < size_s(); ++i, ++j)
if (!at(i).isAscii()) ++j;
return j;
}
const char * PIString::data() const {
PIByteArray & d_(*(const_cast<PIByteArray * >(&data_)));
d_.clear();
for (int i = 0, j = 0; i < size_s(); ++i, ++j) {
if (at(i).isAscii())
d_.push_back(uchar(at(i).toAscii()));
else {
d_.push_back((at(i).toCharPtr()[0])); ++j;
d_.push_back((at(i).toCharPtr()[1]));
}
}
d_.push_back(uchar('\0'));
return (const char * )d_.data();
}
string PIString::convertToStd() const {
string s;
if (size() > 0) {
@@ -332,7 +356,7 @@ string PIString::convertToStd() const {
char PIString::toChar() const {
PIString s(toNativeDecimalPoints());
char v;
sscanf(s.stdString().c_str(), "%c", &v);
sscanf(s.data(), "%c", &v);
return v;
}
@@ -340,9 +364,9 @@ char PIString::toChar() const {
short PIString::toShort() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
short v;
if (s.left(2) == "0x") {sscanf(s.stdString().c_str(), "%hx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.stdString().c_str(), "%ho", &v); return v;}
sscanf(s.stdString().c_str(), "%hd", &v);
if (s.left(2) == "0x") {sscanf(s.data(), "%hx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%ho", &v); return v;}
sscanf(s.data(), "%hd", &v);
return v;
}
@@ -350,9 +374,9 @@ short PIString::toShort() const {
int PIString::toInt() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
int v;
if (s.left(2) == "0x") {sscanf(s.stdString().c_str(), "%x", &v); return v;}
if (s.left(1) == "0") {sscanf(s.stdString().c_str(), "%o", &v); return v;}
sscanf(s.stdString().c_str(), "%d", &v);
if (s.left(2) == "0x") {sscanf(s.data(), "%x", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%o", &v); return v;}
sscanf(s.data(), "%d", &v);
return v;
}
@@ -360,9 +384,9 @@ int PIString::toInt() const {
long PIString::toLong() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
long v;
if (s.left(2) == "0x") {sscanf(s.stdString().c_str(), "%lx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.stdString().c_str(), "%lo", &v); return v;}
sscanf(s.stdString().c_str(), "%ld", &v);
if (s.left(2) == "0x") {sscanf(s.data(), "%lx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%lo", &v); return v;}
sscanf(s.data(), "%ld", &v);
return v;
}
@@ -370,9 +394,9 @@ long PIString::toLong() const {
llong PIString::toLLong() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
llong v;
if (s.left(2) == "0x") {sscanf(s.stdString().c_str(), "%llx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.stdString().c_str(), "%llo", &v); return v;}
sscanf(s.stdString().c_str(), "%lld", &v);
if (s.left(2) == "0x") {sscanf(s.data(), "%llx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%llo", &v); return v;}
sscanf(s.data(), "%lld", &v);
return v;
}

19
pistring.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
String
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -126,8 +126,12 @@ public:
PIString & insert(const int index, const char * c) {return insert(index, PIString(c));}
PIString & expandRightTo(const int len, const PIChar & c) {if (len > length()) resize(len, c); return *this;}
PIString & expandLeftTo(const int len, const PIChar & c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;}
PIString & reverse() {PIString str(*this); clear(); piForeachR (const PIChar & c, str) push_back(c); return *this;}
PIString reversed() const {PIString str(*this); str.reverse(); return str;}
const char * data() {return convertToStd().c_str();}
//const char * data() {return convertToStd().c_str();}
int lengthAscii() const;
const char * data() const;
const string stdString() const {return convertToStd();}
wstring stdWString() const {return convertToWString();}
PIByteArray toByteArray() {string s(convertToStd()); return PIByteArray(s.c_str(), s.length());}
@@ -153,15 +157,15 @@ public:
int length() const {return size();}
bool isEmpty() const {return (size() == 0 || *this == "");}
bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().stdString().c_str()) > 0. || s.trimmed().toLowerCase() == "true") return true; return false;}
bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true") return true; return false;}
char toChar() const;
short toShort() const;
int toInt() const;
long toLong() const;
llong toLLong() const;
float toFloat() const {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().stdString().c_str());}
double toDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().stdString().c_str());}
ldouble toLDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().stdString().c_str());}
float toFloat() const {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().data());}
double toDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
ldouble toLDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
//inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;}
PIString & setNumber(const int value) {clear(); *this += itos(value); return *this;}
@@ -188,11 +192,14 @@ private:
string convertToStd() const;
wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;}
PIByteArray data_;
//string std_string;
//wstring std_wstring;
};
inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
inline std::istream & operator >>(std::istream & s, PIString & v) {string ss; s >> ss; v << PIString(ss); return s;}
inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;}

8
pisystemmonitor.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Process resource monitor
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -39,10 +39,10 @@ bool PISystemMonitor::startOnProcess(int pID) {
stop();
pID_ = pID;
#ifndef WINDOWS
file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIFile::Read);
filem.open("/proc/" + PIString::fromNumber(pID_) + "/statm", PIFile::Read);
file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIIODevice::ReadOnly);
filem.open("/proc/" + PIString::fromNumber(pID_) + "/statm", PIIODevice::ReadOnly);
if (!file.isOpened()) {
cout << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!" << endl;
piCout << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!" << endl;
return false;
}
cycle = -1;

2
pisystemmonitor.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Process resource monitor
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

47
pithread.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Thread
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,23 +20,26 @@
#include "pithread.h"
PIThread::PIThread(bool startNow, int timer_delay): PIObject() {
PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay): PIObject() {
piMonitor.threads++;
data_ = data;
ret_func = func;
running = lockRun = false;
priority_ = piNormal;
timer = timer_delay;
if (startNow) start(timer_delay);
}
PIThread::PIThread(bool startNow, int timer_delay): PIObject() {
piMonitor.threads++;
ret_func = 0;
running = lockRun = false;
priority_ = piNormal;
timer = timer_delay;
/*addEvent("started");
addEvent("stopped");
addEventHandler<int>(HANDLER(PIThread, start));
addEventHandler(HANDLER(PIThread, startOnce));
addEventHandler(HANDLER(PIThread, stop));
addEventHandler<bool>(HANDLER(PIThread, terminate));*/
if (startNow) start(timer_delay);
}
#ifndef WINDOWS
#else
#endif
PIThread::~PIThread() {
piMonitor.threads--;
@@ -57,14 +60,17 @@ bool PIThread::start(int timer_delay) {
pthread_attr_init(&attr);
pthread_attr_setschedparam(&attr, &sparam);
if (pthread_create(&thread, &attr, thread_function, this) == 0) {
setPriority(priority_);
running = true;
return true;
}
#else
thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_function, this, 0, 0);
if (thread == 0)
return false;
setPriority(priority_);
if (thread != 0) {
setPriority(priority_);
running = true;
return true;
}
#endif
return false;
}
@@ -76,13 +82,18 @@ bool PIThread::startOnce() {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setschedparam(&attr, &sparam);
if (pthread_create(&thread, &attr, thread_function_once, this) == 0)
if (pthread_create(&thread, &attr, thread_function_once, this) == 0) {
setPriority(priority_);
running = true;
return true;
}
#else
thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_function_once, this, 0, 0);
if (thread == 0)
if (thread != 0) {
setPriority(priority_);
running = true;
return false;
setPriority(priority_);
}
#endif
return false;
}
@@ -110,6 +121,7 @@ void * PIThread::thread_function(void * t) {
while (!ct->terminating) {
if (ct->lockRun) ct->mutex_.lock();
ct->run();
if (ct->ret_func != 0) ct->ret_func(ct->data_);
if (ct->lockRun) ct->mutex_.unlock();
if (ct->timer > 0) msleep(ct->timer);
}
@@ -133,6 +145,7 @@ void * PIThread::thread_function_once(void * t) {
raiseEvent(ct, "started");
if (ct->lockRun) ct->mutex_.lock();
ct->run();
if (ct->ret_func != 0) ct->ret_func(ct->data_);
if (ct->lockRun) ct->mutex_.unlock();
raiseEvent(ct, "stopped");
ct->end();

21
pithread.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Thread
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,8 +30,11 @@ inline void msleep(int msecs) {Sleep(msecs);}
inline void msleep(int msecs) {usleep(msecs * 1000);}
#endif
typedef void (*ThreadFunc)(void * );
class PIThread: public PIObject {
public:
PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1);
PIThread(bool startNow = false, int timer_delay = -1);
~PIThread();
@@ -52,11 +55,16 @@ public:
//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);
void setData(void * d) {data_ = d;}
void setSlot(ThreadFunc func) {ret_func = func;}
void setPriority(PIThread::Priority prior);
PIThread::Priority priority() const {return priority_;}
bool isRunning() const {return running;}
@@ -69,19 +77,20 @@ public:
EVENT_HANDLER0(PIThread, void, unlock) {mutex_.unlock();}
PIMutex & mutex() {return mutex_;}
private:
virtual void begin() {;} // executed at start
virtual void run() {;} // main loop
virtual void end() {;} // executed at finish
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
volatile bool terminating, running, lockRun;
int timer, policy;
void * data_;
PIMutex mutex_;
PIThread::Priority priority_;
ThreadFunc ret_func;
#ifndef WINDOWS
pthread_t thread;
sched_param sparam;

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Timer
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -56,11 +56,15 @@ PITimer::~PITimer() {
#ifndef WINDOWS
void PITimer::start(double msecs) {
if (ti == 0) return;
if (ti == 0 || msecs < 0) return;
spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000;
spec.it_interval.tv_sec = (time_t)(msecs / 1000);
spec.it_value = spec.it_interval;
ti = timer_create(CLOCK_REALTIME, &se, &timer);
if (ti == -1) {
piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString() << endl;
return;
}
timer_settime(timer, 0, &spec, 0);
running = true;
}
@@ -119,11 +123,10 @@ void PITimer::run() {
double PITimer::elapsed_n() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (t_cur * 1000000. - t_st * 1000000.);
return (t_cur - t_st) * 1000000.;
#else
clock_gettime(0, &t_cur);
return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec) -
(t_st.tv_sec * 1.e+9 + t_st.tv_nsec);
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+9 + (t_cur.tv_nsec - t_st.tv_nsec);
#endif
}
@@ -131,11 +134,10 @@ double PITimer::elapsed_n() {
double PITimer::elapsed_u() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (t_cur * 1000. - t_st * 1000.);
return (t_cur - t_st) * 1000.;
#else
clock_gettime(0, &t_cur);
return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3)) -
(t_st.tv_sec * 1.e+6 + (t_st.tv_nsec / 1.e+3));
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+6 + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+3;
#endif
}
@@ -146,8 +148,7 @@ double PITimer::elapsed_m() {
return (double)(t_cur - t_st);
#else
clock_gettime(0, &t_cur);
return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6)) -
(t_st.tv_sec * 1.e+3 + (t_st.tv_nsec / 1.e+6));
return (t_cur.tv_sec - t_st.tv_sec) * 1.e+3 + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+6;
#endif
}
@@ -155,11 +156,102 @@ double PITimer::elapsed_m() {
double PITimer::elapsed_s() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (t_cur / 1000. - t_st / 1000.);
return (t_cur - t_st) / 1000.;
#else
clock_gettime(0, &t_cur);
return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9)) -
(t_st.tv_sec + (t_st.tv_nsec / 1.e+9));
return (t_cur.tv_sec - t_st.tv_sec) + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+9;
#endif
}
double PITimer::reset_time_n() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return t_st * 1000000.;
#else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+9 + t_st.tv_nsec;
#endif
}
double PITimer::reset_time_u() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (t_cur - t_st) * 1000.;
#else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+6 + t_st.tv_nsec / 1.e+3;
#endif
}
double PITimer::reset_time_m() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (double)(t_cur - t_st);
#else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+3 + t_st.tv_nsec / 1.e+6;
#endif
}
double PITimer::reset_time_s() {
#ifdef WINDOWS
t_cur = GetCurrentTime();
return (t_cur - t_st) / 1000.;
#else
clock_gettime(0, &t_cur);
return t_st.tv_sec + t_st.tv_nsec / 1.e+9;
#endif
}
double PITimer::elapsed_system_n() {
#ifdef WINDOWS
long t_cur = GetCurrentTime();
return (t_cur * 1000000.);
#else
timespec t_cur;
clock_gettime(0, &t_cur);
return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec);
#endif
}
double PITimer::elapsed_system_u() {
#ifdef WINDOWS
long t_cur = GetCurrentTime();
return (t_cur * 1000.);
#else
timespec t_cur;
clock_gettime(0, &t_cur);
return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3));
#endif
}
double PITimer::elapsed_system_m() {
#ifdef WINDOWS
long t_cur = GetCurrentTime();
return (double)t_cur;
#else
timespec t_cur;
clock_gettime(0, &t_cur);
return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6));
#endif
}
double PITimer::elapsed_system_s() {
#ifdef WINDOWS
long t_cur = GetCurrentTime();
return (t_cur / 1000.);
#else
timespec t_cur;
clock_gettime(0, &t_cur);
return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9));
#endif
}
@@ -186,6 +278,31 @@ PIDate currentDate() {
}
PIString PITime::toString(const PIString & format) {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(hours));
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(minutes));
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(seconds));
return ts;
}
PIString PIDate::toString(const PIString & format) {
PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).expandLeftTo(2, '0'));
ts.replace("y", PIString::fromNumber(year));
ts.replace("mm", PIString::fromNumber(month).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(month));
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(day));
return ts;
}
PIString time2string(const PITime & time, const PIString & format) {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0'));

View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Timer
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,12 +32,14 @@ struct PITime {
int seconds;
int minutes;
int hours;
PIString toString(const PIString & format = "h:mm:ss");
};
struct PIDate {
int day;
int month;
int year; // since 1900
PIString toString(const PIString & format = "d.mm.yyyy");
};
class PITimer
@@ -77,11 +79,21 @@ public:
double elapsed_m(); // miliseconds
double elapsed_s(); // seconds
double reset_time_n(); // nanoseconds
double reset_time_u(); // microseconds
double reset_time_m(); // miliseconds
double reset_time_s(); // seconds
static double elapsed_system_n(); // nanoseconds
static double elapsed_system_u(); // microseconds
static double elapsed_system_m(); // miliseconds
static double elapsed_system_s(); // seconds
private:
#ifdef WINDOWS
void run();
long int t_st, t_cur;
long t_st, t_cur;
#else
static void timer_event(sigval e);
@@ -109,7 +121,7 @@ private:
PITime currentTime();
PIDate currentDate();
PIString time2string(const PITime & time, const PIString & format = "h:mm:ss");
PIString date2string(const PIDate & date, const PIString & format = "d.mm.yyyy");
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
#endif // PITIMER_H

6
pivariable.cpp Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Variable, Struct (simple serialization)
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@ bool PIVariant::operator ==(const PIVariant & v) const {
case PIVariant::String: return vString == v.vString;
case PIVariant::StringList: return vStringList == v.vStringList;
};
return false;
}
@@ -84,6 +85,7 @@ PIString PIVariant::stringValue() const {
case PIVariant::String: return vString;
case PIVariant::StringList: return vStringList.join("%|%");
};
return vString;
}
@@ -214,7 +216,7 @@ void PIVariable::writeVariable(char * dest) {
void PIStruct::parseFile(const PIString & file) {
PIConfig conf(file, PIFile::Read);
PIConfig conf(file, PIIODevice::ReadOnly);
PIVariable var;
PIString ts;
uint sz = 0;

2
pivariable.h Normal file → Executable file
View File

@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Variable, Struct (simple serialization)
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

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

Binary file not shown.

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

Binary file not shown.