23.06.2014 - PICodeParser, PICodeInfo, PIConnection, new binary "pip_cmg"

This commit is contained in:
peri4
2014-06-23 21:08:27 +04:00
parent 2e5e75c4c4
commit 15a20d40ac
56 changed files with 10315 additions and 760 deletions

View File

@@ -1,2 +1,2 @@
Pelipenko Ivan (peri4) peri4ko@gmail.com Pelipenko Ivan (peri4) peri4ko@yandex.ru
Bychkov Andrey (blizer) wapmobil@gmail.com Bychkov Andrey () work.a.b@yandex.ru

View File

@@ -2,7 +2,7 @@ project(pip)
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} .) include_directories(${CMAKE_CURRENT_SOURCE_DIR} .)
include(CheckFunctionExists) include(CheckFunctionExists)
set(VERSION "0.0308") set(VERSION "0.0400")
set(SOVERSION ${VERSION}) set(SOVERSION ${VERSION})
set(CMAKE_BUILD_TYPE "Release") set(CMAKE_BUILD_TYPE "Release")
set(LIBS) set(LIBS)
@@ -83,7 +83,8 @@ else ()
if (NOT APPLE) if (NOT APPLE)
list(APPEND LIBS rt) list(APPEND LIBS rt)
endif() endif()
add_definitions("-Wall -g3") add_definitions("-Wall")
add_definitions("-g3")
add_library(pip SHARED ${CPPS}) add_library(pip SHARED ${CPPS})
endif () endif ()
endif () endif ()
@@ -92,11 +93,11 @@ target_link_libraries(pip ${LIBS})
# Test program # Test program
#find_package(Qt4 REQUIRED) find_package(Qt4 REQUIRED)
#include_directories(${QT_INCLUDES}) include_directories(${QT_INCLUDES})
add_executable(pip_test "main.cpp") add_executable(pip_test "main.cpp")
#target_link_libraries(pip_test pip ${QT_QTCORE_LIBRARY}) target_link_libraries(pip_test pip ${QT_QTCORE_LIBRARY})
target_link_libraries(pip_test pip) #target_link_libraries(pip_test pip)
add_subdirectory(system_test) add_subdirectory(system_test)

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = PIP
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 0.3.8 PROJECT_NUMBER = 0.4.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a

0
clean.bat Executable file → Normal file
View File

View File

@@ -112,7 +112,7 @@ void writeModel(PICodeParser & parser, const PIString out) {
PIFile f(out + ".cpp"); PIFile f(out + ".cpp");
f.clear(); f.clear();
f.open(PIIODevice::WriteOnly); f.open(PIIODevice::WriteOnly);
f << "// Generated by \"PIP Code model generator\" " << currentDateTime().toString("dd.MM.yyyy hh:mm:ss\n\n"); f << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n");
f << "#include <string.h>\n#include \"" << out << ".h\"\n\nusing namespace PICodeInfo;\n\n"; f << "#include <string.h>\n#include \"" << out << ".h\"\n\nusing namespace PICodeInfo;\n\n";
piForeachC (PIString & i, inc_files) piForeachC (PIString & i, inc_files)
f << "#include \"" << i << "\"\n"; f << "#include \"" << i << "\"\n";
@@ -180,7 +180,7 @@ void writeModel(PICodeParser & parser, const PIString out) {
f.setPath(out + ".h"); f.setPath(out + ".h");
f.clear(); f.clear();
f.open(PIIODevice::WriteOnly); f.open(PIIODevice::WriteOnly);
f << "// Generated by \"PIP Code model generator\" " << currentDateTime().toString("dd.MM.yyyy hh:mm:ss\n\n"); f << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n");
f << "#ifndef " << defname << "\n#define " << defname << "\n\n"; f << "#ifndef " << defname << "\n#define " << defname << "\n\n";
f << "#include \"pivariant.h\"\n#include \"picodeinfo.h\"\n\n"; f << "#include \"pivariant.h\"\n#include \"picodeinfo.h\"\n\n";
piForeachC (PICodeParser::Entity * e, ventities) piForeachC (PICodeParser::Entity * e, ventities)

View File

@@ -37,11 +37,11 @@ int main(int argc, char * argv[]) {
execFunction(&tm, "stop"); execFunction(&tm, "stop");
execFunction(&tm, "stop_"); execFunction(&tm, "stop_");
piMSleep(1000);*/ piMSleep(1000);*/
typedef std::pair<PIString, PICodeInfo::ClassInfo * > mpair; typedef PIMap<PIString, PICodeInfo::ClassInfo* >::value_type mpair;
piForeachC (mpair & i, *(PICodeInfo::classesInfo)) piForeachC (mpair & i, *(PICodeInfo::classesInfo))
piCout << *i.second; piCout << *i.second;
piCout << "\n\n"; piCout << "\n\n";
typedef std::pair<PIString, PICodeInfo::EnumInfo * > epair; typedef PIMap<PIString, PICodeInfo::EnumInfo * >::value_type epair;
piForeachC (epair & i, *(PICodeInfo::enumsInfo)) piForeachC (epair & i, *(PICodeInfo::enumsInfo))
piCout << *i.second; piCout << *i.second;
return 0; return 0;

File diff suppressed because it is too large Load Diff

100
code_model_generator/test.h Normal file
View File

@@ -0,0 +1,100 @@
// Generated by "PIP Code model generator" 29.04.2014 18:03:05
#ifndef TEST_H
#define TEST_H
#include "pivariant.h"
#include "picodeinfo.h"
class PIMutex;
class PIBitArray;
class PIHuffman;
class PIByteArray;
class PIChar;
class PIString;
class PIStringList;
class PISystemTime;
struct PITime;
struct PIDate;
struct PIDateTime;
class Solver;
class PIFFT;
class PIVariant;
class PIObject;
class PIThread;
class PITimer;
class PIKbdListener;
class PIIODevice;
class PISerial;
class PIFile;
class PIProcess;
class PIEthernet;
class PIPacketExtractor;
class PIConfig;
class PIMultiProtocolBase;
class PIProtocol;
class PIDiagnostics;
class PISystemMonitor;
class PIConsole;
class PICLI;
class PIEvaluatorContent;
class PIEvaluator;
class PIMultiProtocol;
class PIRepeater;
class PICodec;
class PIPeer;
class PIBinaryLog;
class PIUSB;
PIVariant execFunction(PIMutex * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIBitArray * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIHuffman * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIByteArray * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIChar * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIString * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIStringList * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PISystemTime * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PITime * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIDate * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIDateTime * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(Solver * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIFFT * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIVariant * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIObject * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIThread * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PITimer * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIKbdListener * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIIODevice * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PISerial * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIFile * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIProcess * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIEthernet * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIPacketExtractor * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIConfig * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIMultiProtocolBase * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIProtocol * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIDiagnostics * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PISystemMonitor * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIConsole * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PICLI * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIEvaluatorContent * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIEvaluator * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIMultiProtocol * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIRepeater * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PICodec * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIPeer * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIBinaryLog * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
PIVariant execFunction(PIUSB * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());
class __ClassInfo_TEST_H_Initializer__ {
public:
__ClassInfo_TEST_H_Initializer__();
static bool _inited_;
};
static __ClassInfo_TEST_H_Initializer__ __classinfo_test_h_initializer__;
#endif // TEST_H

223
main.cpp
View File

@@ -46,90 +46,119 @@ class ElementD: public PIObject {
#include "pip.h" #include "pip.h"
#include "pivariant.h" #include "pivariant.h"
/*
Test::PIVariant<> * pv;
template <typename T>
Test::PIVariant<T> newVariant(const T & v) {return Test::PIVariant<T>(v);}
template <typename T>
Test::PIVariant<T> * castVariant(Test::__PIVariantBase * v, const T & t) {return static_cast<Test::PIVariant<T> * >(v);}
*/
#include "picodeparser.h" #include "picodeparser.h"
#include "pidir.h"
#include "piconnection.h"
#include <QList>
#define S(a, b) a#b bool readed(void*, uchar * data, int size) {
piCout << Hex << "readed" << PIByteArray(data, size);
enum TypeFlag {NoFlag, Const = 0x01, Static = 0x02, Mutable = 0x04, Volatile = 0x08, Inline = 0x10, Virtual = 0x20}; //piCout << PIString((char*)data, size);
typedef PIFlags<TypeFlag> TypeFlags; return true;
struct TypeInfo {
TypeInfo() {flags = 0;}
PIString name;
PIString type;
TypeFlags flags;
};
struct FunctionInfo {
PIString name;
TypeInfo return_type;
PIVector<TypeInfo> arguments;
};
struct ClassInfo {
PIString name;
PIStringList parents;
PIVector<TypeInfo> variables;
PIVector<FunctionInfo> functions;
};
inline PICout operator <<(PICout s, const TypeInfo & v) {
if (v.flags[Inline]) s << "inline ";
if (v.flags[Virtual]) s << "virtual ";
if (v.flags[Static]) s << "static ";
if (v.flags[Const]) s << "const ";
if (v.flags[Mutable]) s << "mutable ";
if (v.flags[Volatile]) s << "volatile ";
s << v.type;
if (!v.name.isEmpty())
s << " " << v.name;
return s;
}
inline PICout operator <<(PICout s, const ClassInfo & v) {
s.setControl(0, true);
s << "class " << v.name;
if (!v.parents.isEmpty()) {
s << ": ";
bool first = true;
piForeachC (PIString & i, v.parents) {
if (first) first = false;
else s << ", ";
s << i;
}
s << " {\n";
piForeachC (FunctionInfo & i, v.functions) {
s << Tab << i.return_type << " " << i.name << "(";
bool fa = true;
piForeachC (TypeInfo & a, i.arguments) {
if (fa) fa = false;
else s << ", ";
s << a;
}
s << ");\n";
}
if (!v.functions.isEmpty() && !v.variables.isEmpty())
s << "\n";
piForeachC (TypeInfo & i, v.variables) {
s << Tab << i << ";\n";
}
s << "}\n";
}
s.restoreControl();
return s;
} }
class A: public PIObject {
PIOBJECT(A)
public:
EVENT_HANDLER2(void, cr, const PIString &, from, const PIByteArray &, data) {
piCout << "A readed" << from << Hex << data;
}
EVENT_HANDLER2(void, per, uchar *, data, int, size) {
piCout << "A readed" << size << ":\"" << PIString((const char *)data, size) << "\"" << NewLine;
//piCout << "A readed \"";
}
};
class TC: public PIConnection {
public:
TC() {
PIPacketExtractor * pe = addFilter("h&f", addDevice("file://piiodevice.h", PIIODevice::ReadOnly, false), PIPacketExtractor::HeaderAndFooter);
pe->setHeader(PIString("//!").toByteArray());
pe->setFooter(PIString("\n").toByteArray());
pe = addFilter(" h ", "file://piiodevice.h", PIPacketExtractor::Header);
addChannel(pe, addDevice("file://out.txt", PIIODevice::WriteOnly));
pe->setHeader(PIString("PI").toByteArray());
pe->setPayloadSize(3);
startAllThreadedReads();
}
virtual void dataReceived(const PIString & from, const PIByteArray & data) {
piCout << "dataReceived" << from << (data.size());
}
virtual void packetReceived(const PIString & from, const PIByteArray & data) {
piCout << "packetReceived" << from << (data.size()) << PIString(data);
}
virtual bool filterValidatePayload(const PIString & filter_name, uchar * rec, int size) {
//piCout << "filterValidatePayload" << filter_name << PIString((char*)rec, size);
if (filter_name == " h ") return PIString((char*)rec, size) == "IOD";
return false;
}
};
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
PIString s("this\t :is \n(SPARTA)!"); /*A a_;
piCout << s.findCWord("this"); PIFile file("piiodevice.h", PIIODevice::ReadOnly);
piCout << s.findCWord("is"); PIByteArray header = PIString("PI").toByteArray();
piCout << s.findCWord("SPARTA"); PIByteArray footer = PIString("}").toByteArray();
piCout << s.findCWord("SPARTA!"); PIPacketExtractor pe(&file);
//pe.setPacketData(header.data(), header.size_s(), 10);
pe.setSplitMode(PIPacketExtractor::Footer);
pe.setHeader(header);
pe.setFooter(footer);
pe.setPayloadSize(3);
pe.setThreadedReadBufferSize(40);
//pe.setBufferSize(256);
//pe.setPacketData(0, 0, 20);
CONNECT2(void, uchar * , int , &pe, packetReceived, &a_, per)
pe.startThreadedRead();
piMSleep(500);*/
TC tc;
piMSleep(500);
piCout << tc.makeConfig();
return 0;
/*tm = PISystemTime::current();
for (int i = 0; i < 10000000; ++i) {
ql.append(i*10);
ql.prepend(i*10 + 1);
}
piCout << (PISystemTime::current() - tm).toMicroseconds();
*/
//tm = PISystemTime::current();
/*for (int i = 0; i < 100000000; ++i) {
pl.append(i*10);
pl.prepend(i*10 + 1);
}*/
//PICodeParser cd_;
//cd.includeDirectory("../qpicalculator");
//cd_.parseFile("piincludes.h");
//piCout << (PISystemTime::current() - tm).toMilliseconds();
/*piCout << NewLine;
piForeachCA (i, pl)
piCout << i;
pl.remove(1, 2).prepend(111).prepend(222);
pl.remove(1, 1);
piCout << NewLine;
piForeachCA (i, pl)
piCout << i;*/
/*piCout << NewLine;
for (int i = 0; i < pl.size_s(); ++i)
piCout << pl[i];
*/
/*PIEthernet eth(PIEthernet::UDP);
eth.setReadAddress("192.168.0.30:4001");
eth.setSendAddress("192.168.0.50:4001");
eth.startThreadedRead(readed);
piCout << "Connected";
//eth.send(PIString("This is test string!\n").toByteArray());
FOREVER_WAIT*/
if (argc < 2) return 0; if (argc < 2) return 0;
PICodeParser cd; PICodeParser cd;
//cd.includeDirectory("../qpicalculator"); //cd.includeDirectory("../qpicalculator");
@@ -137,48 +166,6 @@ int main (int argc, char * argv[]) {
piForeachC (PICodeParser::Enum & e, cd.enums) piForeachC (PICodeParser::Enum & e, cd.enums)
piCout << e.name << e.members; piCout << e.name << e.members;
ClassInfo ci;
PICodeParser::Entity * e = cd.findEntityByName("PITimer");
if (!e) return 0;
ci.name = e->name;
piForeachC (PICodeParser::Entity * p, e->parents)
ci.parents << p->name;
piForeachC (PICodeParser::Member & m, e->members) {
TypeInfo ni;
ni.name = m.name;
ni.type = m.type;
if (m.attributes[PICodeParser::Const]) ni.flags |= Const;
if (m.attributes[PICodeParser::Static]) ni.flags |= Static;
if (m.attributes[PICodeParser::Mutable]) ni.flags |= Mutable;
if (m.attributes[PICodeParser::Volatile]) ni.flags |= Volatile;
if (m.attributes[PICodeParser::Inline]) ni.flags |= Inline;
if (m.attributes[PICodeParser::Virtual]) ni.flags |= Virtual;
ci.variables << ni;
}
piForeachC (PICodeParser::Member & m, e->functions) {
FunctionInfo fi;
fi.name = m.name;
fi.return_type.type = m.type;
if (m.attributes[PICodeParser::Const]) fi.return_type.flags |= Const;
if (m.attributes[PICodeParser::Static]) fi.return_type.flags |= Static;
piForeachC (PIString & a, m.arguments_full) {
TypeInfo ni;
PIString arg(a);
arg.prepend(" ");
if (arg.find(" const ") >= 0) {
ni.flags |= Const;
arg.replaceAll(" const ", " ");
}
int ts = 0;
for (ts = arg.size_s() - 1; ts >= 0; --ts)
if (!_isCChar(arg[ts]) && !(arg[ts].isDigit())) break;
ni.name = arg.takeRight(arg.size_s() - ts - 1).trim();
ni.type = arg.trim();
fi.arguments << ni;
}
ci.functions << fi;
}
piCout << NewLine << ci;
//piCout << v.toType<float>(); //piCout << v.toType<float>();
//piCout << v.toType<float>().toType<PIString>(); //piCout << v.toType<float>().toType<PIString>();

0
make_lib.bat Executable file → Normal file
View File

0
make_rc_win.bat Executable file → Normal file
View File

View File

@@ -94,12 +94,12 @@ bool PIBinaryLog::openDevice() {
return false; return false;
} }
if (isEmpty()) piCoutObj << "Error: Empty BinLog file"; if (isEmpty()) piCoutObj << "Error: Empty BinLog file";
// startlogtime = currentSystemTime(); // startlogtime = PISystemTime::current();
play_time = 0; play_time = 0;
// nextrecord = readsRecord(); // nextrecord = readsRecord();
if (!rapidStart()) is_started = true; if (!rapidStart()) is_started = true;
} }
startlogtime = currentSystemTime(); startlogtime = PISystemTime::current();
return true; return true;
} }
@@ -119,7 +119,7 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) {
double delay; double delay;
switch (playMode()) { switch (playMode()) {
case PlayRealTime: case PlayRealTime:
pt = currentSystemTime() - startlogtime; pt = PISystemTime::current() - startlogtime;
// if (real_speedX > 0) // if (real_speedX > 0)
// for (int i=0; i<real_speedX-1; i++) pt += pt; // for (int i=0; i<real_speedX-1; i++) pt += pt;
// piCout << pt << lastrecord.timestamp << lastrecord.timestamp - pt; // piCout << pt << lastrecord.timestamp << lastrecord.timestamp - pt;
@@ -127,10 +127,10 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) {
if (lastrecord.timestamp > pt) if (lastrecord.timestamp > pt)
(lastrecord.timestamp - pt).sleep(); (lastrecord.timestamp - pt).sleep();
} else { } else {
startlogtime = currentSystemTime() - lastrecord.timestamp; startlogtime = PISystemTime::current() - lastrecord.timestamp;
is_started = true; is_started = true;
} }
// int delay = piRoundd(lastread_timestamp.toMilliseconds() - (currentSystemTime() - startlogtime).toMilliseconds()); // int delay = piRoundd(lastread_timestamp.toMilliseconds() - (PISystemTime::current() - startlogtime).toMilliseconds());
break; break;
case PlayVariableSpeed: case PlayVariableSpeed:
delay = lastrecord.timestamp.toMilliseconds() - play_time; delay = lastrecord.timestamp.toMilliseconds() - play_time;
@@ -152,7 +152,7 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) {
PIString PIBinaryLog::createNewFile() { PIString PIBinaryLog::createNewFile() {
if (!file.close()) return PIString(); if (!file.close()) return PIString();
if (open(logDir() + "/" + filePrefix() + currentDateTime().toString("yyyy_MM_dd__hh_mm_ss.binlog"), PIIODevice::WriteOnly)) if (open(logDir() + "/" + filePrefix() + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss.binlog"), PIIODevice::WriteOnly))
return file.path(); return file.path();
piCoutObj << "Can't create new file, maybe LogDir is invalid."; piCoutObj << "Can't create new file, maybe LogDir is invalid.";
return PIString(); return PIString();
@@ -162,7 +162,7 @@ PIString PIBinaryLog::createNewFile() {
int PIBinaryLog::writeBinLog(int id, const void *data, int size) { int PIBinaryLog::writeBinLog(int id, const void *data, int size) {
if (size <= 0 || !canWrite()) return -1; if (size <= 0 || !canWrite()) return -1;
PIByteArray logdata; PIByteArray logdata;
logdata << id << size << (currentSystemTime() - startlogtime) << PIByteArray::RawData(data, size); logdata << id << size << (PISystemTime::current() - startlogtime) << PIByteArray::RawData(data, size);
int res = file.write(logdata.data(), logdata.size()); int res = file.write(logdata.data(), logdata.size());
file.flush(); file.flush();
if (res > 0) return size; if (res > 0) return size;
@@ -242,7 +242,7 @@ void PIBinaryLog::restart() {
play_time = 0; play_time = 0;
file.seekToBegin(); file.seekToBegin();
checkFileHeader(); checkFileHeader();
startlogtime = currentSystemTime(); startlogtime = PISystemTime::current();
if (th) startThreadedRead(); if (th) startThreadedRead();
} }
@@ -306,6 +306,13 @@ PIBinaryLog::BinLogRecord PIBinaryLog::readRecord() {
} }
PIString PIBinaryLog::constructFullPath() const {
PIString ret(fullPathPrefix() + "://");
ret << logDir() << ":" << filePrefix() << ":" << defaultID();
return ret;
}
void PIBinaryLog::configureFromFullPath(const PIString & full_path) { void PIBinaryLog::configureFromFullPath(const PIString & full_path) {
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {

View File

@@ -117,6 +117,7 @@ public:
//! Go to begin of BinLog file //! Go to begin of BinLog file
void restart(); void restart();
PIString constructFullPath() const;
//! \handlers //! \handlers
//! \{ //! \{

View File

@@ -18,23 +18,21 @@
*/ */
#include "pibytearray.h" #include "pibytearray.h"
#include "pistring.h"
/*! \class PIByteArray /*! \class PIByteArray
* \brief Byte array * \brief Byte array
* \details This class based on PIVector<uchar> and provide some handle function * \details This class based on PIDeque<uchar> and provide some handle function
* to manipulate it. * to manipulate it.
* *
* \section PIByteArray_sec0 Usage * \section PIByteArray_sec0 Usage
* %PIByteArray can be used to store custom data and manipulate it. There are many * %PIByteArray can be used to store custom data and manipulate it. There are many
* stream operators to store/restore common types to byte array. Store operators * stream operators to store/restore common types to byte array. Store operators
* places data at the end of arraym restore operators takes data from the beginning * places data at the end of array, restore operators takes data from the beginning
* of array. * of array.
* In addition there are Base 64 convertions and checksums: * In addition there are Base 64 convertions and checksums:
* * plain 8-bit * * plain 8-bit
* * plain 32-bit * * plain 32-bit
* * CRC 8-bit
* * CRC 16-bit
* * CRC 32-bit
* *
* One of the major usage of %PIByteArray is stream functions. You can form binary * One of the major usage of %PIByteArray is stream functions. You can form binary
* packet from many types (also dynamic types, e.g. PIVector) with one line: * packet from many types (also dynamic types, e.g. PIVector) with one line:
@@ -114,13 +112,13 @@ int PIHuffman::nodeCompare(const void * f, const void * s) {
} }
PIVector<uchar> PIHuffman::compress(const PIVector<uchar> & src) { PIDeque<uchar> PIHuffman::compress(const PIDeque<uchar> & src) {
calcFrequencies(src); calcFrequencies(src);
return src; return src;
} }
void PIHuffman::calcFrequencies(const PIVector<uchar> & src) { void PIHuffman::calcFrequencies(const PIDeque<uchar> & src) {
nodes.resize(256); nodes.resize(256);
for (int i = 0; i < 256; ++i) { for (int i = 0; i < 256; ++i) {
nodes[i].parent = nodes[i].right = nodes[i].left = 0; nodes[i].parent = nodes[i].right = nodes[i].left = 0;
@@ -247,7 +245,7 @@ PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
} }
uchar PIByteArray::checksumPlain8() { uchar PIByteArray::checksumPlain8() const {
uchar c = 0; uchar c = 0;
int sz = size_s(); int sz = size_s();
for (int i = 0; i < sz; ++i) for (int i = 0; i < sz; ++i)
@@ -257,7 +255,7 @@ uchar PIByteArray::checksumPlain8() {
} }
uint PIByteArray::checksumPlain32() { uint PIByteArray::checksumPlain32() const {
uint c = 0; uint c = 0;
int sz = size_s(); int sz = size_s();
for (int i = 0; i < sz; ++i) for (int i = 0; i < sz; ++i)
@@ -267,137 +265,29 @@ uint PIByteArray::checksumPlain32() {
} }
uchar PIByteArray::checksumCRC8() { PIString PIByteArray::toString(int base) const {
const uchar CRC8Table[256] = { PIString ret;
0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97,
0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E,
0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4,
0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D,
0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11,
0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8,
0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52,
0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB,
0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA,
0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13,
0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9,
0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50,
0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C,
0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95,
0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F,
0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6,
0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED,
0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54,
0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE,
0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17,
0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B,
0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2,
0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28,
0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91,
0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0,
0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69,
0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93,
0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A,
0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56,
0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF,
0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15,
0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC};
int sz = size_s(); int sz = size_s();
ushort ret = 0xFF;
for (int i = 0; i < sz; ++i)
ret = CRC8Table[at(i) ^ ret];
return ret;
}
ushort PIByteArray::checksumCRC16() {
const ushort CRC16Table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};
int sz = size_s();
uchar nTemp;
ushort ret = 0xFFFF;
for (int i = 0; i < sz; ++i) { for (int i = 0; i < sz; ++i) {
nTemp = at(i) ^ ret; if (i > 0) ret += " ";
ret >>= 8; if (base == 2) ret += "b";
ret ^= CRC16Table[nTemp]; if (base == 8) ret += "0";
if (base == 16) ret += "0x";
ret += PIString::fromNumber(at(i), base);
} }
return ret; return ret;
} }
uint PIByteArray::checksumCRC32() { PIByteArray PIByteArray::fromString(PIString str) {
const uint CRC32Table[256] = { PIByteArray ret;
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, if (str.trim().isEmpty()) return ret;
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, str.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ");
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, PIStringList bl(str.split(" "));
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, bool ok(false);
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, piForeachC (PIString & b, bl) {
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, int bv = b.toInt(-1, &ok);
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, if (ok) ret << uchar(bv);
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
int sz = size_s();
uchar nTemp;
uint ret = 0xFFFFFFFF;
for (int i = 0; i < sz; ++i) {
nTemp = at(i) ^ ret;
ret >>= 8;
ret ^= CRC32Table[nTemp];
} }
return ret; return ret;
} }

View File

@@ -30,27 +30,28 @@
#include "pibitarray.h" #include "pibitarray.h"
class PIString;
class PIByteArray; class PIByteArray;
class PIHuffman { class PIHuffman {
public: public:
PIVector<uchar> compress(const PIVector<uchar> & src); PIDeque<uchar> compress(const PIDeque<uchar> & src);
private: private:
struct node { struct node {
int freq; int freq;
PIVector<uchar> word; PIDeque<uchar> word;
PIBitArray path; PIBitArray path;
node * parent; node * parent;
node * right; node * right;
node * left; node * left;
}; };
static int nodeCompare(const void * f, const void * s); static int nodeCompare(const void * f, const void * s);
void calcFrequencies(const PIVector<uchar> & src); void calcFrequencies(const PIDeque<uchar> & src);
PIVector<node> nodes; PIVector<node> nodes;
}; };
class PIP_EXPORT PIByteArray: public PIVector<uchar> class PIP_EXPORT PIByteArray: public PIDeque<uchar>
{ {
public: public:
@@ -61,7 +62,7 @@ public:
PIByteArray(const uint size) {resize(size);} PIByteArray(const uint size) {resize(size);}
//! Constructs byte array from data "data" and size "size" //! Constructs byte array from data "data" and size "size"
PIByteArray(const void * data, const uint size) {for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);} PIByteArray(const void * data, const uint size): PIDeque<uchar>((const uchar*)data, size_t(size)) {/*for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);*/}
//! Help struct to store/restore custom blocks of data to/from PIByteArray //! Help struct to store/restore custom blocks of data to/from PIByteArray
@@ -80,7 +81,7 @@ public:
}; };
//! Return resized byte array //! Return resized byte array
PIByteArray resized(int new_size) {PIByteArray tv(*this); tv.resize(new_size); return tv;} PIByteArray resized(int new_size) const {PIByteArray tv(*this); tv.resize(new_size); return tv;}
//! Convert data to Base 64 and return this byte array //! Convert data to Base 64 and return this byte array
PIByteArray & convertToBase64(); PIByteArray & convertToBase64();
@@ -89,10 +90,10 @@ public:
PIByteArray & convertFromBase64(); PIByteArray & convertFromBase64();
//! Return converted to Base 64 data //! Return converted to Base 64 data
PIByteArray toBase64() {PIByteArray ba(*this); ba.convertToBase64(); return ba;} PIByteArray toBase64() const {PIByteArray ba(*this); ba.convertToBase64(); return ba;}
//! Return converted from Base 64 data //! Return converted from Base 64 data
PIByteArray fromBase64() {PIByteArray ba(*this); ba.convertFromBase64(); return ba;} PIByteArray fromBase64() const {PIByteArray ba(*this); ba.convertFromBase64(); return ba;}
PIByteArray & compressRLE(uchar threshold = 192); PIByteArray & compressRLE(uchar threshold = 192);
PIByteArray & decompressRLE(uchar threshold = 192); PIByteArray & decompressRLE(uchar threshold = 192);
@@ -101,6 +102,8 @@ public:
PIByteArray & compressHuffman() {*this = huffman.compress(*this); return *this;} PIByteArray & compressHuffman() {*this = huffman.compress(*this); return *this;}
PIString toString(int base = 16) const;
//! Add to the end data "data" with size "size" //! Add to the end data "data" with size "size"
PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;} PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
@@ -115,21 +118,14 @@ public:
//PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;} //PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;}
//! Returns plain 8-bit checksum //! Returns plain 8-bit checksum
uchar checksumPlain8(); uchar checksumPlain8() const;
//! Returns plain 32-bit checksum //! Returns plain 32-bit checksum
uint checksumPlain32(); uint checksumPlain32() const;
//! Returns CRC 8-bit checksum void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
uchar checksumCRC8();
//! Returns CRC 16-bit checksum static PIByteArray fromString(PIString str);
ushort checksumCRC16();
//! Returns CRC 32-bit checksum
uint checksumCRC32();
void operator =(const PIVector<uchar> & d) {resize(d.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = d[i];}
private: private:
union base64HelpStruct { union base64HelpStruct {
@@ -189,6 +185,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << v
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details //! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;}
//! \relatesalso PIByteArray \brief Store operator //! \relatesalso PIByteArray \brief Store operator
template<typename Type0, typename Type1>
inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
//! \relatesalso PIByteArray \brief Store operator
template<typename T> template<typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
//! \relatesalso PIByteArray \brief Store operator //! \relatesalso PIByteArray \brief Store operator
@@ -232,6 +231,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {assert(s.siz
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details //! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;} inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;}
//! \relatesalso PIByteArray \brief Restore operator //! \relatesalso PIByteArray \brief Restore operator
template<typename Type0, typename Type1>
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
//! \relatesalso PIByteArray \brief Restore operator
template<typename T> template<typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
//! \relatesalso PIByteArray \brief Restore operator //! \relatesalso PIByteArray \brief Restore operator
@@ -240,11 +242,15 @@ inline PIByteArray & operator >>(PIByteArray & s, PIList<T> & v) {assert(s.size_
//! \relatesalso PIByteArray \brief Restore operator //! \relatesalso PIByteArray \brief Restore operator
template<typename T> template<typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
// //! \relatesalso PIByteArray \brief Restore operator
//template <typename Key, typename T>
//inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE #ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE
template<typename T> template<typename T>
inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
#endif #endif
#undef PBA_OPERATOR_FROM #undef PBA_OPERATOR_FROM
//! \relatesalso PIByteArray \brief Byte arrays compare operator //! \relatesalso PIByteArray \brief Byte arrays compare operator

View File

@@ -155,7 +155,7 @@ private:
}; };
__PIVECTOR_SIMPLE_FUNCTIONS__(PIChar) __PICONTAINERS_SIMPLE_TYPE__(PIChar)
//! Output operator to \c std::ostream //! Output operator to \c std::ostream
inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;}

View File

@@ -20,6 +20,22 @@
#include "picodeinfo.h" #include "picodeinfo.h"
PIString PICodeInfo::EnumInfo::memberName(int value_) const {
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
if (e.value == value_)
return e.name;
return PIString();
}
int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const {
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
if (e.name == name_)
return e.value;
return -1;
}
PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo; PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo; PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;

View File

@@ -59,6 +59,8 @@ struct EnumeratorInfo {
}; };
struct EnumInfo { struct EnumInfo {
PIString memberName(int value) const;
int memberValue(const PIString & name) const;
PIString name; PIString name;
PIVector<PICodeInfo::EnumeratorInfo> members; PIVector<PICodeInfo::EnumeratorInfo> members;
}; };

View File

@@ -110,10 +110,10 @@ public:
Entry * parent() const {return _parent;} Entry * parent() const {return _parent;}
//! Returns children count //! Returns children count
int childCount() {return _children.size_s();} int childCount() const {return _children.size_s();}
//! Returns children as \a PIConfig::Branch //! Returns children as \a PIConfig::Branch
Branch & children() {_children.delim = delim; return _children;} Branch & children() const {_children.delim = delim; return _children;}
//! Returns child at index "index" //! Returns child at index "index"
Entry * child(const int index) const {return _children[index];} Entry * child(const int index) const {return _children[index];}
@@ -303,7 +303,7 @@ public:
static Entry _empty; static Entry _empty;
Entry * _parent; Entry * _parent;
Branch _children; mutable Branch _children;
PIString _tab; PIString _tab;
PIString _name; PIString _name;
PIString _value; PIString _value;

764
piconnection.cpp Normal file
View File

@@ -0,0 +1,764 @@
/*
PIP - Platform Independent Primitives
Complex I/O point
Copyright (C) 2014 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 "piconnection.h"
#include "piconfig.h"
/** \class PIConnection
* \brief Complex Input/Output point
*
* \section PIConnection_synopsis Synopsis
* %PIConnection provides abstract layer over physical devices,
* filtering and connecting data streams. Each %PIConnection
* works through Device Pool, so several %PIConnections can
* read from single physical device. General scheme:
* \image html piconnection.png
*
* \section PIConnection_pool Device pool concept
* Device pool is static object, single for each application, which
* contains unique devices. Each %PIConnection works with real devices
* through Device pool. Each device has assosiated thread for read
* and it can be started or stopped with %PIConnection functions
* \a startThreadedRead() and \a stopThreadedRead().
*
* \section PIConnection_config Configuration
* You can create %PIConnection from config file section or configure
* it later with function \a configureFromConfig(). Devices describes
* with its full pathes, for details see \ref PIIODevice_sec7. Example:
* \image html piconnection_conf.png
*
*/
PIVector<PIConnection * > PIConnection::_connections;
PIConnection::PIConnection(): PIObject() {
_connections << this;
}
PIConnection::PIConnection(const PIString & config, const PIString & name_): PIObject(name_) {
_connections << this;
configureFromConfig(config, name_);
}
PIConnection::~PIConnection() {
__device_pool__->unboundConnection(this);
removeAllFilters();
_connections.removeAll(this);
}
bool PIConnection::configureFromConfig(const PIString & conf_path, const PIString & name_) {
PIConfig conf(conf_path, PIIODevice::ReadOnly);
if (!conf.isOpened()) return false;
__device_pool__->unboundConnection(this);
removeAllChannels();
removeAllFilters();
removeAllDevices();
setName(name_);
PIConfig::Entry ce(conf.getValue(name_));
PIConfig::Branch db(ce.getValue("device").children()), fb(ce.getValue("filter").children()), cb(ce.getValue("channel").children());
PIStringList dev_list(ce.getValue("device").value());
piForeachC (PIConfig::Entry * e, db)
dev_list << e->value();
dev_list.removeStrings("");
piForeachC (PIString & s, dev_list) {
PIString fn(s);
PIIODevice::DeviceMode dm = PIIODevice::ReadWrite;
if (fn.find("(") > 0 && fn.find(")") > 0) {
PIString dms(fn.right(fn.length() - fn.find("(")).takeRange("(", ")").trim().toLowerCase().removeAll(" "));
//piCout << dms;
if (dms == "r" || dms == "ro" || dms == "read" || dms == "readonly")
dm = PIIODevice::ReadOnly;
if (dms == "w" || dms == "wo" || dms == "write" || dms == "writeonly")
dm = PIIODevice::WriteOnly;
fn.cutRight(fn.length() - fn.find("(") + 1).trim();
}
//piCout << fn;
PIIODevice * dev = addDevice(fn, dm);
if (dev) dev->setName(name_ + ".device." + s);
}
piForeachC (PIConfig::Entry * e, fb) {
PIPacketExtractor::SplitMode sm = PIPacketExtractor::None;
PIString sms(e->getValue("splitMode").value());
int smi = sms.toInt();
if (smi >= 1 && smi <= 5) sm = (PIPacketExtractor::SplitMode)smi;
else {
sms = sms.trim().toLowerCase();
if (sms.find("header") >= 0 && sms.find("footer") >= 0)
sm = PIPacketExtractor::HeaderAndFooter;
else {
if (sms.find("header") >= 0)
sm = PIPacketExtractor::Header;
else {
if (sms.find("footer") >= 0)
sm = PIPacketExtractor::Footer;
else {
if (sms.find("time") >= 0)
sm = PIPacketExtractor::Timeout;
else {
if (sms.find("size") >= 0)
sm = PIPacketExtractor::Size;
}
}
}
}
}
PIStringList devs(e->value());
PIConfig::Branch db(e->getValue("device").children());
piForeachC (PIConfig::Entry * e2, db)
devs << e2->value();
devs.removeStrings("");
if (devs.isEmpty()) continue;
PIPacketExtractor * pe = addFilter(e->name(), devs.front(), sm);
if (pe == 0) continue;
for (int i = 1; i < devs.size_s(); ++i)
addFilter(e->name(), devs[i], sm);
pe->setPayloadSize(e->getValue("payloadSize", pe->payloadSize()));
pe->setPacketSize(e->getValue("packetSize", pe->packetSize()));
pe->setTimeout(e->getValue("timeout", pe->timeout()));
pe->setHeader(PIByteArray::fromString(e->getValue("header", "").value()));
pe->setFooter(PIByteArray::fromString(e->getValue("footer", "").value()));
}
piForeachC (PIConfig::Entry * e, cb) {
PIString f(e->getValue("from").value()), t(e->getValue("to").value());
addChannel(f, t);
}
return true;
}
PIString PIConnection::makeConfig() const {
PIString ret;
ret << "[" << name() << "]\n";
PIVector<PIIODevice * > devs(boundedDevices());
int dn(0);
piForeachC (PIIODevice * d, devs) {
ret << "device." << dn << " = " << d->constructFullPath(); ++dn;
if (d->mode() == PIIODevice::ReadOnly) ret << " (ro)";
if (d->mode() == PIIODevice::WriteOnly) ret << " (wo)";
ret << "\n";
}
piForeachC (PEPair & f, extractors) {
if (f.second == 0) continue;
if (f.second->extractor == 0) continue;
PIString prefix = "filter." + f.first;
for (int i = 0; i < f.second->devices.size_s(); ++i)
ret << prefix << ".device." << i << " = " << f.second->devices[i]->constructFullPath() << "\n";
ret << prefix << ".splitMode = ";
switch (f.second->extractor->splitMode()) {
case PIPacketExtractor::None: ret << "none"; break;
case PIPacketExtractor::Header: ret << "header"; break;
case PIPacketExtractor::Footer: ret << "footer"; break;
case PIPacketExtractor::HeaderAndFooter: ret << "header & footer"; break;
case PIPacketExtractor::Size: ret << "size"; break;
case PIPacketExtractor::Timeout: ret << "timeout"; break;
}
ret << "\n";
ret << prefix << ".payloadSize = " << f.second->extractor->payloadSize() << "\n";
ret << prefix << ".packetSize = " << f.second->extractor->packetSize() << "\n";
ret << prefix << ".timeout = " << f.second->extractor->timeout() << "\n";
ret << prefix << ".header = " << f.second->extractor->header().toString() << "\n";
ret << prefix << ".footer = " << f.second->extractor->footer().toString() << "\n";
}
dn = 0;
piForeachC (CPair & c, channels_) {
piForeachC (PIIODevice * d, c.second) {
PIString prefix = "channel." + PIString::fromNumber(dn); ++dn;
ret << prefix << ".from = " << devPath(c.first) << "\n";
ret << prefix << ".to = " << devPath(d) << "\n";
}
}
ret << "[]\n";
return ret;
}
PIIODevice * PIConnection::addDevice(const PIString & full_path, PIIODevice::DeviceMode mode, bool start) {
PIIODevice * dev = __device_pool__->addDevice(this, full_path, mode, start);
if (dev) {
dev->setName(name() + ".device." + full_path);
device_modes[dev] = mode;
}
return dev;
}
bool PIConnection::removeDevice(const PIString & full_path) {
PIIODevice * dev = __device_pool__->device(full_path);
if (dev == 0) return false;
device_modes.remove(dev);
piForeachC (PEPair & i, extractors) {
if (i.second == 0) continue;
i.second->devices.removeAll(dev);
}
bounded_extractors.remove(dev);
channels_.remove(dev);
for (PIMap<PIIODevice * , PIVector<PIIODevice * > >::iterator it = channels_.begin(); it != channels_.end(); ++it)
it.value().removeAll(dev);
return __device_pool__->removeDevice(this, full_path);
}
void PIConnection::removeAllDevices() {
PIVector<PIIODevice * > bdevs(__device_pool__->boundedDevices(this));
piForeach (PIIODevice * d, bdevs) {
channels_.remove(d);
for (PIMap<PIIODevice * , PIVector<PIIODevice * > >::iterator it = channels_.begin(); it != channels_.end(); ++it)
it.value().removeAll(d);
}
__device_pool__->unboundConnection(this);
device_modes.clear();
bounded_extractors.clear();
piForeachC (PEPair & i, extractors) {
if (i.second == 0) continue;
i.second->devices.clear();
}
}
PIIODevice * PIConnection::device(const PIString & full_path) const {
DevicePool::DeviceData * dd = __device_pool__->devices.value(full_path);
if (dd == 0) return 0;
if (dd->dev == 0) return 0;
if (!dd->listeners.contains(const_cast<PIConnection * >(this))) return 0;
return dd->dev;
}
PIVector<PIIODevice * > PIConnection::boundedDevices() const {
return __device_pool__->boundedDevices(this);
}
PIPacketExtractor * PIConnection::addFilter(const PIString & name_, const PIString & full_path, PIPacketExtractor::SplitMode mode) {
Extractor * e = extractors.value(name_);
PIIODevice * dev = __device_pool__->device(full_path);
if (dev == 0) {
piCoutObj << "\"addPacketExtractor\" error: no such device \"" << full_path << "\"!";
return 0;
}
if (e == 0) {
e = new Extractor();
extractors[name_] = e;
}
if (e->extractor == 0) {
e->extractor = new PIPacketExtractor(0, mode);
e->extractor->setName(name_);
e->extractor->setThreadedReadData(new PIPair<PIConnection * , PIString>(this, name_));
e->extractor->setHeaderCheckSlot(filterValidateHeaderS);
e->extractor->setFooterCheckSlot(filterValidateFooterS);
e->extractor->setPayloadCheckSlot(filterValidatePayloadS);
CONNECT2(void, uchar * , int, e->extractor, packetReceived, this, packetExtractorReceived)
}
if (!e->devices.contains(dev)) {
bounded_extractors[dev] << e->extractor;
e->devices << dev;
}
return e->extractor;
}
PIPacketExtractor * PIConnection::addFilter(const PIString & name_, const PIIODevice * dev, PIPacketExtractor::SplitMode mode) {
if (dev == 0) return 0;
PIString fp;
if (dev->isPropertyExists("__fullPath__")) fp = dev->property("__fullPath__").toString();
fp = dev->constructFullPath();
return addFilter(name_, fp, mode);
}
bool PIConnection::removeFilter(const PIString & name_, const PIString & full_path) {
Extractor * p = extractors.value(name_);
if (p == 0) return false;
bool ret = false;
for (int i = 0; i < p->devices.size_s(); ++i) {
if (p->devices[i]->property("__fullPath__").toString() == full_path) {
bounded_extractors[p->devices[i]].removeAll(p->extractor);
p->devices.remove(i);
--i;
ret = true;
}
}
if (p->devices.isEmpty()) {
unboundExtractor(p->extractor);
delete p;
}
return ret;
}
bool PIConnection::removeFilter(const PIString & name, const PIIODevice * dev) {
if (dev == 0) return false;
return removeFilter(name, dev->property("__fullPath__").toString());
}
bool PIConnection::removeFilter(const PIString & name_) {
Extractor * p = extractors.value(name_);
if (p == 0) return false;
unboundExtractor(p->extractor);
delete p;
return true;
}
void PIConnection::removeAllFilters() {
piForeachC (PEPair & i, extractors) {
if (i.second == 0) continue;
channels_.remove(i.second->extractor);
for (PIMap<PIIODevice * , PIVector<PIIODevice * > >::iterator it = channels_.begin(); it != channels_.end(); ++it)
it.value().removeAll(i.second->extractor);
delete i.second;
}
extractors.clear();
bounded_extractors.clear();
}
PIVector<PIPacketExtractor * > PIConnection::filters() const {
PIVector<PIPacketExtractor * > ret;
piForeachC (PEPair & i, extractors)
if (i.second != 0)
if (i.second->extractor != 0) ret << i.second->extractor;
return ret;
}
PIStringList PIConnection::filterNames() const {
PIStringList ret;
piForeachC (PEPair & i, extractors)
if (i.second != 0)
if (i.second->extractor != 0) ret << i.first;
return ret;
}
PIPacketExtractor * PIConnection::filter(const PIString & name) const {
piForeachC (PEPair & i, extractors)
if (i.second != 0)
if (i.second->extractor != 0 && i.first == name)
return i.second->extractor;
return 0;
}
PIVector<PIIODevice * > PIConnection::filterBoundedDevices(const PIString & name_) const {
PIVector<PIIODevice * > ret;
Extractor * p = extractors.value(name_);
if (p == 0) return ret;
return p->devices;
}
bool PIConnection::addChannel(const PIString & name0, const PIString & name1) {
//piCout << "addChannel" << name0 << name1;
if (name0.isEmpty() || name1.isEmpty()) return false;
PIIODevice * dev0 = device(name0), * dev1 = device(name1);
PIPacketExtractor * pe0(0), * pe1(0);
if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor;
if (extractors.value(name1) != 0) pe1 = extractors.value(name1)->extractor;
if (pe0 != 0) dev0 = pe0;
if (pe1 != 0) dev1 = pe1;
if (dev0 == 0 || dev1 == 0) {
if (dev0 == 0) piCoutObj << "\"addChannel\" error: no such device \"" << name0 << "\"!";
if (dev1 == 0) piCoutObj << "\"addChannel\" error: no such device \"" << name1 << "\"!";
return false;
}
if (!channels_[dev0].contains(dev1))
channels_[dev0] << dev1;
return true;
}
bool PIConnection::removeChannel(const PIString & name0, const PIString & name1) {
PIIODevice * dev0 = device(name0), * dev1 = device(name1);
PIPacketExtractor * pe0(0), * pe1(0);
if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor;
if (extractors.value(name1) != 0) pe1 = extractors.value(name1)->extractor;
if (pe0 != 0) dev0 = pe0;
if (pe1 != 0) dev1 = pe1;
if (dev0 == 0 || dev1 == 0) return false;
channels_[dev0].removeAll(dev1);
return true;
}
bool PIConnection::removeChannel(const PIString & name0) {
PIIODevice * dev0 = device(name0);
PIPacketExtractor * pe0(0);
if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor;
if (pe0 != 0) dev0 = pe0;
if (dev0 == 0) return false;
channels_.remove(dev0);
for (PIMap<PIIODevice * , PIVector<PIIODevice * > >::iterator it = channels_.begin(); it != channels_.end(); ++it)
it.value().removeAll(dev0);
return true;
}
void PIConnection::removeAllChannels() {
channels_.clear();
}
PIString PIConnection::devPath(const PIIODevice * d) const {
if (d == 0) return PIString();
if (strcmp(d->className(), "PIPacketExtractor") == 0) return d->name();
return d->constructFullPath();
}
PIString PIConnection::devFPath(const PIIODevice * d) const {
if (d == 0) return PIString();
if (d->isPropertyExists("__fullPath__")) return d->property("__fullPath__").toString();
return d->name();
}
PIVector<PIPair<PIString, PIString > > PIConnection::channels() const {
PIVector<PIPair<PIString, PIString > > ret;
piForeachC (CPair & i, channels_) {
PIString fp0(devFPath(i.first));
piForeachC (PIIODevice * d, i.second)
ret << PIPair<PIString, PIString>(fp0, devFPath(d));
}
return ret;
}
void PIConnection::startThreadedRead(const PIString & full_path) {
DevicePool::DeviceData * dd = __device_pool__->devices.value(full_path, 0);
if (dd == 0) return;
if (dd->dev == 0) return;
if (dd->started || dd->dev->mode() == PIIODevice::WriteOnly) return;
dd->rthread->start();
dd->started = true;
}
void PIConnection::startAllThreadedReads() {
piForeachC (DevicePool::DDPair & d, __device_pool__->devices)
startThreadedRead(d.first);
}
void PIConnection::stopThreadedRead(const PIString & full_path) {
DevicePool::DeviceData * dd = __device_pool__->devices.value(full_path, 0);
if (dd == 0) return;
if (dd->dev == 0) return;
if (!dd->started || dd->dev->mode() == PIIODevice::WriteOnly) return;
dd->rthread->stop();
dd->started = false;
}
void PIConnection::stopAllThreadedReads() {
piForeachC (DevicePool::DDPair & d, __device_pool__->devices)
stopThreadedRead(d.first);
}
int PIConnection::write(const PIString & full_path, const PIByteArray & data) {
PIIODevice * dev = __device_pool__->device(full_path);
if (dev == 0) {
piCoutObj << "Null Device!";
return -1;
}
if (!dev->canWrite()) {
piCoutObj << "Device \"" << full_path << "\" can`t write!";
return -1;
}
return dev->write(data);
}
PIVector< PIConnection * > PIConnection::allConnections() {
return _connections;
}
PIVector< PIIODevice * > PIConnection::allDevices() {
return __device_pool__->boundedDevices();
}
PIIODevice * PIConnection::DevicePool::addDevice(PIConnection * parent, const PIString & fp, PIIODevice::DeviceMode mode, bool start) {
DeviceData * dd = devices[fp];
int pmode(0);
bool need_start = false;
if (dd == 0) {
dd = new DeviceData();
devices[fp] = dd;
}
if (dd->dev == 0) {
//piCout << "new device" << fp;
dd->dev = PIIODevice::createFromFullPath(fp);
if (dd->dev == 0) {
piCoutObj << "Error: can`t create device \"" << fp << "\"!"; //:" << errorString();
return 0;
}
dd->dev->setProperty("__fullPath__", fp);
} else
pmode = dd->dev->mode();
if (!dd->listeners.contains(parent))
dd->listeners << parent;
if (pmode == mode || pmode == PIIODevice::ReadWrite)
return dd->dev;
if ((mode & PIIODevice::ReadOnly) > 0) {
if (dd->rthread != 0) {
delete dd->rthread;
dd->rthread = 0;
dd->started = false;
}
dd->rthread = new PIThread(dd, threadReadDP);
need_start = true;
pmode |= PIIODevice::ReadOnly;
}
if ((mode & PIIODevice::WriteOnly) > 0)
pmode |= PIIODevice::WriteOnly;
dd->dev->close();
dd->dev->open((PIIODevice::DeviceMode)pmode);
if (need_start && start) {
dd->rthread->start();
dd->started = true;
}
return dd->dev;
}
bool PIConnection::DevicePool::removeDevice(PIConnection * parent, const PIString & fp) {
DeviceData * dd = devices.value(fp);
if (dd == 0)
return false;
if (dd->dev == 0)
return false;
bool ok = dd->listeners.contains(parent);
dd->listeners.removeAll(parent);
if (dd->listeners.isEmpty()) {
delete dd;
devices.remove(fp);
}
return ok;
}
void PIConnection::DevicePool::unboundConnection(PIConnection * parent) {
PIStringList rem;
piForeachC (DDPair & i, devices) {
if (i.second == 0) {
rem << i.first;
continue;
}
i.second->listeners.removeAll(parent);
if (i.second->listeners.isEmpty())
rem << i.first;
}
piForeachC (PIString & i, rem) {
DeviceData * dd = devices.value(i);
if (dd == 0)
continue;
delete dd;
devices.remove(i);
}
}
PIIODevice * PIConnection::DevicePool::device(const PIString & fp) const {
DeviceData * dd = devices.value(fp);
if (dd == 0) return 0;
return dd->dev;
}
PIVector<PIConnection * > PIConnection::DevicePool::boundedConnections() const {
PIVector<PIConnection * > ret;
piForeachC (DDPair & i, devices) {
if (i.second == 0)
continue;
ret << i.second->listeners;
}
for (int i = 0; i < ret.size_s(); ++i)
for (int j = i + 1; j < ret.size_s(); ++j)
if (ret[i] == ret[j]) {
ret.remove(j);
--j;
}
return ret;
}
PIVector< PIIODevice * > PIConnection::DevicePool::boundedDevices() const {
PIVector<PIIODevice * > ret;
piForeachC (DDPair & i, devices) {
if (i.second == 0) continue;
if (i.second->dev == 0) continue;
ret << i.second->dev;
}
return ret;
}
PIVector<PIIODevice * > PIConnection::DevicePool::boundedDevices(const PIConnection * parent) const {
PIVector<PIIODevice * > ret;
piForeachC (DDPair & i, devices) {
if (i.second == 0) continue;
if (i.second->dev == 0) continue;
if (i.second->listeners.contains(const_cast<PIConnection*>(parent)))
ret << i.second->dev;
}
return ret;
}
PIConnection::DevicePool::DeviceData::~DeviceData() {
if (rthread != 0) {
rthread->stop();
delete rthread;
rthread = 0;
}
if (dev != 0) {
delete dev;
dev = 0;
}
}
void PIConnection::DevicePool::threadReadDP(void * ddp) {
DeviceData * dd((DeviceData * )ddp);
if (dd->dev == 0) {piMSleep(100); return;}
PIByteArray ba;
ba = dd->dev->read(dd->dev->threadedReadBufferSize());
if (ba.isEmpty()) {piMSleep(10); return;}
//piCout << "Readed from" << dd->dev->path() << Hex << ba;
__device_pool__->deviceReaded(dd, ba);
}
void PIConnection::DevicePool::deviceReaded(PIConnection::DevicePool::DeviceData * dd, const PIByteArray & data) {
PIString from = dd->dev->property("__fullPath__").toString();
piForeach (PIConnection * ld, dd->listeners)
ld->rawReceived(dd->dev, from, data);
}
bool PIConnection::filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size) {
PIPair<PIConnection * , PIString> * p((PIPair<PIConnection * , PIString> * )c);
return p->first->filterValidateHeader(p->second, src, rec, size);
}
bool PIConnection::filterValidateFooterS(void * c, uchar * src, uchar * rec, int size) {
PIPair<PIConnection * , PIString> * p((PIPair<PIConnection * , PIString> * )c);
return p->first->filterValidateFooter(p->second, src, rec, size);
}
bool PIConnection::filterValidatePayloadS(void * c, uchar * rec, int size) {
PIPair<PIConnection * , PIString> * p((PIPair<PIConnection * , PIString> * )c);
return p->first->filterValidatePayload(p->second, rec, size);
}
void PIConnection::rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data) {
dataReceived(from, data);
dataReceivedEvent(from, data);
PIVector<PIPacketExtractor * > be(bounded_extractors.value(dev));
//piCout << be;
piForeach (PIPacketExtractor * i, be)
i->threadedRead(const_cast<uchar * >(data.data()), data.size_s());
PIVector<PIIODevice * > chd(channels_.value(dev));
piForeach (PIIODevice * d, chd)
d->write(data);
}
bool PIConnection::filterValidateHeader(const PIString & filter_name, uchar * src, uchar * rec, int size) {
for (int i = 0; i < size; ++i)
if (src[i] != rec[i])
return false;
return true;
}
bool PIConnection::filterValidateFooter(const PIString & filter_name, uchar * src, uchar * rec, int size) {
for (int i = 0; i < size; ++i)
if (src[i] != rec[i])
return false;
return true;
}
bool PIConnection::filterValidatePayload(const PIString & filter_name, uchar * rec, int size) {
return true;
}
PIConnection::Extractor::~Extractor() {
if (extractor != 0) {
if (extractor->threadedReadData() != 0)
delete (PIPair<PIConnection * , PIString> * )(extractor->threadedReadData());
delete extractor;
extractor = 0;
}
}
void PIConnection::unboundExtractor(PIPacketExtractor * pe) {
if (pe == 0) return;
channels_.remove(pe);
for (PIMap<PIIODevice * , PIVector<PIIODevice * > >::iterator it = channels_.begin(); it != channels_.end(); ++it)
it.value().removeAll(pe);
PIVector<PIIODevice * > k = bounded_extractors.keys();
piForeach (PIIODevice * i, k) {
PIVector<PIPacketExtractor*> & be(bounded_extractors[i]);
be.removeAll(pe);
if (be.isEmpty())
bounded_extractors.remove(i);
}
extractors.remove(pe->name());
}
void PIConnection::packetExtractorReceived(uchar * data, int size) {
PIString from(emitter() == 0 ? "" : emitter()->name());
packetReceived(from, PIByteArray(data, size));
packetReceivedEvent(from, PIByteArray(data, size));
PIIODevice * cd = (PIIODevice * )emitter();
if (cd == 0) return;
PIVector<PIIODevice * > chd(channels_.value(cd));
piForeach (PIIODevice * d, chd)
d->write(data, size);
}
PIConnection::DevicePool * __device_pool__;
bool __DevicePoolContainer__::inited_(false);
__DevicePoolContainer__::__DevicePoolContainer__() {
if (inited_) return;
inited_ = true;
__device_pool__ = new PIConnection::DevicePool();
}

291
piconnection.h Normal file
View File

@@ -0,0 +1,291 @@
/*! \file piconnection.h
* \brief Complex I/O point
*/
/*
PIP - Platform Independent Primitives
Complex I/O point
Copyright (C) 2014 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 PICONNECTION_H
#define PICONNECTION_H
#include "pipacketextractor.h"
class PIP_EXPORT PIConnection: public PIObject
{
PIOBJECT(PIConnection)
public:
//! Constructs an empty connection
PIConnection();
//! Constructs connection and configure it from config file "config" from section "name"
PIConnection(const PIString & config, const PIString & name);
~PIConnection();
/*! \brief Configure connection from config file "config" from section "name". Returns if configuration was successful
* \details \b Warning: all devices, filters and channels removed before configure! */
bool configureFromConfig(const PIString & config, const PIString & name);
//! Returns config file section of current connection configuration
PIString makeConfig() const;
/*! \brief Add device with full path "full_path", open mode "mode" to Device pool and connection
* \details Returns pointer to device or null if device can not be created. If "start" is true,
* read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead()
* or \a startAllThreadedReads(). By default, read thread doesn`t start */
PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false);
/*! \brief Remove device with full path "full_path" from connection
* \details Returns if device was removed. If there is no connection bounded to this device,
* it will be removed from Device pool */
bool removeDevice(const PIString & full_path);
/*! \brief Remove all device from connection
* \details If there is no connection bounded to there devices, they removed from Device pool */
void removeAllDevices();
//! Returns device with full path "full_path" or null if there is no such device
PIIODevice * device(const PIString & full_path) const;
//! Returns all devices bounded to this connection
PIVector<PIIODevice * > boundedDevices() const;
/*! \brief Add filter with name "name" to device with full path "full_path"
* \details If there is no filter with name "name", connection create new with split mode "mode" and bound
* to it device "full_path". If filter with name "name" already exists, device "full_path" add to this filter.
* \b Attention! "mode" is altual olny if new filter was created!
* This function returns PIPacketExtractor * assosiated with this filter */
PIPacketExtractor * addFilter(const PIString & name, const PIString & full_path, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None);
//! Add filter with name "name" to device "dev"
PIPacketExtractor * addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None);
/*! \brief Remove from filter with name "name" device with full path "full_path"
* \details If there is no devices bounded to this filter, it will be removed. Returns
* if device was removed */
bool removeFilter(const PIString & name, const PIString & full_path);
//! Remove from filter with name "name" device "dev"
bool removeFilter(const PIString & name, const PIIODevice * dev);
//! Remove filter with name "name". Returns if filter was removed
bool removeFilter(const PIString & name);
//! Remove all filters from connection
void removeAllFilters();
//! Returns all filters of connection
PIVector<PIPacketExtractor * > filters() const;
//! Returns all filter names of connection
PIStringList filterNames() const;
//! Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter
PIPacketExtractor * filter(const PIString & name) const;
//! Returns all devices bounded to filter "name"
PIVector<PIIODevice * > filterBoundedDevices(const PIString & name) const;
/*! \brief Add to connection channel from "name_from" to "name_to"
* \details "name_from" and "name_to" can be full pathes of devices or filter names.
* Returns \b false if there if no such device or filter, else create channel and returns \b true */
bool addChannel(const PIString & name_from, const PIString & name_to);
//! Add to connection channel from "name_from" to "dev_to"
bool addChannel(const PIString & name_from, const PIIODevice * dev_to) {return addChannel(name_from, devFPath(dev_to));}
//! Add to connection channel from "dev_from" to "name_to"
bool addChannel(const PIIODevice * dev_from, const PIString & name_to) {return addChannel(devFPath(dev_from), name_to);}
//! Add to connection channel from "dev_from" to "dev_to"
bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return addChannel(devFPath(dev_from), devFPath(dev_to));}
/*! \brief Remove from connection channel from "name_from" to "name_to"
* \details "name_from" and "name_to" can be full pathes of devices or filter names.
* Returns \b false if there if no such device or filter, else remove channel and returns \b true */
bool removeChannel(const PIString & name_from, const PIString & name_to);
//! Remove from connection channel from "name_from" to "dev_to"
bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) {return removeChannel(name_from, devFPath(dev_to));}
//! Remove from connection channel from "dev_from" to "name_to"
bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) {return removeChannel(devFPath(dev_from), name_to);}
//! Remove from connection channel from "dev_from" to "dev_to"
bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return removeChannel(devFPath(dev_from), devFPath(dev_to));}
/*! \brief Remove from connection all channels from "name_from"
* \details "name_from" can be full path of device or filter name.
* Returns \b false if there if no such device or filter, else remove channels and returns \b true */
bool removeChannel(const PIString & name_from);
//! Remove from connection all channels from "dev_from"
bool removeChannel(const PIIODevice * dev_from) {return removeChannel(devFPath(dev_from));}
//! Remove from connection all channels
void removeAllChannels();
//! Returns all channels of this connection as full pathes or filter names pair array (from, to)
PIVector<PIPair<PIString, PIString> > channels() const;
//! Start read thread of device with full path "full_path"
void startThreadedRead(const PIString & full_path);
//! Start read thread of device "dev"
void startThreadedRead(const PIIODevice * dev) {startThreadedRead(devFPath(dev));}
//! Start read threads of all Device pool device
void startAllThreadedReads();
//! Stop read thread of device with full path "full_path"
void stopThreadedRead(const PIString & full_path);
//! Stop read thread of device "dev"
void stopThreadedRead(const PIIODevice * dev) {stopThreadedRead(devFPath(dev));}
//! Stop read threads of all Device pool device
void stopAllThreadedReads();
//! Returns if there is no devices in this connection
bool isEmpty() const {return device_modes.isEmpty();}
//! Write data "data" to device with full path "full_path" and returns result of \a write() function of device
int write(const PIString & full_path, const PIByteArray & data);
//! Returns all connections in application
static PIVector<PIConnection * > allConnections();
//! Returns all devices in Device pool
static PIVector<PIIODevice * > allDevices();
class DevicePool: public PIObject {
PIOBJECT(DevicePool)
friend class PIConnection;
public:
DevicePool(): PIObject("PIConnection::DevicePool") {}
PIIODevice * addDevice(PIConnection * parent, const PIString & fp, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = true);
bool removeDevice(PIConnection * parent, const PIString & fp);
void unboundConnection(PIConnection * parent);
PIIODevice * device(const PIString & fp) const;
PIVector<PIConnection * > boundedConnections() const;
PIVector<PIIODevice * > boundedDevices() const;
PIVector<PIIODevice * > boundedDevices(const PIConnection * parent) const;
protected:
struct DeviceData {
DeviceData(): dev(0), rthread(0), started(false) {}
~DeviceData();
PIIODevice * dev;
PIThread * rthread;
bool started;
PIVector<PIConnection * > listeners;
};
static void threadReadDP(void * ddp);
void deviceReaded(DeviceData * dd, const PIByteArray & data);
typedef PIMap<PIString, DeviceData * >::value_type DDPair;
PIMap<PIString, DeviceData * > devices;
};
EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data)
EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data)
//! \events
//! \{
//! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data)
//! \brief Raise on data received from device with full path "from"
//! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data)
//! \brief Raise on packet received from filter with name "from"
//! \}
protected:
//! Executes on data received from device with full path "from"
virtual void dataReceived(const PIString & from, const PIByteArray & data) {}
//! Executes on packet received from filter with name "from"
virtual void packetReceived(const PIString & from, const PIByteArray & data) {}
//! Validate header "rec" with source header "src" and size "size", executes from filter "filter_name"
virtual bool filterValidateHeader(const PIString & filter_name, uchar * src, uchar * rec, int size);
//! Validate footer "rec" with source footer "src" and size "size", executes from filter "filter_name"
virtual bool filterValidateFooter(const PIString & filter_name, uchar * src, uchar * rec, int size);
//! Validate payload "rec" with size "size", executes from filter "filter_name"
virtual bool filterValidatePayload(const PIString & filter_name, uchar * rec, int size);
private:
static bool filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size);
static bool filterValidateFooterS(void * c, uchar * src, uchar * rec, int size);
static bool filterValidatePayloadS(void * c, uchar * rec, int size);
void rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data);
void unboundExtractor(PIPacketExtractor * pe);
EVENT_HANDLER2(void, packetExtractorReceived, uchar * , data, int, size);
PIString devPath(const PIIODevice * d) const;
PIString devFPath(const PIIODevice * d) const;
struct Extractor {
Extractor(): extractor(0) {}
~Extractor();
PIPacketExtractor * extractor;
PIVector<PIIODevice * > devices;
};
typedef PIMap<PIString, Extractor * >::value_type PEPair;
typedef PIMap<PIIODevice * , PIVector<PIPacketExtractor * > >::value_type BEPair;
typedef PIMap<PIIODevice * , PIVector<PIIODevice * > >::value_type CPair;
PIMap<PIString, Extractor * > extractors;
PIMap<PIIODevice * , PIIODevice::DeviceMode> device_modes;
PIMap<PIIODevice * , PIVector<PIPacketExtractor * > > bounded_extractors;
PIMap<PIIODevice * , PIVector<PIIODevice * > > channels_;
static PIVector<PIConnection * > _connections;
};
extern PIConnection::DevicePool * __device_pool__;
class __DevicePoolContainer__ {
public:
__DevicePoolContainer__();
static bool inited_;
};
static __DevicePoolContainer__ __device_pool_container__;
#endif // PICONNECTION_H

View File

@@ -692,7 +692,7 @@ void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr,
addVariable("priority", &(ptr->statistic().priority), col, format); addVariable("priority", &(ptr->statistic().priority), col, format);
addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format); addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format);
addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format); addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format);
addVariable("cpu load", &(ptr->statistic().cpu_load_system), col, format); addVariable("cpu load", &(ptr->statistic().cpu_load_user), col, format);
} }
void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, PIFlags<PIConsole::Format> format) { void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, PIFlags<PIConsole::Format> format) {
vid++; tv.id = vid; tv.size = sizeof(ullong); tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format; vid++; tv.id = vid; tv.size = sizeof(ullong); tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format;
@@ -812,8 +812,8 @@ void PIConsole::listenServers() {
stopPeer(); stopPeer();
server_mode = false; server_mode = false;
server_name.clear(); server_name.clear();
srand(currentSystemTime().nanoseconds); srand(PISystemTime::current().nanoseconds);
peer = new PIPeer("_rcc_:" + currentDateTime().toString("hhmmssddMMyy_") + PIString::fromNumber(rand())); peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(rand()));
CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived);
peer_timer.start(100.); peer_timer.start(100.);
} }

View File

@@ -26,7 +26,7 @@
#ifndef PICONTAINERS_H #ifndef PICONTAINERS_H
#define PICONTAINERS_H #define PICONTAINERS_H
#include "pivector.h" #include "piincludes.h"
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
class PIP_EXPORT PIPair { class PIP_EXPORT PIPair {
@@ -47,8 +47,10 @@ inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> &
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;}
#include "pivector.h"
#include "pistack.h" #include "pistack.h"
#include "piqueue.h" #include "piqueue.h"
#include "pideque.h"
#include "pimap.h" #include "pimap.h"
#ifdef DOXYGEN #ifdef DOXYGEN
@@ -295,25 +297,28 @@ public:
}; };
#ifndef PIP_CONTAINERS_STL
template<typename Type, typename Allocator = std::allocator<Type> > # define __PICONTAINERS_SIMPLE_TYPE__(T) \
class PIP_EXPORT PIDeque: public deque<Type, Allocator> { __PIDEQUE_SIMPLE_TYPE__(T)\
typedef PIDeque<Type, Allocator> _CDeque; __PIVECTOR_SIMPLE_TYPE__(T)
typedef deque<Type, Allocator> _stlc;
public: __PICONTAINERS_SIMPLE_TYPE__(bool)
PIDeque() {piMonitor.containers++;} __PICONTAINERS_SIMPLE_TYPE__(char)
PIDeque(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} __PICONTAINERS_SIMPLE_TYPE__(uchar)
PIDeque(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);} __PICONTAINERS_SIMPLE_TYPE__(short)
PIDeque(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} __PICONTAINERS_SIMPLE_TYPE__(ushort)
PIDeque(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} __PICONTAINERS_SIMPLE_TYPE__(int)
~PIDeque() {piMonitor.containers--;} __PICONTAINERS_SIMPLE_TYPE__(uint)
int size_s() const {return static_cast<int>(_stlc::size());} __PICONTAINERS_SIMPLE_TYPE__(long)
bool isEmpty() const {return _stlc::empty();} __PICONTAINERS_SIMPLE_TYPE__(ulong)
bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} __PICONTAINERS_SIMPLE_TYPE__(llong)
int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} __PICONTAINERS_SIMPLE_TYPE__(ullong)
_CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;} __PICONTAINERS_SIMPLE_TYPE__(float)
PIVector<Type> toVector() {PIVector<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} __PICONTAINERS_SIMPLE_TYPE__(double)
}; __PICONTAINERS_SIMPLE_TYPE__(ldouble)
#endif
#endif // PICONTAINERS_H #endif // PICONTAINERS_H

477
pideque.h Normal file
View File

@@ -0,0 +1,477 @@
/*! \file pideque.h
* \brief Dynamic array of any type
*
* This file declares PIDeque
*/
/*
PIP - Platform Independent Primitives
Dynamic array of any type
Copyright (C) 2014 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 PIDEQUE_H
#define PIDEQUE_H
#include "piincludes.h"
#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN)
template <typename T>
class PIDeque {
public:
PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
//printf("new vector 1 %p (%s) ... !{\n", this, typeid(T).name());
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data);
}
PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
//printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name());
alloc(other.pid_size, true);
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data);
}
PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
//printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name());
alloc(size, true);
newT(pid_data + pid_start, data, pid_size);
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data);
}
PIDeque(size_t pid_size, const T & f = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
//printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name());
resize(pid_size, f);
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data);
}
~PIDeque() {
//printf("delete deque %p (%s) (s=%d, rs=%d, st=%d, d=%p) ... ~{\n", this, typeid(T).name(), int(pid_size), int(pid_rsize), int(pid_start), pid_data);
deleteT(pid_data + pid_start, pid_size);
dealloc();
//deleteRaw(pid_tdata);
_reset();
//printf("}~\n");
}
PIDeque<T> & operator =(const PIDeque<T> & other) {
if (this == &other) return *this;
deleteT(pid_data + pid_start, pid_size);
alloc(other.pid_size, true);
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
return *this;
}
typedef T value_type;
class iterator {
friend class PIDeque<T>;
private:
iterator(PIDeque<T> * v, size_t p): parent(v), pos(p) {}
PIDeque<T> * parent;
size_t 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 PIDeque<T>;
private:
const_iterator(const PIDeque<T> * v, size_t p): parent(v), pos(p) {}
const PIDeque<T> * parent;
size_t 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 PIDeque<T>;
private:
reverse_iterator(PIDeque<T> * v, size_t p): parent(v), pos(p) {}
PIDeque<T> * parent;
size_t 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 PIDeque<T>;
private:
const_reverse_iterator(const PIDeque<T> * v, size_t p): parent(v), pos(p) {}
const PIDeque<T> * parent;
size_t 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, pid_size);}
const_iterator begin() const {return const_iterator(this, 0);}
const_iterator end() const {return const_iterator(this, pid_size);}
reverse_iterator rbegin() {return reverse_iterator(this, pid_size - 1);}
reverse_iterator rend() {return reverse_iterator(this, -1);}
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, pid_size - 1);}
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
size_t size() const {return pid_size;}
ssize_t size_s() const {return pid_size;}
size_t length() const {return pid_size;}
size_t capacity() const {return pid_rsize;}
bool isEmpty() const {return (pid_size == 0);}
T & operator [](size_t index) {return pid_data[pid_start + index];}
T & at(size_t index) {return pid_data[pid_start + index];}
const T & operator [](size_t index) const {return pid_data[pid_start + index];}
const T & at(size_t index) const {return pid_data[pid_start + index];}
T & back() {return pid_data[pid_start + pid_size - 1];}
const T & back() const {return pid_data[pid_start + pid_size - 1];}
T & front() {return pid_data[pid_start];}
const T & front() const {return pid_data[pid_start];}
bool operator ==(const PIDeque<T> & t) const {if (pid_size != t.pid_size) return false; for (size_t i = 0; i < pid_size; ++i) if (t[i] != pid_data[pid_start + i]) return false; return true;}
bool operator !=(const PIDeque<T> & t) const {if (pid_size != t.pid_size) return true; for (size_t i = 0; i < pid_size; ++i) if (t[i] != pid_data[pid_start + i]) return true; return false;}
bool contains(const T & v) const {for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (v == pid_data[i]) return true; return false;}
int etries(const T & v) const {int ec = 0; for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (v == pid_data[i]) ++ec; return ec;}
T * data(size_t index = 0) {return &(pid_data[pid_start + index]);}
const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);}
PIDeque<T> & clear() {resize(0); return *this;}
PIDeque<T> & fill(const T & f = T()) {
//if (sizeof(T) == 1) memset(pid_data, f, pid_size);
deleteT(pid_data + pid_start, pid_size);
//zeroRaw(pid_data, pid_size);
for (size_t i = pid_start; i < pid_start + pid_size; ++i)
elementNew(pid_data + i, f);
return *this;
}
PIDeque<T> & assign(const T & f = T()) {return fill(f);}
PIDeque<T> & assign(size_t new_size, const T & f) {resize(new_size); return fill(f);}
PIDeque<T> & resize(size_t new_size, const T & f = T()) {
if (new_size < pid_size) {
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
pid_size = new_size;
}
if (new_size > pid_size) {
size_t os = pid_size;
alloc(new_size, true);
//if (sizeof(T) == 1) memset(&(pid_data[os]), f, ds);
//zeroRaw(&(pid_data[os]), new_size - os);
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) elementNew(pid_data + i, f);
}
return *this;
}
PIDeque<T> & reserve(size_t new_size) {if (new_size <= pid_rsize) return *this; size_t os = pid_size; alloc(new_size, true); pid_size = os; return *this;}
PIDeque<T> & insert(size_t index, const T & v = T()) {
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
//piCout << "insert" << dir << index << pid_size << pid_rsize << pid_start << "!<";
if (dir) {
alloc(pid_size + 1, true);
if (index < pid_size - 1) {
size_t os = pid_size - index - 1;
memmove(&(pid_data[index + pid_start + 1]), &(pid_data[index + pid_start]), os * sizeof(T));
}
} else {
pid_start--;
alloc(pid_size + 1, false);
//piCout << "insert front" << pid_size << pid_rsize << pid_start << "!<";
if (index > 0)
memmove(&(pid_data[pid_start]), &(pid_data[pid_start + 1]), index * sizeof(T));
}
//piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!";
elementNew(pid_data + pid_start + index, v);
return *this;
}
PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
if (other.isEmpty()) return *this;
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
//piCout << "insert" << dir << index << pid_size << pid_rsize << pid_start << "!<";
if (dir) {
ssize_t os = pid_size - index;
alloc(pid_size + other.pid_size, true);
if (os > 0)
memmove(&(pid_data[index + pid_start + other.pid_size]), &(pid_data[index + pid_start]), os * sizeof(T));
} else {
pid_start -= other.pid_size;
alloc(pid_size + other.pid_size, false);
//piCout << "insert front" << pid_size << pid_rsize << pid_start << "!<";
if (index > 0)
memmove(&(pid_data[pid_start]), &(pid_data[pid_start + other.pid_size]), index * sizeof(T));
}
//piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!";
newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.pid_size);
return *this;
}
PIDeque<T> & remove(size_t index, size_t count = 1) {
if (count == 0) return *this;
if (index + count >= pid_size) {
resize(index);
return *this;
}
size_t os = pid_size - index - count;
deleteT(&(pid_data[index + pid_start]), count);
if (os <= index) {
//if (true) {
if (os > 0) memmove(&(pid_data[index + pid_start]), &(pid_data[index + pid_start + count]), os * sizeof(T));
} else {
if (index > 0) memmove(&(pid_data[pid_start + count]), &(pid_data[pid_start]), index * sizeof(T));
pid_start += count;
}
pid_size -= count;
return *this;
}
void swap(PIDeque<T> & other) {
piSwap<T*>(pid_data, other.pid_data);
piSwap<size_t>(pid_size, other.pid_size);
piSwap<size_t>(pid_rsize, other.pid_rsize);
piSwap<size_t>(pid_start, other.pid_start);
}
typedef int (*CompareFunc)(const T * , const T * );
static int compare_func(const T * t0, const T * t1) {return (*t0) < (*t1) ? -1 : ((*t0) == (*t1) ? 0 : 1);}
PIDeque<T> & sort(CompareFunc compare = compare_func) {qsort(pid_data + pid_start, pid_size, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;}
PIDeque<T> & enlarge(llong pid_size) {llong ns = size_s() + pid_size; if (ns <= 0) clear(); else resize(size_t(ns)); return *this;}
PIDeque<T> & removeOne(const T & v) {for (size_t i = 0; i < pid_size; ++i) if (pid_data[i + pid_start] == v) {remove(i); return *this;} return *this;}
PIDeque<T> & removeAll(const T & v) {for (llong i = 0; i < pid_size; ++i) if (pid_data[i + pid_start] == v) {remove(i); --i;} return *this;}
PIDeque<T> & push_back(const T & v) {alloc(pid_size + 1, true); elementNew(pid_data + pid_start + pid_size - 1, v); return *this;}
PIDeque<T> & append(const T & v) {return push_back(v);}
PIDeque<T> & operator <<(const T & v) {return push_back(v);}
PIDeque<T> & operator <<(const PIDeque<T> & t) {
size_t ps = pid_size;
alloc(pid_size + t.pid_size, true);
newT(pid_data + ps + pid_start, t.pid_data + t.pid_start, t.pid_size);
return *this;
}
PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;}
PIDeque<T> & prepend(const T & v) {return push_front(v);}
PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;}
PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;}
T take_back() {T t(back()); pop_back(); return t;}
T take_front() {T t(front()); pop_front(); return t;}
private:
void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
/*void * qmemmove(void * dst, void * src, size_t size) {
if (piAbs<ssize_t>(ssize_t(dst) - ssize_t(src)) >= size)
memcpy(dst, src, size);
else {
char * tb = new char[size];
memcpy(tb, src, size);
memcpy(dst, tb, size);
delete tb;
}
return dst;
}*/
inline size_t asize(ssize_t s) {
if (s <= 0) return 0;
if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s))
return pid_rsize + pid_rsize;
size_t t = 0, s_ = size_t(s) - 1;
while (s_ >> t) ++t;
return (1 << t);
}
inline void newT(T * dst, const T * src, size_t s) {
for (size_t i = 0; i < s; ++i)
elementNew(dst + i, src[i]);
}
inline T * newRaw(size_t s) {
//cout << std::dec << " ![("<<this<<")newRaw " << s << " elements ... <\n" << endl;
//uchar * ret = new uchar[s * sizeof(T)];
uchar * ret = (uchar*)(malloc(s * sizeof(T)));//new uchar[];
//zeroRaw((T*)ret, s);
//cout << std::hex << " > (new 0x" << (llong)ret << ") ok]!" << endl;
return (T*)ret;
}
/*void reallocRawTemp(size_t s) {
if (pid_tdata == 0) pid_tdata = (T*)(malloc(s * sizeof(T)));
else pid_tdata = (T*)(realloc(pid_tdata, s * sizeof(T)));
}*/
inline void deleteT(T * d, size_t sz) {
//cout << " ~[("<<this<<")deleteT " << std::dec << sz << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl;
if ((uchar*)d != 0) {
for (size_t i = 0; i < sz; ++i)
elementDelete(d[i]);
//zeroRaw(d, sz);
}
//cout << " > ok]~" << endl;
}
inline void deleteRaw(T *& d) {
//cout << " ~[("<<this<<")deleteRaw " << std::dec << pid_rsize << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl;
if ((uchar*)d != 0) free((uchar*)d);
d = 0;
//cout << " > ok]~" << endl;
}
void zeroRaw(T * d, size_t s) {
//cout << " ~[("<<this<<")zeroRaw " << std::dec << s << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl;
if ((uchar*)d != 0) memset(d, 0, s*sizeof(T));
//cout << " > ok]~" << endl;
}
inline void elementNew(T * to, const T & from) {new(to)T(from);}
inline void elementDelete(T & from) {from.~T();}
void dealloc() {deleteRaw(pid_data);}
inline void checkMove(bool direction) {
if (pid_size >= 4 && pid_size < pid_rsize / 4) {
/*if (direction) {
if (pid_start >= 4 && pid_start > pid_size + pid_size && pid_start > pid_rsize / 2) {
piCout << (int)this << "checkMove" << direction << pid_start << (int)pid_data << pid_rsize << pid_size;
piCout << (int)this << "move from" << pid_start << "to" << pid_size << "," << (int)pid_data << pid_rsize << pid_size;
memmove(pid_data + pid_size, pid_data + pid_start, pid_size * sizeof(T));
pid_start = pid_size;
}
} else {
if (ssize_t(pid_start) < ssize_t(pid_rsize) - pid_size - pid_size && ssize_t(pid_start) < ssize_t(pid_rsize / 2) - pid_size) {
piCout << (int)this << "checkMove" << direction << pid_start << (int)pid_data << pid_rsize << pid_size;
piCout << (int)this << "move from" << pid_start << "to" << (ssize_t(pid_rsize) - pid_size) << "," << (int)pid_data << pid_rsize << pid_size;
memmove(pid_data + ssize_t(pid_rsize) - pid_size - pid_size, pid_data + pid_start, pid_size * sizeof(T));
pid_start = ssize_t(pid_rsize) - pid_size - pid_size;
}
}*/
if (pid_start < pid_size + pid_size || pid_start > pid_rsize - pid_size - pid_size) {
size_t ns = (pid_rsize - pid_size) / 2;
if (pid_start != ns) {
memmove(pid_data + ns, pid_data + pid_start, pid_size * sizeof(T));
pid_start = ns;
}
}
}
}
inline void alloc(size_t new_size, bool direction) { // direction == true -> alloc forward
if (direction) {
if (pid_start + new_size <= pid_rsize) {
pid_size = new_size;
checkMove(direction);
return;
}
pid_size = new_size;
size_t as = asize(pid_start + new_size);
if (as != pid_rsize) {
pid_data = (T*)(realloc(pid_data, as*sizeof(T)));
pid_rsize = as;
}
} else {
size_t as = asize(piMax<ssize_t>(new_size, pid_rsize) - pid_start);
//piCout << "alloc" << new_size << pid_size << pid_rsize << as << pid_start;
if (pid_start >= 0 && as <= pid_rsize) {
pid_size = new_size;
checkMove(direction);
return;
}
size_t os = pid_size;
pid_size = new_size;
if (as > pid_rsize) {
//piCout << "alloc new size" << as;
//cout << std::hex << " ![("<<this<<")realloc " << pid_data << " data ... <\n" << endl;
T * td = newRaw(as);
//piCout << "pid_start" << pid_start << (pid_start + ssize_t(as) - os);
ssize_t ost = pid_start, ns = 0;
if (ost < 0) {ns -= ost; ost = 0;}
pid_start += ssize_t(as) - os;
if (os > 0 && pid_data != 0) {
memcpy(td + pid_start + ns, pid_data + ost, os * sizeof(T));
deleteRaw(pid_data);
}
pid_data = td;
pid_rsize = as;
}
}
//checkMove(direction);
//piCout << "alloc new start" << pid_start;
}
T * pid_data;
size_t pid_size, pid_rsize;
size_t pid_start;
};
#define __PIDEQUE_SIMPLE_TYPE__(T) \
template<> inline void PIDeque<T>::newT(T * dst, const T * src, size_t s) {memcpy(dst, src, s * sizeof(T));} \
template<> inline void PIDeque<T>::deleteT(T * d, size_t sz) {;} \
template<> inline void PIDeque<T>::elementNew(T * to, const T & from) {(*to) = from;} \
template<> inline void PIDeque<T>::elementDelete(T & from) {;}
#else
template<typename Type, typename Allocator = std::allocator<Type> >
class PIP_EXPORT PIDeque: public deque<Type, Allocator> {
typedef PIDeque<Type, Allocator> _CDeque;
typedef deque<Type, Allocator> _stlc;
public:
PIDeque() {piMonitor.containers++;}
PIDeque(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);}
PIDeque(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);}
PIDeque(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);}
PIDeque(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);}
~PIDeque() {piMonitor.containers--;}
int size_s() const {return static_cast<int>(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;}
int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;}
_CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;}
PIDeque<Type> toVector() {PIDeque<Type> v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
#define __PIDEQUE_SIMPLE_FUNCTIONS__(T)
#endif
template<typename T>
inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
template<typename T>
inline PICout operator <<(PICout s, const PIDeque<T> & v) {s.space(); s.setControl(0, true); s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
#endif // PIDEQUE_H

230
pidir.cpp
View File

@@ -19,7 +19,7 @@
#include "pidir.h" #include "pidir.h"
#if !defined(WINDOWS) && !defined(ANDROID) #if !defined(ANDROID)
#ifdef WINDOWS #ifdef WINDOWS
const PIChar PIDir::separator = '\\'; const PIChar PIDir::separator = '\\';
#else #else
@@ -27,47 +27,40 @@
#endif #endif
PIDir::PIDir() { PIDir::PIDir(const PIString & dir) {
path_ = PIDir::current().path_; path_ = dir;
dir_ = 0;
open();
} }
PIDir::PIDir(const PIString & dir) { PIDir::PIDir(const PIFile & file) {
path_ = dir; path_ = file.path();
dir_ = 0; if (isExists()) return;
open(); int pos = path_.findLast(separator);
path_.cutRight(path_.size_s() - pos);
} }
bool PIDir::operator ==(const PIDir & d) const { bool PIDir::operator ==(const PIDir & d) const {
return true; return d.absolutePath() == absolutePath();
} }
bool PIDir::open() { bool PIDir::isAbsolute() const {
if (dir_ != 0) if (path_.size() == 0) return false;
if (!close()) #ifdef WINDOWS
return false; if (path_.size() < 3) return false;
dir_ = opendir(path_.data()); return (path_[1] == ":");
return (dir_ != 0); #else
return (path_[0] == separator);
#endif
} }
bool PIDir::close() { PIString PIDir::absolutePath() const {
if (dir_ == 0) return true; if (isAbsolute()) return path_;
if (closedir(dir_) == 0) { PIDir d(path_);
dir_ = 0; d.setDir(PIDir::current().path_ + separator + path_);
return true; return d.path_;
}
return false;
}
PIString PIDir::absolutePath() {
//di;
return PIString();
} }
@@ -75,12 +68,15 @@ PIDir & PIDir::cleanPath() {
PIString p(path_); PIString p(path_);
if (p.size() == 0) { if (p.size() == 0) {
path_ = "."; path_ = ".";
open();
return *this; return *this;
} }
path_.replaceAll(PIString(separator) + PIString(separator), PIString(separator)); path_.replaceAll(PIString(separator) + PIString(separator), PIString(separator));
bool isAbs = isAbsolute(); bool is_abs = isAbsolute();
PIStringList l = PIString(p).split(separator); PIStringList l = PIString(p).split(separator);
#ifdef WINDOWS
PIString letter;
if (is_abs) letter = l.take_front();
#endif
l.removeAll("."); l.removeAll(".");
l.removeAll(""); l.removeAll("");
bool found = true; bool found = true;
@@ -102,112 +98,216 @@ PIDir & PIDir::cleanPath() {
if (l.size() > 0) if (l[0] == "..") if (l.size() > 0) if (l[0] == "..")
{l.pop_front(); found = true;} {l.pop_front(); found = true;}
} }
path_ = separator + l.join(separator); path_ = separator + l.join(separator); /// TODO think about windows
if (!isAbs) path_.insert(0, "."); if (!is_abs) path_.prepend(".");
if (path_.size() == 0) path_ = "./"; #ifdef WINDOWS
open(); else path_.prepend(letter);
#endif
if (path_.size() == 0) path_ = ".";
return *this;
}
PIDir & PIDir::setDir(const PIString & path) {
path_ = path;
cleanPath();
return *this; return *this;
} }
PIDir & PIDir::cd(const PIString & path) { PIDir & PIDir::cd(const PIString & path) {
if (path_.size() == 0) return *this; if (path_.size() == 0) return *this;
if (path_[path_.size() - 1] != separator) path_ << separator; if (path_[path_.size() - 1] != separator) path_ += separator;
path_ << path; path_ += path;
return cleanPath(); return cleanPath();
} }
bool PIDir::mkDir(bool withParents) { bool PIDir::make(bool withParents) {
PIDir d = cleanedPath(); PIDir d = cleanedPath();
PIString tp; PIString tp;
int ret; bool is_abs = isAbsolute();
bool isAbs = isAbsolute();
if (withParents) { if (withParents) {
PIStringList l = d.path_.split(separator); PIStringList l = d.path_.split(separator);
for (int i = l.size_s() - 1; i >= 0; --i) { for (int i = l.size_s() - 1; i >= 0; --i) {
if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator); if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator);
else { else {
tp = separator; tp = separator;
if (!isAbs) tp.push_front('.'); if (!is_abs) tp.push_front('.');
} }
//cout << tp << endl; //cout << tp << endl;
if (isExists(tp)) { if (isExists(tp)) {
for (int j = i + 1; j <= l.size_s(); ++j) { for (int j = i + 1; j <= l.size_s(); ++j) {
tp = PIStringList(l).remove(j, l.size_s() - j).join(separator); tp = PIStringList(l).remove(j, l.size_s() - j).join(separator);
//cout << tp << endl; //cout << tp << endl;
ret = mkdir(tp.data(), 16877); if (makeDir(tp)) continue;
if (ret == 0) continue; else return false;
printf("[PIDir] mkDir(\"%s\") error: %s\n", d.path_.data(), strerror(errno));
return false;
} }
break; break;
}; };
} }
} else { } else
ret = mkdir(d.path_.data(), 16877); if (makeDir(d.path_)) return true;
if (ret == 0) return true;
printf("[PIDir] mkDir(\"%s\") error: %s\n", d.path_.data(), strerror(errno));
}
return false; return false;
} }
PIVector<PIDir::DirEntry> PIDir::entries() { PIVector<PIDir::DirEntry> PIDir::entries() {
PIDir d = cleanedPath(); PIVector<DirEntry> l;
PIString p = d.path_; PIString p(cleanedPath().path_);
#ifdef WINDOWS
WIN32_FIND_DATA fd; memset(&fd, 0, sizeof(fd));
p += "\\*";
void * hf = FindFirstFile((LPCTSTR)(p.data()), &fd);
if (!hf) return l;
LARGE_INTEGER filesize;
do {
int m = 0;
filesize.LowPart = filesize.HighPart = 0;
if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) m |= S_IFHDN;
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) m |= S_IFBLK;
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) m |= S_IFDIR;
else {
m |= S_IFREG;
filesize.LowPart = fd.nFileSizeLow;
filesize.HighPart = fd.nFileSizeHigh;
}
l << DirEntry(fd.cFileName, m, filesize.QuadPart);
memset(&fd, 0, sizeof(fd));
} while (FindNextFile(hf, &fd) != 0);
FindClose(hf);
#else
dirent ** list; dirent ** list;
# ifndef QNX # ifndef QNX
int cnt = scandir(const_cast<char*>(p.data()), &list, 0, alphasort); int cnt = scandir(p.data(), &list, 0, versionsort);
# else # else
int cnt = scandir(const_cast<char*>(p.data()), 0, 0, alphasort); int cnt = scandir(const_cast<char*>(p.data()), 0, 0, versionsort);
# endif # endif
struct stat fs; struct stat fs;
PIVector<DirEntry> l;
for (int i = 0; i < cnt; ++i) { for (int i = 0; i < cnt; ++i) {
stat((p + separator + PIString(list[i]->d_name)).data(), &fs); stat((p + separator + PIString(list[i]->d_name)).data(), &fs);
l.push_back(DirEntry(list[i]->d_name, fs.st_mode, fs.st_size)); l << DirEntry(list[i]->d_name, fs.st_mode, fs.st_size);
if (list[i]->d_name[0] == '.') l.back().mode |= S_IFHDN;
delete list[i]; delete list[i];
} }
delete list; delete list;
#endif
return l; return l;
} }
bool PIDir::isExists(const PIString & path) {
#ifdef WINDOWS
return (GetFileAttributes((LPCTSTR)(path.data())) & FILE_ATTRIBUTE_DIRECTORY);
#else
DIR * dir_ = opendir(path.data());
if (dir_ == 0) return false;
closedir(dir_);
#endif
return true;
}
PIDir PIDir::current() { PIDir PIDir::current() {
char rc[1024]; char rc[1024];
#ifdef WINDOWS
memset(rc, 0, 1024);
if (GetCurrentDirectory(1024, (LPTSTR)rc) == 0) return PIString();
#else
if (getcwd(rc, 1024) == 0) return PIString(); if (getcwd(rc, 1024) == 0) return PIString();
#endif
return PIDir(rc); return PIDir(rc);
} }
PIDir PIDir::home() { PIDir PIDir::home() {
return PIDir(getenv("HOME")); char * rc = 0;
#ifdef WINDOWS
rc = new char[1024];
memset(rc, 0, 1024);
if (ExpandEnvironmentStrings((LPCTSTR)"%HOMEPATH%", (LPTSTR)rc, 1024) == 0) {
delete[] rc;
return PIDir();
}
PIString s(rc);
delete[] rc;
return PIDir(s);
#else
rc = getenv("HOME");
if (rc == 0) return PIDir();
return PIDir(rc);
#endif
} }
PIDir PIDir::temporary() { PIDir PIDir::temporary() {
char * rc; char * rc = 0;
#ifdef WINDOWS
rc = new char[1024];
memset(rc, 0, 1024);
int ret = GetTempPath(1024, (LPTSTR)rc);
if (ret == 0) {
delete[] rc;
return PIDir();
}
PIString s(rc);
delete[] rc;
return PIDir(s);
#else
rc = tmpnam(0); rc = tmpnam(0);
if (rc == 0) return PIDir();
PIString s(rc); PIString s(rc);
return PIDir(s.left(s.findLast(PIDir::separator))); return PIDir(s.left(s.findLast(PIDir::separator)));
#endif
} }
bool PIDir::mkDir(const PIString & path, bool withParents) { bool PIDir::make(const PIString & path, bool withParents) {
PIDir d(path); PIDir d(path);
if (d.isExists()) return true; if (d.isExists()) return true;
return d.mkDir(withParents); return d.make(withParents);
} }
bool PIDir::rmDir(const PIString & path) { bool PIDir::setCurrent(const PIString & path) {
string s = path.stdString(); #ifdef WINDOWS
int ret = rmdir(s.c_str()); if (SetCurrentDirectory((LPCTSTR)(path.data())) != 0) return true;
if (ret == 0) return true; #else
printf("[PIDir] rmDir(\"%s\") error: %s\n", s.c_str(), strerror(errno)); if (chdir(path.data()) == 0) return true;
#endif
printf("[PIDir] setCurrent(\"%s\") error: %s\n", path.data(), errorString().c_str());
return false; return false;
} }
bool PIDir::makeDir(const PIString & path) {
#ifdef WINDOWS
if (CreateDirectory((LPCTSTR)(path.data()), NULL) != 0) return true;
#else
if (mkdir(path.data(), 16877) == 0) return true;
#endif
printf("[PIDir] makeDir(\"%s\") error: %s\n", path.data(), errorString().c_str());
return false;
}
bool PIDir::removeDir(const PIString & path) {
#ifdef WINDOWS
if (RemoveDirectory((LPCTSTR)(path.data())) != 0) return true;
#else
if (rmdir(path.data()) == 0) return true;
#endif
printf("[PIDir] removeDir(\"%s\") error: %s\n", path.data(), errorString().c_str());
return false;
}
bool PIDir::renameDir(const PIString & path, const PIString & new_name) {
if (::rename(path.data(), new_name.data()) == 0) return true;
printf("[PIDir] renameDir(\"%s\", \"%s\") error: %s\n", path.data(), new_name.data(), errorString().c_str());
return false;
}
#endif #endif

77
pidir.h
View File

@@ -21,26 +21,40 @@
#define PIDIR_H #define PIDIR_H
#include "pifile.h" #include "pifile.h"
#include "pistring.h" #if !defined(ANDROID)
#if !defined(WINDOWS) && !defined(ANDROID) #ifdef WINDOWS
# undef S_IFDIR
# undef S_IFREG
# undef S_IFLNK
# undef S_IFBLK
# undef S_IFCHR
# undef S_IFSOCK
# define S_IFDIR 0x01
# define S_IFREG 0x02
# define S_IFLNK 0x04
# define S_IFBLK 0x08
# define S_IFCHR 0x10
# define S_IFSOCK 0x20
#else
# ifdef ANDROID # ifdef ANDROID
# include <sys/dirent.h> # include <sys/dirent.h>
# else # else
# include <sys/dir.h> # include <sys/dir.h>
# endif # endif
# include <sys/stat.h> # include <sys/stat.h>
#endif
#define S_IFHDN 0x40
class PIP_EXPORT PIDir class PIP_EXPORT PIDir
{ {
public: public:
PIDir(); PIDir(const PIString & dir = PIString());
PIDir(const PIString & dir); PIDir(const PIFile & file);
~PIDir() {close();}
struct DirEntry { struct DirEntry {
DirEntry() {;} DirEntry(const PIString & name_ = PIString(), int mode_ = 0, int size_ = 0) {
DirEntry(const PIString & name_, const int & mode_, const int & size_) { name = name_; mode = mode_; size = size_;
name = name_; mode = mode_; size = size_;} }
PIString name; PIString name;
int mode; int mode;
@@ -52,41 +66,62 @@ public:
bool isBlockDevice() const {return (mode & S_IFBLK);} bool isBlockDevice() const {return (mode & S_IFBLK);}
bool isCharacterDevice() const {return (mode & S_IFCHR);} bool isCharacterDevice() const {return (mode & S_IFCHR);}
bool isSocket() const {return (mode & S_IFSOCK);} bool isSocket() const {return (mode & S_IFSOCK);}
bool isHidden() const {return (mode & S_IFHDN);}
}; };
bool isExists() const {return (dir_ != 0);} bool isExists() const {return PIDir::isExists(path_);}
bool isAbsolute() const {if (path_.size() == 0) return false; return (path_[0] == separator);} bool isAbsolute() const;
bool isRelative() const {return !isAbsolute();}
const PIString & path() const {return path_;} const PIString & path() const {return path_;}
PIString absolutePath() const;
PIDir & cleanPath(); PIDir & cleanPath();
PIDir cleanedPath() {PIDir d(path_); d.cleanPath(); return d;} PIDir cleanedPath() const {PIDir d(path_); d.cleanPath(); return d;}
PIString absolutePath(); PIDir & setDir(const PIString & path);
bool mkDir(bool withParents = true); bool setCurrent() {return PIDir::setCurrent(path_);}
PIVector<DirEntry> entries(); PIVector<DirEntry> entries();
bool make(bool withParents = true);
bool remove() {return PIDir::remove(path_);}
bool rename(const PIString & new_name) {if (!PIDir::rename(path_, new_name)) return false; path_ = new_name; return true;}
PIDir & cd(const PIString & path); PIDir & cd(const PIString & path);
PIDir & up() {return cd("..");} PIDir & up() {return cd("..");}
bool operator ==(const PIDir & d) const; bool operator ==(const PIDir & d) const;
bool operator !=(const PIDir & d) const {return !((*this) == d);}
static const PIChar separator; static const PIChar separator;
static PIDir current(); static PIDir current();
static PIDir home(); static PIDir home();
static PIDir temporary(); static PIDir temporary();
static bool mkDir(const PIString & path, bool withParents = true); static bool isExists(const PIString & path);
static bool rmDir(const PIString & path); static bool make(const PIString & path, bool withParents = true);
static bool isExists(const PIString & path) {return PIDir(path).isExists();} static bool remove(const PIString & path) {return removeDir(path);}
//static bool rmDir(const PIString & path); static bool rename(const PIString & path, const PIString & new_name) {return PIDir::renameDir(path, new_name);}
static bool setCurrent(const PIString & path);
static bool setCurrent(const PIDir & dir) {return setCurrent(dir.path_);}
private: private:
bool open(); static bool makeDir(const PIString & path);
bool close(); static bool removeDir(const PIString & path);
static bool renameDir(const PIString & path, const PIString & new_name);
PIString path_; PIString path_;
DIR * dir_;
}; };
inline bool operator <(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name < v1.name);}
inline bool operator >(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name > v1.name);}
inline bool operator ==(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name == v1.name);}
inline bool operator !=(const PIDir::DirEntry & v0, const PIDir::DirEntry & v1) {return (v0.name != v1.name);}
inline PICout operator <<(PICout s, const PIDir & v) {s.setControl(0, true); s << "PIDir(\"" << v.path() << "\")"; s.restoreControl(); return s;}
inline PICout operator <<(PICout s, const PIDir::DirEntry & v) {s.setControl(0, true); s << "DirEntry(\"" << v.name << "\", " << v.size << " b, " << PIString::fromNumber(v.mode, 16) << ")"; s.restoreControl(); return s;}
#endif #endif
#endif // PIDIR_H #endif // PIDIR_H

View File

@@ -90,7 +90,7 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
setParameters(PIEthernet::ReuseAddress); setParameters(PIEthernet::ReuseAddress);
setThreadedReadBufferSize(65536); setThreadedReadBufferSize(65536);
setPriority(piHigh); setPriority(piHigh);
setType(TCP_Client); setType(TCP_Client, false);
setPath(ip_port); setPath(ip_port);
} }
@@ -165,7 +165,7 @@ bool PIEthernet::openDevice() {
init(); init();
if (sock == -1 || path().isEmpty()) return false; if (sock == -1 || path().isEmpty()) return false;
parseAddress(path(), &ip_, &port_); parseAddress(path(), &ip_, &port_);
if (type() != UDP) if (type() != UDP && mode() == PIIODevice::WriteOnly)
return true; return true;
//piCout << "bind to" << (params[PIEthernet::Broadcast] ? "bc" : ip_) << ":" << port_ << " ..."; //piCout << "bind to" << (params[PIEthernet::Broadcast] ? "bc" : ip_) << ":" << port_ << " ...";
memset(&addr_, 0, sizeof(addr_)); memset(&addr_, 0, sizeof(addr_));
@@ -563,6 +563,17 @@ bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
} }
PIString PIEthernet::constructFullPath() const {
PIString ret(fullPathPrefix() + "://");
ret << (type() == PIEthernet::UDP ? "UDP" : "TCP") << ":" << readIP() << ":" << readPort();
if (type() == PIEthernet::UDP) {
piForeachC (PIString & m, multicastGroups())
ret << ":mcast:" << m;
}
return ret;
}
void PIEthernet::configureFromFullPath(const PIString & full_path) { void PIEthernet::configureFromFullPath(const PIString & full_path) {
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
bool mcast = false; bool mcast = false;
@@ -574,8 +585,8 @@ void PIEthernet::configureFromFullPath(const PIString & full_path) {
if (p == "udp") setType(UDP); if (p == "udp") setType(UDP);
if (p == "tcp") setType(TCP_Client); if (p == "tcp") setType(TCP_Client);
break; break;
case 1: setReadIP(p); break; case 1: setReadIP(p); setSendIP(p); break;
case 2: setReadPort(p.toInt()); break; case 2: setReadPort(p.toInt()); setSendPort(p.toInt()); break;
} }
if (i <= 2) continue; if (i <= 2) continue;
if (i % 2 == 1) {if (p.toLowerCase() == "mcast") mcast = true;} if (i % 2 == 1) {if (p.toLowerCase() == "mcast") mcast = true;}

View File

@@ -83,23 +83,23 @@ public:
//! Returns read address in format "i.i.i.i:p" //! Returns read address in format "i.i.i.i:p"
PIString readAddress() {return path();} PIString readAddress() const {return path();}
//! Returns read IP //! Returns read IP
PIString readIP() {parseAddress(path(), &ip_, &port_); return ip_;} PIString readIP() const {parseAddress(path(), &ip_, &port_); return ip_;}
//! Returns read port //! Returns read port
int readPort() {parseAddress(path(), &ip_, &port_); return port_;} int readPort() const {parseAddress(path(), &ip_, &port_); return port_;}
//! Returns send address in format "i.i.i.i:p" //! Returns send address in format "i.i.i.i:p"
PIString sendAddress() {return ip_s + ":" + PIString::fromNumber(port_s);} PIString sendAddress() const {return ip_s + ":" + PIString::fromNumber(port_s);}
//! Returns send IP //! Returns send IP
PIString sendIP() {return ip_s;} PIString sendIP() const {return ip_s;}
//! Returns send port //! Returns send port
int sendPort() {return port_s;} int sendPort() const {return port_s;}
//! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them //! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
@@ -179,6 +179,8 @@ public:
//! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client //! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
int write(const PIByteArray & data) {return write(data.data(), data.size_s());} int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
PIString constructFullPath() const;
EVENT1(newConnection, PIEthernet * , client) EVENT1(newConnection, PIEthernet * , client)
EVENT0(connected) EVENT0(connected)
EVENT1(disconnected, bool, withError) EVENT1(disconnected, bool, withError)
@@ -327,10 +329,11 @@ protected:
#endif #endif
int sock, sock_s, port_, port_s, port_c, wrote; int sock, sock_s, wrote;
mutable int port_, port_s, port_c;
bool connected_, connecting_; bool connected_, connecting_;
sockaddr_in addr_, saddr_; sockaddr_in addr_, saddr_;
PIString ip_, ip_s, ip_c; mutable PIString ip_, ip_s, ip_c;
PIThread server_thread_; PIThread server_thread_;
PIVector<PIEthernet * > clients_; PIVector<PIEthernet * > clients_;
PIQueue<PIString> mcast_queue; PIQueue<PIString> mcast_queue;
@@ -341,7 +344,7 @@ protected:
private: private:
static void server_func(void * eth); static void server_func(void * eth);
void setType(Type t) {setProperty("type", (int)t); if (isOpened()) {closeDevice(); init(); openDevice();}} void setType(Type t, bool reopen = true) {setProperty("type", (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}}
static std::string ethErrorString() { static std::string ethErrorString() {
#ifdef WINDOWS #ifdef WINDOWS

View File

@@ -148,6 +148,11 @@ bool PIFile::isExists(const PIString & path) {
} }
PIString PIFile::constructFullPath() const {
return fullPathPrefix() + "://" + path();
}
void PIFile::configureFromFullPath(const PIString & full_path) { void PIFile::configureFromFullPath(const PIString & full_path) {
setPath(full_path); setPath(full_path);
} }

View File

@@ -92,10 +92,10 @@ public:
//! Read from file to "read_to" no more than "max_size" and return readed bytes count //! Read from file to "read_to" no more than "max_size" and return readed bytes count
int read(void * read_to, int max_size) {if (!canRead() || fd == 0) return -1; return fread(read_to, max_size, 1, fd);} int read(void * read_to, int max_size) {if (!canRead() || fd == 0) return -1; return fread(read_to, 1, max_size, fd);}
//! Write to file "data" with size "max_size" and return written bytes count //! Write to file "data" with size "max_size" and return written bytes count
int write(const void * data, int max_size) {if (!canWrite() || fd == 0) return -1; return fwrite(data, max_size, 1, fd);} int write(const void * data, int max_size) {if (!canWrite() || fd == 0) return -1; return fwrite(data, 1, max_size, fd);}
PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable() || fd == 0) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;} PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable() || fd == 0) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;}
@@ -183,6 +183,7 @@ public:
//! Read from file text representation of "v" //! Read from file text representation of "v"
PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;} PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;}
PIString constructFullPath() const;
EVENT_HANDLER(void, clear) {close(); fd = fopen(path().data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();} EVENT_HANDLER(void, clear) {close(); fd = fopen(path().data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();}
EVENT_HANDLER0(void, remove) {close(); std::remove(path().data());} EVENT_HANDLER0(void, remove) {close(); std::remove(path().data());}

View File

@@ -40,6 +40,7 @@ clock_serv_t __pi_mac_clock;
#endif #endif
PIMutex __PICout_mutex__; PIMutex __PICout_mutex__;
PIString __PICout_string__;
#ifdef WINDOWS #ifdef WINDOWS
@@ -127,6 +128,9 @@ DWORD PICout::smode = 0;
#endif #endif
bool PICout::buffer_ = false;
PICout::PICout(PIFlags<PICoutControl> controls): fo_(true), cc_(false), fc_(false), cnb_(10), co_(controls) { PICout::PICout(PIFlags<PICoutControl> controls): fo_(true), cc_(false), fc_(false), cnb_(10), co_(controls) {
#ifdef WINDOWS #ifdef WINDOWS
if (hOut == 0) { if (hOut == 0) {
@@ -156,8 +160,12 @@ PICout PICout::operator<<(const PICoutAction v) {
CONSOLE_CURSOR_INFO curinfo; CONSOLE_CURSOR_INFO curinfo;
#endif #endif
switch (v) { switch (v) {
case PICoutManipulators::Flush: std::cout << std::flush; break; case PICoutManipulators::Flush:
if (!PICout::buffer_)
std::cout << std::flush;
break;
case PICoutManipulators::Backspace: case PICoutManipulators::Backspace:
if (!PICout::buffer_) {
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleScreenBufferInfo(hOut, &sbi); GetConsoleScreenBufferInfo(hOut, &sbi);
coord = sbi.dwCursorPosition; coord = sbi.dwCursorPosition;
@@ -168,8 +176,10 @@ PICout PICout::operator<<(const PICoutAction v) {
#else #else
printf("\e[1D \e[1D"); printf("\e[1D \e[1D");
#endif #endif
}
break; break;
case PICoutManipulators::ShowCursor: case PICoutManipulators::ShowCursor:
if (!PICout::buffer_) {
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleCursorInfo(hOut, &curinfo); GetConsoleCursorInfo(hOut, &curinfo);
curinfo.bVisible = true; curinfo.bVisible = true;
@@ -177,8 +187,10 @@ PICout PICout::operator<<(const PICoutAction v) {
#else #else
printf("\e[?25h"); printf("\e[?25h");
#endif #endif
}
break; break;
case PICoutManipulators::HideCursor: case PICoutManipulators::HideCursor:
if (!PICout::buffer_) {
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleCursorInfo(hOut, &curinfo); GetConsoleCursorInfo(hOut, &curinfo);
curinfo.bVisible = false; curinfo.bVisible = false;
@@ -186,8 +198,10 @@ PICout PICout::operator<<(const PICoutAction v) {
#else #else
printf("\e[?25l"); printf("\e[?25l");
#endif #endif
}
break; break;
case PICoutManipulators::ClearScreen: case PICoutManipulators::ClearScreen:
if (!PICout::buffer_) {
#ifdef WINDOWS #ifdef WINDOWS
/// TODO !!! /// TODO !!!
/*GetConsoleCursorInfo(hOut, &curinfo); /*GetConsoleCursorInfo(hOut, &curinfo);
@@ -200,6 +214,7 @@ PICout PICout::operator<<(const PICoutAction v) {
#else #else
printf("\e[H\e[J"); printf("\e[H\e[J");
#endif #endif
}
break; break;
case PICoutManipulators::SaveContol: saveControl(); break; case PICoutManipulators::SaveContol: saveControl(); break;
case PICoutManipulators::RestoreControl: restoreControl(); break; case PICoutManipulators::RestoreControl: restoreControl(); break;
@@ -209,9 +224,19 @@ PICout PICout::operator<<(const PICoutAction v) {
} }
#define PINUMERICCOUT if (cnb_ == 10) std::cout << v; else std::cout << PIString::fromNumber(v, cnb_); #define PICOUTTOTARGET(v) {if (PICout::buffer_) __PICout_string__ << (v); else std::cout << (v);}
#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_))
PICout PICout::operator <<(const uchar v) {space(); if (cnb_ == 10) std::cout << ushort(v); else std::cout << PIString::fromNumber(v, cnb_); return *this;}
PICout PICout::operator <<(const char * v) {space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
PICout PICout::operator <<(const string & v) {space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
PICout PICout::operator <<(const bool v) {space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
PICout PICout::operator <<(const char v) {space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const uchar v) {space(); if (cnb_ == 10) PICOUTTOTARGET(ushort(v)) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_)) return *this;}
PICout PICout::operator <<(const short int v) {space(); PINUMERICCOUT return *this;} PICout PICout::operator <<(const short int v) {space(); PINUMERICCOUT return *this;}
@@ -229,18 +254,91 @@ PICout PICout::operator <<(const llong v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const ullong v) {space(); PINUMERICCOUT return *this;} PICout PICout::operator <<(const ullong v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const float v) {space(); std::cout << v; return *this;} PICout PICout::operator <<(const float v) {space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const double v) {space(); std::cout << v; return *this;} PICout PICout::operator <<(const double v) {space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const void * v) {space(); std::cout << "0x" << PIString::fromNumber(ullong(v), 16); return *this;} PICout PICout::operator <<(const void * v) {space(); PICOUTTOTARGET("0x") PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16)) return *this;}
PICout PICout::operator <<(const PIObject * v) {space(); if (v == 0) std::cout << "PIObject*(0x0)"; else std::cout << v->className() << "*(" << "0x" << PIString::fromNumber(ullong(v), 16) << ", \"" << v->name() << "\")"; return *this;} PICout PICout::operator <<(const PIObject * v) {
space();
if (v == 0) PICOUTTOTARGET("PIObject*(0x0)")
else {
PICOUTTOTARGET(v->className())
PICOUTTOTARGET("*(0x")
PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16))
PICOUTTOTARGET(", \"")
PICOUTTOTARGET(v->name())
PICOUTTOTARGET("\")")
}
return *this;
}
PICout PICout::operator <<(const PICoutSpecialChar v) {
switch (v) {
case Null:
if (PICout::buffer_) __PICout_string__ << PIChar(0);
else std::cout << char(0);
break;
case NewLine:
if (PICout::buffer_) __PICout_string__ << "\n";
else std::cout << '\n';
fo_ = true;
break;
case Tab:
if (PICout::buffer_) __PICout_string__ << "\t";
else std::cout << '\t';
break;
case Esc:
#ifdef CC_VC
if (PICout::buffer_) __PICout_string__ << PIChar(27);
else std::cout << char(27);
#else
if (PICout::buffer_) __PICout_string__ << "\e";
else std::cout << '\e';
#endif
break;
case Quote:
if (PICout::buffer_) __PICout_string__ << "\"";
else std::cout << '"';
break;
};
return *this;
}
#undef PICOUTTOTARGET
#undef PINUMERICCOUT #undef PINUMERICCOUT
PICout & PICout::space() {
if (!fo_ && co_[AddSpaces]) {
if (PICout::buffer_) __PICout_string__ << " ";
else std::cout << ' ';
}
fo_ = false;
return *this;
}
PICout & PICout::quote() {
if (co_[AddQuotes]) {
if (PICout::buffer_) __PICout_string__ << "\"";
else std::cout << '"';
}
fo_ = false;
return *this;
}
PICout & PICout::newLine() {
if (co_[AddNewLine]) {
if (PICout::buffer_) __PICout_string__ << "\n";
else std::cout << std::endl;
}
fo_ = false;
return *this;
}
void PICout::applyFormat(PICoutFormat f) { void PICout::applyFormat(PICoutFormat f) {
if (PICout::buffer_) return;
fc_ = true; fc_ = true;
#ifdef WINDOWS #ifdef WINDOWS
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
@@ -300,6 +398,34 @@ void PICout::applyFormat(PICoutFormat f) {
} }
bool PICout::setBufferActive(bool on, bool clear) {
PIMutexLocker ml(__PICout_mutex__);
bool ret = PICout::buffer_;
if (clear) __PICout_string__.clear();
PICout::buffer_ = on;
return ret;
}
bool PICout::isBufferActive() {
return PICout::buffer_;
}
PIString PICout::buffer(bool clear) {
PIMutexLocker ml(__PICout_mutex__);
PIString ret = __PICout_string__;
if (clear) __PICout_string__.clear();
return ret;
}
void PICout::clearBuffer() {
PIMutexLocker ml(__PICout_mutex__);
__PICout_string__.clear();
}
/*! \class PICout /*! \class PICout
* \brief Class for formatted output similar std::cout * \brief Class for formatted output similar std::cout
* *
@@ -326,11 +452,12 @@ void PICout::applyFormat(PICoutFormat f) {
* PIP - Platform-Independent Primitives - is crossplatform library for C++ developers. * PIP - Platform-Independent Primitives - is crossplatform library for C++ developers.
* It is wrap around STL and pure C++. This library can help developers write non-GUI * It is wrap around STL and pure C++. This library can help developers write non-GUI
* projects much more quickly, efficiently and customizable than on pure C++. * projects much more quickly, efficiently and customizable than on pure C++.
* Library contains more classes, some of them are pure abstract, some classes * Library contains many classes, some of them are pure abstract, some classes
* can be used as they are, some classes should be inherited to new classes. * can be used as they are, some classes should be inherited to new classes.
* PIP provide classes: * PIP provide classes:
* * direct output to console (\a PICout) * * direct output to console (\a PICout)
* * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack) * * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack)
* * byte array (\a PIByteArray)
* * string (\a PIString, \a PIStringList) * * string (\a PIString, \a PIStringList)
* * base object (events and handlers) (\a PIObject) * * base object (events and handlers) (\a PIObject)
* * thread (\a PIThread) * * thread (\a PIThread)
@@ -346,6 +473,8 @@ void PICout::applyFormat(PICoutFormat f) {
* * ethernet (\a PIEthernet) * * ethernet (\a PIEthernet)
* * USB (\a PIUSB) * * USB (\a PIUSB)
* * packets extractor (\a PIPacketExtractor) * * packets extractor (\a PIPacketExtractor)
* * binary log (\a PIBinaryLog)
* * connection quality diagnotic (\a PIDiagnostics)
* * command-line arguments parser (\a PICLI) * * command-line arguments parser (\a PICLI)
* * math evaluator (\a PIEvaluator) * * math evaluator (\a PIEvaluator)
* * peering net node (\a PIPeer) * * peering net node (\a PIPeer)

View File

@@ -39,7 +39,7 @@
#define PIP_VERSION_REVISION PIP_VERSION & 0xFF #define PIP_VERSION_REVISION PIP_VERSION & 0xFF
//! Suffix of PIP version //! Suffix of PIP version
#define PIP_VERSION_SUFFIX "_prealpha" #define PIP_VERSION_SUFFIX "_beta2"
#ifdef DOXYGEN #ifdef DOXYGEN
@@ -747,7 +747,10 @@ private:
class PIObject; class PIObject;
class PIMutex; class PIMutex;
class PIString;
extern PIMutex __PICout_mutex__; extern PIMutex __PICout_mutex__;
extern PIString __PICout_string__;
//! \brief Namespace contains enums controlled PICout //! \brief Namespace contains enums controlled PICout
namespace PICoutManipulators { namespace PICoutManipulators {
@@ -825,16 +828,16 @@ public:
~PICout(); ~PICout();
//! Output operator for strings with <tt>"const char * "</tt> type //! Output operator for strings with <tt>"const char * "</tt> type
PICout operator <<(const char * v) {space(); quote(); std::cout << v; quote(); return *this;} PICout operator <<(const char * v);
//! Output operator for strings with <tt>"std::string"</tt> type //! Output operator for strings with <tt>"std::string"</tt> type
PICout operator <<(const string & v) {space(); quote(); std::cout << v; quote(); return *this;} PICout operator <<(const string & v);
//! Output operator for boolean values //! Output operator for boolean values
PICout operator <<(const bool v) {space(); std::cout << (v ? "true" : "false"); return *this;} PICout operator <<(const bool v);
//! Output operator for <tt>"char"</tt> values //! Output operator for <tt>"char"</tt> values
PICout operator <<(const char v) {space(); std::cout << v; return *this;} PICout operator <<(const char v);
//! Output operator for <tt>"unsigned char"</tt> values //! Output operator for <tt>"unsigned char"</tt> values
PICout operator <<(const uchar v); PICout operator <<(const uchar v);
@@ -876,23 +879,7 @@ public:
PICout operator <<(const PIObject * v); PICout operator <<(const PIObject * v);
//! Output operator for \a PICoutSpecialChar values //! Output operator for \a PICoutSpecialChar values
PICout operator <<(const PICoutSpecialChar v) { PICout operator <<(const PICoutSpecialChar v);
switch (v) {
case Null: std::cout << char(0); break;
case NewLine: std::cout << '\n'; fo_ = true; break;
case Tab: std::cout << '\t'; break;
case Esc:
#ifdef CC_VC
std::cout << char(27);
#else
std::cout << '\e';
#endif
break;
case Quote: std::cout << '"'; break;
};
return *this;
}
//! Output operator for \a PIFlags<PICoutFormat> values //! Output operator for \a PIFlags<PICoutFormat> values
PICout operator <<(const PIFlags<PICoutFormat> v) { PICout operator <<(const PIFlags<PICoutFormat> v) {
@@ -955,21 +942,27 @@ public:
/*! \brief Conditional put space character to output /*! \brief Conditional put space character to output
* \details If it is not a first output and control \a AddSpaces is set * \details If it is not a first output and control \a AddSpaces is set
* space character is put \sa \a quote(), \a newLine() */ * space character is put \sa \a quote(), \a newLine() */
inline PICout & space() {if (!fo_ && co_[AddSpaces]) std::cout << ' '; fo_ = false; return *this;} PICout & space();
/*! \brief Conditional put quote character to output /*! \brief Conditional put quote character to output
* \details If control \a AddQuotes is set * \details If control \a AddQuotes is set
* quote character is put \sa \a space(), \a newLine() */ * quote character is put \sa \a space(), \a newLine() */
inline PICout & quote() {if (co_[AddQuotes]) std::cout << '"'; fo_ = false; return *this;} PICout & quote();
/*! \brief Conditional put new line character to output /*! \brief Conditional put new line character to output
* \details If control \a AddNewLine is set * \details If control \a AddNewLine is set
* new line character is put \sa \a space(), \a quote() */ * new line character is put \sa \a space(), \a quote() */
inline PICout & newLine() {if (co_[AddNewLine]) std::cout << std::endl; fo_ = false; return *this;} PICout & newLine();
static bool setBufferActive(bool on, bool clear = false);
static bool isBufferActive();
static PIString buffer(bool clear = false);
static void clearBuffer();
private: private:
void applyFormat(PICoutFormat f); void applyFormat(PICoutFormat f);
static bool buffer_;
bool fo_, cc_, fc_; bool fo_, cc_, fc_;
int cnb_, attr_; int cnb_, attr_;
PICoutControls co_; PICoutControls co_;

View File

@@ -127,6 +127,9 @@ public:
//! Return content of threaded read buffer //! Return content of threaded read buffer
const uchar * threadedReadBuffer() const {return buffer_tr.data();} const uchar * threadedReadBuffer() const {return buffer_tr.data();}
//! Return custom data that will be passed to "threaded read slot"
void * threadedReadData() const {return ret_data_;}
//! Return \b true if threaded read is started //! Return \b true if threaded read is started
bool isThreadedRead() const {return isRunning();} bool isThreadedRead() const {return isRunning();}
@@ -189,6 +192,9 @@ public:
bool configure(const PIString & config_file, const PIString & section, bool parent_section = false); bool configure(const PIString & config_file, const PIString & section, bool parent_section = false);
//! Reimplement to construct full unambiguous string, describes this device, default returns \a path()
virtual PIString constructFullPath() const {return path();}
//! \brief Try to determine suitable device, create new one, configure it with \a configureFromFullPath() and returns it. //! \brief Try to determine suitable device, create new one, configure it with \a configureFromFullPath() and returns it.
//! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://". //! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://".
//! See \ref PIIODevice_sec7 //! See \ref PIIODevice_sec7
@@ -197,7 +203,7 @@ public:
EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER1(bool, open, const PIString &, _path) {setPath(_path); if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} EVENT_HANDLER1(bool, open, const PIString &, _path) {setPath(_path); if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER1(bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} EVENT_HANDLER1(bool, open, const DeviceMode &, _mode) {mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _mode) {setPath(_path); mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _mode) {setPath(_path); mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
EVENT_HANDLER(bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;} EVENT_HANDLER(bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;}
EVENT_HANDLER(bool, initialize) {init_ = init(); return init_;} EVENT_HANDLER(bool, initialize) {init_ = init(); return init_;}
@@ -289,9 +295,6 @@ protected:
//! Reimplement to construct full unambiguous string prefix. \ref PIIODevice_sec7 //! Reimplement to construct full unambiguous string prefix. \ref PIIODevice_sec7
virtual PIString fullPathPrefix() const {return PIString();} virtual PIString fullPathPrefix() const {return PIString();}
//! Reimplement to construct full unambiguous string, describes this device, default returns \a path()
virtual PIString constructFullPath() const {return path();}
//! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing //! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing
virtual void configureFromFullPath(const PIString & full_path) {;} virtual void configureFromFullPath(const PIString & full_path) {;}

View File

@@ -90,9 +90,9 @@ void PIKbdListener::run() {
case 40: ret = 1; lc = (ctrl ? CtrlDownArrow : DownArrow); break; case 40: ret = 1; lc = (ctrl ? CtrlDownArrow : DownArrow); break;
default: ret = 1; lc = (shift ? char(toupper(ker.uChar.AsciiChar)) : ker.uChar.AsciiChar); break; default: ret = 1; lc = (shift ? char(toupper(ker.uChar.AsciiChar)) : ker.uChar.AsciiChar); break;
} }
if (lc == 0) return; if (lc == 0) {piMSleep(10); return;}
} else return; } else {piMSleep(10); return;}
} else return; } else {piMSleep(10); return;}
/*if (lc == 0) { /*if (lc == 0) {
ReadConsole(hIn, &rc, 1, &ret, 0); ReadConsole(hIn, &rc, 1, &ret, 0);
//cout << "read console" << endl; //cout << "read console" << endl;
@@ -105,7 +105,7 @@ void PIKbdListener::run() {
cout << endl << std::hex << rc << endl;*/ cout << endl << std::hex << rc << endl;*/
#else #else
ret = read(0, &rc, 4); ret = read(0, &rc, 4);
if (ret < 0 || ret > 3) return; if (ret < 0 || ret > 3) {piMSleep(10); return;}
lc = char(((uchar * )&rc)[ret - 1]); lc = char(((uchar * )&rc)[ret - 1]);
//for (int i = 0; i < ret; ++i) //for (int i = 0; i < ret; ++i)
// cout << std::hex << int(((uchar * )&rc)[i]) << ' '; // cout << std::hex << int(((uchar * )&rc)[i]) << ' ';

103
pimap.h
View File

@@ -26,9 +26,10 @@
#define PIMAP_H #define PIMAP_H
#include "pivector.h" #include "pivector.h"
#include "pideque.h"
#if 0 // !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) #if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN)
template<class T> template<class T>
void piQuickSort(T * a, ssize_t N) { void piQuickSort(T * a, ssize_t N) {
@@ -54,7 +55,7 @@ template <typename Key, typename T>
class PIMap { class PIMap {
public: public:
PIMap() {;} PIMap() {;}
PIMap(const PIMap<Key, T> & other) {;} PIMap(const PIMap<Key, T> & other) {*this = other;}
~PIMap() {;} ~PIMap() {;}
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) { PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
@@ -69,6 +70,42 @@ public:
typedef Key key_type; typedef Key key_type;
typedef PIPair<Key, T> value_type; typedef PIPair<Key, T> value_type;
class iterator {
friend class PIMap<Key, T>;
private:
iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
const PIMap<Key, T> * parent;
ssize_t pos;
public:
iterator(): parent(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(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 reverse_iterator {
friend class PIMap<Key, T>;
private:
reverse_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
const PIMap<Key, T> * parent;
ssize_t pos;
public:
reverse_iterator(): parent(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(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_iterator { class const_iterator {
friend class PIMap<Key, T>; friend class PIMap<Key, T>;
private: private:
@@ -78,12 +115,14 @@ public:
public: public:
const_iterator(): parent(0) {} const_iterator(): parent(0) {}
const PIMap<Key, T>::value_type operator *() const {return parent->_pair(pos);} const PIMap<Key, T>::value_type operator *() const {return parent->_pair(pos);}
const PIMap<Key, T>::value_type* operator ->() const {cval = parent->_pair(pos); return &cval;}
void operator ++() {++pos;} void operator ++() {++pos;}
void operator ++(int) {++pos;} void operator ++(int) {++pos;}
void operator --() {--pos;} void operator --() {--pos;}
void operator --(int) {--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);}
bool operator !=(const const_iterator & it) const {return (pos != it.pos);} bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
mutable value_type cval;
}; };
class const_reverse_iterator { class const_reverse_iterator {
@@ -95,20 +134,22 @@ public:
public: public:
const_reverse_iterator(): parent(0) {} const_reverse_iterator(): parent(0) {}
const PIMap<Key, T>::value_type operator *() const {return parent->_pair(pos);} const PIMap<Key, T>::value_type operator *() const {return parent->_pair(pos);}
const PIMap<Key, T>::value_type* operator ->() const {cval = parent->_pair(pos); return &cval;}
void operator ++() {--pos;} void operator ++() {--pos;}
void operator ++(int) {--pos;} void operator ++(int) {--pos;}
void operator --() {++pos;} void operator --() {++pos;}
void operator --(int) {++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);}
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
mutable value_type cval;
}; };
// iterator begin() {return iterator(this, 0);} iterator begin() {return iterator(this, 0);}
// iterator end() {return iterator(this, size());} iterator end() {return iterator(this, size());}
const_iterator begin() const {return const_iterator(this, 0);} const_iterator begin() const {return const_iterator(this, 0);}
const_iterator end() const {return const_iterator(this, size());} const_iterator end() const {return const_iterator(this, size());}
// reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);} reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);}
// reverse_iterator rend() {return reverse_iterator(this, -1);} reverse_iterator rend() {return reverse_iterator(this, -1);}
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);} const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);}
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
@@ -126,6 +167,20 @@ public:
return pim_content.back(); return pim_content.back();
} }
const T operator [](const Key & key) const {bool f(false); ssize_t i = _find(key, f); if (f) return pim_content[pim_index[i].index]; return T();} const T operator [](const Key & key) const {bool f(false); ssize_t i = _find(key, f); if (f) return pim_content[pim_index[i].index]; return T();}
T & at(const Key & key) {return (*this)[key];}
const T at(const Key & key) const {return (*this)[key];}
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
if (other.isEmpty()) return *this;
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
pim_content << other.pim_content;
size_t si = pim_index.size();
for (int i = 0; i < other.pim_content.size_s(); ++i)
pim_index << MapIndex(other.pim_index[i].key, other.pim_index[i].index + si);
_sort();
return *this;
}
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);} bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);}
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);} bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);}
@@ -136,6 +191,8 @@ public:
//PIMap<Key, T> & removeAll(const T & v) {for (llong i = 0; i < pim_size; ++i) if (pim_data[i] == v) {remove(i); --i;} return *this;} //PIMap<Key, T> & removeAll(const T & v) {for (llong i = 0; i < pim_size; ++i) if (pim_data[i] == v) {remove(i); --i;} return *this;}
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;} PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;}
PIMap<Key, T> & remove(const Key & key) {return removeOne(key);}
PIMap<Key, T> & erase(const Key & key) {return removeOne(key);}
PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;} PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;}
void swap(PIMap<Key, T> & other) { void swap(PIMap<Key, T> & other) {
@@ -159,6 +216,13 @@ public:
} }
//const T value(const Key & key, const T & default_ = T()) const {MapIndex * i = _find(key); if (i == 0) return default_; return pim_content[i->index];} //const T value(const Key & key, const T & default_ = T()) const {MapIndex * i = _find(key); if (i == 0) return default_; return pim_content[i->index];}
const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];} const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];}
Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;}
PIVector<Key> keys() const {
PIVector<Key> ret;
for (int i = 0; i < pim_index.size_s(); ++i)
ret << pim_index[i].key;
return ret;
}
void dump() { void dump() {
piCout << "PIMap" << size() << "entries" << NewLine << "content:"; piCout << "PIMap" << size() << "entries" << NewLine << "content:";
@@ -174,8 +238,10 @@ private:
MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;} MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;}
Key key; Key key;
size_t index; size_t index;
//bool operator <(const MapIndex & s) const {return key < s.key;} bool operator ==(const MapIndex & s) const {return key == s.key;}
//bool operator >(const MapIndex & s) const {return key > s.key;} bool operator !=(const MapIndex & s) const {return key != s.key;}
bool operator <(const MapIndex & s) const {return key < s.key;}
bool operator >(const MapIndex & s) const {return key > s.key;}
}; };
ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const { ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
@@ -184,10 +250,7 @@ private:
mid = (first + last) / 2; mid = (first + last) / 2;
if (key > pim_index[mid].key) first = mid + 1; if (key > pim_index[mid].key) first = mid + 1;
else if (key < pim_index[mid].key) last = mid - 1; else if (key < pim_index[mid].key) last = mid - 1;
else { else {found = true; return mid;}
found = true;
return mid;
}
} }
found = false; found = false;
return first; return first;
@@ -225,16 +288,18 @@ private:
//piCout << "_pair" << index << pim_index[index].index; //piCout << "_pair" << index << pim_index[index].index;
return value_type(pim_index[index].key, pim_content[pim_index[index].index]); return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
} }
Key & _key(ssize_t index) {return pim_index[index].key;}
T & _value(ssize_t index) {return pim_content[pim_index[index].index];}
PIVector<T> pim_content; PIVector<T> pim_content;
PIVector<MapIndex> pim_index; PIDeque<MapIndex> pim_index;
}; };
//template <typename Key, typename T> bool operator <(const typename PIMap<Key, T>::MapIndex & f, const typename PIMap<Key, T>::MapIndex & s) {return f.key < s.key;} //template <typename Key, typename T> bool operator <(const typename PIMap<Key, T>::MapIndex & f, const typename PIMap<Key, T>::MapIndex & s) {return f.key < s.key;}
//template <typename Key, typename T> bool operator >(const typename PIMap<Key, T>::MapIndex & f, const typename PIMap<Key, T>::MapIndex & s) {return f.key > s.key;} //template <typename Key, typename T> bool operator >(const typename PIMap<Key, T>::MapIndex & f, const typename PIMap<Key, T>::MapIndex & s) {return f.key > s.key;}
#define __PIMAP_SIMPLE_FUNCTIONS__(T) /*#define __PIMAP_SIMPLE_FUNCTIONS__(T)
/* template<> inline PIMap<Key, T>::~PIMap() {dealloc(); _reset();} \ template<> inline PIMap<Key, T>::~PIMap() {dealloc(); _reset();} \
template<> inline PIMap<Key, T> & PIMap<Key, T>::push_back(const T & v) {alloc(pim_size + 1); pim_data[pim_size - 1] = v; return *this;} \ template<> inline PIMap<Key, T> & PIMap<Key, T>::push_back(const T & v) {alloc(pim_size + 1); pim_data[pim_size - 1] = v; return *this;} \
template<> inline PIMap<Key, T> & PIMap<Key, T>::fill(const T & f) { \ template<> inline PIMap<Key, T> & PIMap<Key, T>::fill(const T & f) { \
for (size_t i = 0; i < pim_size; ++i) \ for (size_t i = 0; i < pim_size; ++i) \
@@ -269,7 +334,7 @@ private:
memmove(&(pim_data[index]), &(pim_data[index + count]), os * sizeof(T)); \ memmove(&(pim_data[index]), &(pim_data[index + count]), os * sizeof(T)); \
pim_size -= count; \ pim_size -= count; \
return *this; \ return *this; \
}*/ }
__PIMAP_SIMPLE_FUNCTIONS__(char) __PIMAP_SIMPLE_FUNCTIONS__(char)
__PIMAP_SIMPLE_FUNCTIONS__(uchar) __PIMAP_SIMPLE_FUNCTIONS__(uchar)
@@ -283,7 +348,7 @@ __PIMAP_SIMPLE_FUNCTIONS__(llong)
__PIMAP_SIMPLE_FUNCTIONS__(ullong) __PIMAP_SIMPLE_FUNCTIONS__(ullong)
__PIMAP_SIMPLE_FUNCTIONS__(float) __PIMAP_SIMPLE_FUNCTIONS__(float)
__PIMAP_SIMPLE_FUNCTIONS__(double) __PIMAP_SIMPLE_FUNCTIONS__(double)
__PIMAP_SIMPLE_FUNCTIONS__(ldouble) __PIMAP_SIMPLE_FUNCTIONS__(ldouble)*/
#else #else
@@ -301,7 +366,7 @@ public:
int size_s() const {return static_cast<int>(_stlc::size());} int size_s() const {return static_cast<int>(_stlc::size());}
_CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;} _CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;}
_CMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} _CMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;}
Key key(Type value_) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();} Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;}
PIVector<Key> keys() const { PIVector<Key> keys() const {
PIVector<Key> ret; PIVector<Key> ret;
for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++)
@@ -325,7 +390,7 @@ public:
_CMultiMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} _CMultiMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;}
bool isEmpty() const {return _stlc::empty();} bool isEmpty() const {return _stlc::empty();}
bool contains(const Key & key_) const {return _stlc::count(key_) > 0;} bool contains(const Key & key_) const {return _stlc::count(key_) > 0;}
Key key(Type value_) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();} Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;}
PIVector<Key> keys(Type value_) const { PIVector<Key> keys(Type value_) const {
PIVector<Key> ret; PIVector<Key> ret;
for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++)

View File

@@ -23,7 +23,7 @@
#ifndef PIMATH_H #ifndef PIMATH_H
#define PIMATH_H #define PIMATH_H
#include "picontainers.h" #include "pibytearray.h"
#ifndef QNX #ifndef QNX
# include <complex> # include <complex>
# include <cmath> # include <cmath>
@@ -94,10 +94,10 @@ const complexd complexd_i(0., 1.);
const complexd complexd_0(0.); const complexd complexd_0(0.);
const complexd complexd_1(1.); const complexd complexd_1(1.);
__PIVECTOR_SIMPLE_FUNCTIONS__(complexi) __PICONTAINERS_SIMPLE_TYPE__(complexi)
__PIVECTOR_SIMPLE_FUNCTIONS__(complexf) __PICONTAINERS_SIMPLE_TYPE__(complexf)
__PIVECTOR_SIMPLE_FUNCTIONS__(complexd) __PICONTAINERS_SIMPLE_TYPE__(complexd)
__PIVECTOR_SIMPLE_FUNCTIONS__(complexld) __PICONTAINERS_SIMPLE_TYPE__(complexld)
const double deg2rad = M_PI_180; const double deg2rad = M_PI_180;
const double rad2deg = M_180_PI; const double rad2deg = M_180_PI;
@@ -165,6 +165,7 @@ class PIMathMatrixT;
#define PIMV_FOR(v, s) for (uint v = s; v < Size; ++v) #define PIMV_FOR(v, s) for (uint v = s; v < Size; ++v)
#pragma pack(push, 1)
template<uint Size, typename Type = double> template<uint Size, typename Type = double>
class PIP_EXPORT PIMathVectorT { class PIP_EXPORT PIMathVectorT {
typedef PIMathVectorT<Size, Type> _CVector; typedef PIMathVectorT<Size, Type> _CVector;
@@ -190,7 +191,7 @@ public:
Type angleRad(const _CVector & v) const {return acos(angleCos(v));} Type angleRad(const _CVector & v) const {return acos(angleCos(v));}
Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));}
_CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));}
_CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; PIMV_FOR(i, 0) c[i] /= tv; return *this;} _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs<Type>(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;}
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;}
bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);}
@@ -199,7 +200,7 @@ public:
Type at(uint index) const {return c[index];} Type at(uint index) const {return c[index];}
Type & operator [](uint index) {return c[index];} Type & operator [](uint index) {return c[index];}
Type operator [](uint index) const {return c[index];} Type operator [](uint index) const {return c[index];}
_CVector & operator =(const _CVector & v) {memcpy(&c, &(v.c), sizeof(Type) * Size); return *this;} _CVector & operator =(const _CVector & v) {memcpy(c, v.c, sizeof(Type) * Size); return *this;}
bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;} bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;}
bool operator !=(const _CVector & v) const {return !(*this == c);} bool operator !=(const _CVector & v) const {return !(*this == c);}
void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];} void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];}
@@ -233,6 +234,7 @@ private:
Type c[Size]; Type c[Size];
}; };
#pragma pack(pop)
template<uint Size, typename Type> template<uint Size, typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMathVectorT<Size, Type> & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;} inline std::ostream & operator <<(std::ostream & s, const PIMathVectorT<Size, Type> & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;}
@@ -245,6 +247,11 @@ inline PIMathVectorT<Size, Type> sqrt(const PIMathVectorT<Size, Type> & v) {PIMa
template<uint Size, typename Type> template<uint Size, typename Type>
inline PIMathVectorT<Size, Type> sqr(const PIMathVectorT<Size, Type> & v) {PIMathVectorT<Size, Type> ret; PIMV_FOR(i, 0) {ret[i] = sqr(v[i]);} return ret;} inline PIMathVectorT<Size, Type> sqr(const PIMathVectorT<Size, Type> & v) {PIMathVectorT<Size, Type> ret; PIMV_FOR(i, 0) {ret[i] = sqr(v[i]);} return ret;}
template<uint Size, typename Type>
inline PIByteArray & operator <<(PIByteArray & s, const PIMathVectorT<Size, Type> & v) {for (int i = 0; i < Size; ++i) s << v[i]; return s;}
template<uint Size, typename Type>
inline PIByteArray & operator >>(PIByteArray & s, PIMathVectorT<Size, Type> & v) {for (int i = 0; i < Size; ++i) s >> v[i]; return s;}
//template<uint Size0, typename Type0 = double, uint Size1 = Size0, typename Type1 = Type0> /// vector {Size0, Type0} to vector {Size1, Type1} //template<uint Size0, typename Type0 = double, uint Size1 = Size0, typename Type1 = Type0> /// vector {Size0, Type0} to vector {Size1, Type1}
//inline operator PIMathVectorT<Size1, Type1>(const PIMathVectorT<Size0, Type0> & v) {PIMathVectorT<Size1, Type1> tv; uint sz = piMin<uint>(Size0, Size1); for (uint i = 0; i < sz; ++i) tv[i] = v[i]; return tv;} //inline operator PIMathVectorT<Size1, Type1>(const PIMathVectorT<Size0, Type0> & v) {PIMathVectorT<Size1, Type1> tv; uint sz = piMin<uint>(Size0, Size1); for (uint i = 0; i < sz; ++i) tv[i] = v[i]; return tv;}
@@ -264,6 +271,7 @@ typedef PIMathVectorT<4u, double> PIMathVectorT4d;
#define PIMM_FOR_C(v) for (uint v = 0; v < Cols; ++v) #define PIMM_FOR_C(v) for (uint v = 0; v < Cols; ++v)
#define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v) #define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v)
#pragma pack(push, 1)
template<uint Cols, uint Rows = Cols, typename Type = double> template<uint Cols, uint Rows = Cols, typename Type = double>
class PIP_EXPORT PIMathMatrixT { class PIP_EXPORT PIMathMatrixT {
typedef PIMathMatrixT<Cols, Rows, Type> _CMatrix; typedef PIMathMatrixT<Cols, Rows, Type> _CMatrix;
@@ -299,7 +307,8 @@ public:
Type & at(uint col, uint row) {return m[col][row];} Type & at(uint col, uint row) {return m[col][row];}
Type at(uint col, uint row) const {return m[col][row];} Type at(uint col, uint row) const {return m[col][row];}
Type * operator [](uint col) {return m[col];} Type * operator [](uint col) {return m[col];}
void operator =(const _CMatrix & sm) {memcpy(&m, &(sm.m), sizeof(Type) * Cols * Rows);} const Type * operator [](uint col) const {return m[col];}
void operator =(const _CMatrix & sm) {memcpy(m, sm.m, sizeof(Type) * Cols * Rows);}
bool operator ==(const _CMatrix & sm) const {PIMM_FOR_WB(c, r) if (m[c][r] != sm.m[c][r]) return false; return true;} bool operator ==(const _CMatrix & sm) const {PIMM_FOR_WB(c, r) if (m[c][r] != sm.m[c][r]) return false; return true;}
bool operator !=(const _CMatrix & sm) const {return !(*this == sm);} bool operator !=(const _CMatrix & sm) const {return !(*this == sm);}
void operator +=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] += sm.m[c][r];} void operator +=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] += sm.m[c][r];}
@@ -350,7 +359,7 @@ public:
} }
} }
if (ok != 0) *ok = true; if (ok != 0) *ok = true;
m = smat.m; memcpy(m, smat.m, sizeof(Type) * Cols * Rows);
return *this; return *this;
} }
@@ -407,7 +416,7 @@ public:
} }
} }
if (ok != 0) *ok = true; if (ok != 0) *ok = true;
m = mtmp.m; memcpy(m, mtmp.m, sizeof(Type) * Cols * Rows);
return *this; return *this;
} }
_CMatrix inverted(bool * ok = 0) {_CMatrix tm(*this); tm.invert(ok); return tm;} _CMatrix inverted(bool * ok = 0) {_CMatrix tm(*this); tm.invert(ok); return tm;}
@@ -419,6 +428,7 @@ private:
Type m[Cols][Rows]; Type m[Cols][Rows];
}; };
#pragma pack(pop)
template<> inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::rotation(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<2u, 2u> tm; tm[0][0] = tm[1][1] = c; tm[0][1] = -s; tm[1][0] = s; return tm;} template<> inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::rotation(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<2u, 2u> tm; tm[0][0] = tm[1][1] = c; tm[0][1] = -s; tm[1][0] = s; return tm;}
@@ -512,7 +522,7 @@ public:
Type angleRad(const _CVector & v) const {return acos(angleCos(v));} Type angleRad(const _CVector & v) const {return acos(angleCos(v));}
Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));}
_CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));}
_CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; PIMV_FOR(i, 0) c[i] /= tv; return *this;} _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs<Type>(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;}
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;}
bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);}

View File

@@ -55,7 +55,7 @@ handler A: event to event
*/ */
PIObject::PIObject(const PIString & name) { PIObject::PIObject(const PIString & name): emitter_(0) {
piMonitor.objects++; piMonitor.objects++;
setName(name); setName(name);
setDebug(true); setDebug(true);

View File

@@ -26,6 +26,7 @@
#define PIOBJECT_H #define PIOBJECT_H
#include "pivariant.h" #include "pivariant.h"
#include "pimutex.h"
#ifdef DOXYGEN #ifdef DOXYGEN
@@ -258,7 +259,7 @@ public:
PIVariant property(const PIString & name) const {if (!properties_.contains(name)) return PIVariant(); return properties_.value(name);} PIVariant property(const PIString & name) const {if (!properties_.contains(name)) return PIVariant(); return properties_.value(name);}
//! Set property with name "name" to "value". If there is no such property in object it will be added //! Set property with name "name" to "value". If there is no such property in object it will be added
void setProperty(const PIString & name, const PIVariant & value) {properties_[name] = value;} void setProperty(const PIString & name, const PIVariant & value) {properties_[name] = value; propertyChanged(name);}
//! Returns if property with name "name" exists //! Returns if property with name "name" exists
bool isPropertyExists(const PIString & name) const {return properties_.contains(name);} bool isPropertyExists(const PIString & name) const {return properties_.contains(name);}
@@ -373,7 +374,11 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]); Connection & i(sender->connections[j]);
if (i.event != event) continue; if (i.event != event) continue;
((PIObject*)(i.dest))->mutex_.lock();
((PIObject*)(i.dest))->emitter_ = sender;
((void(*)(void * ))i.slot)(i.dest); ((void(*)(void * ))i.slot)(i.dest);
((PIObject*)(i.dest))->emitter_ = 0;
((PIObject*)(i.dest))->mutex_.unlock();
} }
} }
template <typename T0> template <typename T0>
@@ -381,7 +386,11 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]); Connection & i(sender->connections[j]);
if (i.event != event) continue; if (i.event != event) continue;
((PIObject*)(i.dest))->mutex_.lock();
((PIObject*)(i.dest))->emitter_ = sender;
((void(*)(void * , T0))i.slot)(i.dest, v0); ((void(*)(void * , T0))i.slot)(i.dest, v0);
((PIObject*)(i.dest))->emitter_ = 0;
((PIObject*)(i.dest))->mutex_.unlock();
} }
} }
template <typename T0, typename T1> template <typename T0, typename T1>
@@ -389,7 +398,11 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]); Connection & i(sender->connections[j]);
if (i.event != event) continue; if (i.event != event) continue;
((PIObject*)(i.dest))->mutex_.lock();
((PIObject*)(i.dest))->emitter_ = sender;
((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1);
((PIObject*)(i.dest))->emitter_ = 0;
((PIObject*)(i.dest))->mutex_.unlock();
} }
} }
template <typename T0, typename T1, typename T2> template <typename T0, typename T1, typename T2>
@@ -397,7 +410,11 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]); Connection & i(sender->connections[j]);
if (i.event != event) continue; if (i.event != event) continue;
((PIObject*)(i.dest))->mutex_.lock();
((PIObject*)(i.dest))->emitter_ = sender;
((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2);
((PIObject*)(i.dest))->emitter_ = 0;
((PIObject*)(i.dest))->mutex_.unlock();
} }
} }
template <typename T0, typename T1, typename T2, typename T3> template <typename T0, typename T1, typename T2, typename T3>
@@ -405,7 +422,11 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]); Connection & i(sender->connections[j]);
if (i.event != event) continue; if (i.event != event) continue;
((PIObject*)(i.dest))->mutex_.lock();
((PIObject*)(i.dest))->emitter_ = sender;
((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); ((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3);
((PIObject*)(i.dest))->emitter_ = 0;
((PIObject*)(i.dest))->mutex_.unlock();
} }
} }
/* /*
@@ -476,7 +497,7 @@ public:
raiseEvent<T0, T1, T2, T3>(name,dest , v0, v1, v2, v3); raiseEvent<T0, T1, T2, T3>(name,dest , v0, v1, v2, v3);
} }
//! Returns PIObject* with name "name" or 0, if there is no objects found //! Returns PIObject* with name "name" or 0, if there is no object found
static PIObject * findByName(const PIString & name) { static PIObject * findByName(const PIString & name) {
piForeach (PIObject * i, PIObject::objects) { piForeach (PIObject * i, PIObject::objects) {
if (i->name() != name) continue; if (i->name() != name) continue;
@@ -487,6 +508,12 @@ public:
protected: protected:
//! Returns PIObject* which has raised an event. This value is correct only in definition of some event handler
PIObject * emitter() const {return emitter_;}
//! Virtual function executes after property with name "name" has been changed
virtual void propertyChanged(const PIString & name) {}
private: private:
struct Connection { struct Connection {
Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), void * o = 0) {slot = sl; signal = si; event = e; dest = o;} Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), void * o = 0) {slot = sl; signal = si; event = e; dest = o;}
@@ -500,6 +527,8 @@ private:
PIMap<PIString, PIVariant> properties_; PIMap<PIString, PIVariant> properties_;
static PIVector<PIObject * > objects; static PIVector<PIObject * > objects;
PIMutex mutex_;
PIObject * emitter_;
}; };

View File

@@ -52,7 +52,9 @@ HEADERS += \
pidiagnostics.h \ pidiagnostics.h \
pibinarylog.h \ pibinarylog.h \
picodeparser.h \ picodeparser.h \
piusb.h picodeinfo.h \
piusb.h \
piconnection.h
SOURCES += main.cpp \ SOURCES += main.cpp \
pivariant.cpp \ pivariant.cpp \
pitimer.cpp \ pitimer.cpp \
@@ -85,7 +87,9 @@ SOURCES += main.cpp \
pidiagnostics.cpp \ pidiagnostics.cpp \
pibinarylog.cpp \ pibinarylog.cpp \
picodeparser.cpp \ picodeparser.cpp \
piusb.cpp picodeinfo.cpp \
piusb.cpp \
piconnection.cpp
win32 { win32 {
LIBS += -lws2_32 -lIphlpapi LIBS += -lws2_32 -lIphlpapi
} else { } else {

View File

@@ -19,7 +19,7 @@ VS_VERSION_INFO VERSIONINFO
BEGIN BEGIN
VALUE "CompanyName", "Peri4\0" VALUE "CompanyName", "Peri4\0"
VALUE "FileDescription", "Platform-Independent Primitives\0" VALUE "FileDescription", "Platform-Independent Primitives\0"
VALUE "FileVersion", "0.4.0_prealpha\0" VALUE "FileVersion", "0.4.0_beta2\0"
VALUE "LegalCopyright", "\0" VALUE "LegalCopyright", "\0"
VALUE "OriginalFilename", "libpip.dll\0" VALUE "OriginalFilename", "libpip.dll\0"
VALUE "ProductName", "PIP\0" VALUE "ProductName", "PIP\0"

View File

@@ -60,13 +60,34 @@
REGISTER_DEVICE(PIPacketExtractor); REGISTER_DEVICE(PIPacketExtractor);
PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, void * recHeaderPtr, int recHeaderSize, int recDataSize) { PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, PIPacketExtractor::SplitMode mode) {
ret_func_header = 0; init_();
setPacketData(recHeaderPtr, recHeaderSize, recDataSize); setDevice(device_);
setSplitMode(mode);
}
void PIPacketExtractor::init_() {
ret_func_header = ret_func_footer = 0;
setPayloadSize(0);
setTimeout(100);
setThreadedReadBufferSize(65536); setThreadedReadBufferSize(65536);
setBufferSize(65536); setBufferSize(65536);
setDevice(device_); setDevice(0);
allReaded = addSize = curInd = missed = 0; setPacketSize(0);
setSplitMode(None);
allReaded = addSize = curInd = missed = footerInd = 0;
header_found = false;
}
void PIPacketExtractor::propertyChanged(const PIString &) {
packetSize_ = property("packetSize").toInt();
mode_ = (SplitMode)(property("splitMode").toInt());
dataSize = property("payloadSize").toInt();
src_header = property("header").toByteArray();
src_footer = property("footer").toByteArray();
packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize();
} }
@@ -76,55 +97,181 @@ void PIPacketExtractor::setDevice(PIIODevice * device_) {
} }
void PIPacketExtractor::setPayloadSize(int size) {
setProperty("payloadSize", size);
dataSize = size;
packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize();
}
void PIPacketExtractor::setHeader(const PIByteArray & data) {
setProperty("header", data);
src_header = data;
packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize();
}
void PIPacketExtractor::setFooter(const PIByteArray & data) {
setProperty("footer", data);
src_footer = data;
packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize();
}
bool PIPacketExtractor::threadedRead(uchar * readed, int size_) { bool PIPacketExtractor::threadedRead(uchar * readed, int size_) {
memcpy(buffer.data(allReaded), readed, size_); //piCout << "readed" << size_;
int ss;
switch (mode_) {
case PIPacketExtractor::None:
packetReceived(readed, size_);
break;
case PIPacketExtractor::Header:
tmpbuf.append(readed, size_);
ss = src_header.size_s() + dataSize;
while (tmpbuf.size_s() >= ss) {
while (!validateHeader(src_header.data(), tmpbuf.data(), src_header.size_s())) {
tmpbuf.pop_front();
++missed;
if (tmpbuf.size_s() < ss) return true;
}
while (!validatePayload(tmpbuf.data(src_header.size_s()), dataSize)) {
tmpbuf.pop_front();
++missed;
if (tmpbuf.size_s() < ss) return true;
}
packetReceived(tmpbuf.data(), ss);
tmpbuf.remove(0, ss);
}
break;
case PIPacketExtractor::Footer:
/*memcpy(buffer.data(allReaded), readed, size_);
allReaded += size_; allReaded += size_;
while (allReaded >= packetSize + addSize && allReaded > 0) { footer_ = (mode_ == PIPacketExtractor::Footer);
if (headerSize > 0) { while (allReaded >= packetSize_hf + addSize && allReaded > 0) {
if (!src_header.isEmpty()) {
if (allReaded + curInd >= buffer_size) { if (allReaded + curInd >= buffer_size) {
memcpy(sbuffer.data(), buffer.data(), buffer_size); memcpy(sbuffer.data(), buffer.data(), buffer_size);
memcpy(buffer.data(), sbuffer.data(buffer_size - packetSize), allReaded); memcpy(buffer.data(), sbuffer.data(buffer_size - packetSize_hf), allReaded);
allReaded = packetSize; allReaded = packetSize_hf;
addSize = curInd = 0; addSize = curInd = 0;
} }
bool brk = false; bool brk = false;
while (!packetHeaderValidate((uchar * )headerPtr, buffer.data(curInd), headerSize)) { while (!validateHeader((uchar * )(footer_ ? src_footer.data() : src_header.data()), buffer.data(curInd + (footer_ ? dataSize : 0)), footer_ ? src_footer.size_s() : src_header.size_s())) {
curInd++; missed++; ++curInd; ++missed;
if (packetSize > 0) missed_packets = missed / packetSize; if (packetSize_hf > 0) missed_packets = missed / packetSize_hf;
if (curInd > addSize) { if (curInd > addSize) {
addSize += packetSize; addSize += packetSize_hf;
brk = true; brk = true;
break; break;
} }
} }
if (brk) continue; if (brk) continue;
memcpy(mheader.data(), buffer.data(curInd), headerSize); //memcpy(mheader.data(), buffer.data(curInd + (footer_ ? dataSize : 0)), src_header.size_s());
if (headerPtr != 0) memcpy(headerPtr, buffer.data(curInd), headerSize); if (!src_header.isEmpty()) memcpy(src_header.data(), buffer.data(curInd), src_header.size_s());
if (!packetValidate(buffer.data(curInd + headerSize), dataSize)) { if (!validatePayload(buffer.data(curInd + src_header.size_s()), dataSize)) {
curInd++; missed++; ++curInd; ++missed;
if (packetSize > 0) missed_packets = missed / packetSize; if (packetSize_hf > 0) missed_packets = missed / packetSize_hf;
continue; continue;
} }
packetReceived(buffer.data(curInd), packetSize); packetReceived(buffer.data(curInd), packetSize_hf);
memcpy(sbuffer.data(), buffer.data(), allReaded); memcpy(sbuffer.data(), buffer.data(), allReaded);
memcpy(buffer.data(), sbuffer.data(packetSize + curInd), allReaded); memcpy(buffer.data(), sbuffer.data(packetSize_hf + curInd), allReaded);
allReaded -= packetSize + curInd; allReaded -= packetSize_hf + curInd;
curInd = addSize = 0; curInd = addSize = 0;
} else { } else {
if (dataSize == 0) { if (dataSize == 0) {
if (packetValidate(buffer.data(), size_)) if (validatePayload(buffer.data(), size_))
packetReceived(buffer.data(), size_); packetReceived(buffer.data(), size_);
memcpy(sbuffer.data(), buffer.data(), allReaded); memcpy(sbuffer.data(), buffer.data(), allReaded);
memcpy(buffer.data(), sbuffer.data(size_), allReaded); memcpy(buffer.data(), sbuffer.data(size_), allReaded);
allReaded -= size_; allReaded -= size_;
} else { } else {
if (packetValidate(buffer.data(), dataSize)) if (validatePayload(buffer.data(), dataSize))
packetReceived(buffer.data(), dataSize); packetReceived(buffer.data(), dataSize);
memcpy(sbuffer.data(), buffer.data(), allReaded); memcpy(sbuffer.data(), buffer.data(), allReaded);
memcpy(buffer.data(), sbuffer.data(packetSize), allReaded); memcpy(buffer.data(), sbuffer.data(packetSize_hf), allReaded);
allReaded -= packetSize; allReaded -= packetSize_hf;
} }
} }
}*/
tmpbuf.append(readed, size_);
ss = src_footer.size_s() + dataSize;
while (tmpbuf.size_s() >= ss) {
while (!validateFooter(src_footer.data(), tmpbuf.data(dataSize), src_footer.size_s())) {
tmpbuf.pop_front();
++missed;
if (tmpbuf.size_s() < ss) return true;
} }
while (!validatePayload(tmpbuf.data(), dataSize)) {
tmpbuf.pop_front();
++missed;
if (tmpbuf.size_s() < ss) return true;
}
packetReceived(tmpbuf.data(), ss);
tmpbuf.remove(0, ss);
}
break;
case PIPacketExtractor::HeaderAndFooter:
tmpbuf.append(readed, size_);
ss = src_header.size_s() + src_footer.size_s();
while (tmpbuf.size_s() >= ss) {
if (!header_found) {
if (tmpbuf.size_s() < ss) return true;
while (!validateHeader(src_header.data(), tmpbuf.data(), src_header.size_s())) {
tmpbuf.pop_front();
++missed;
if (tmpbuf.size_s() < ss) return true;
}
header_found = true;
footerInd = src_header.size_s();
} else {
if (tmpbuf.size_s() < footerInd + src_footer.size_s()) return true;
while (!validateFooter(src_footer.data(), tmpbuf.data(footerInd), src_footer.size_s())) {
++footerInd;
if (tmpbuf.size_s() < footerInd + src_footer.size_s()) return true;
}
//piCout << "footer found at" << footerInd;
header_found = false;
if (!validatePayload(tmpbuf.data(src_header.size_s()), footerInd - src_header.size_s())) {
tmpbuf.pop_front();
++missed;
continue;
}
packetReceived(tmpbuf.data(), footerInd + src_footer.size_s());
tmpbuf.remove(0, footerInd + src_footer.size_s());
footerInd = src_header.size_s();
}
}
break;
case PIPacketExtractor::Timeout:
memcpy(buffer.data(), readed, size_);
trbuf = dev->readForTime(time_);
memcpy(buffer.data(size_), trbuf.data(), trbuf.size());
if (size_ + trbuf.size() > 0)
packetReceived(buffer.data(), size_ + trbuf.size());
break;
case PIPacketExtractor::Size:
tmpbuf.append(readed, size_);
if (packetSize_ <= 0) {
tmpbuf.clear();
return true; return true;
} }
while (tmpbuf.size_s() >= packetSize_) {
if (!validatePayload(tmpbuf.data(), packetSize_)) {
tmpbuf.pop_front();
++missed;
missed_packets = missed / packetSize_;
continue;
}
packetReceived(tmpbuf.data(), packetSize_);
tmpbuf.remove(0, packetSize_);
}
break;
};
return true;
}
PIString PIPacketExtractor::constructFullPath() const {
return fullPathPrefix() + "://";
}

View File

@@ -27,15 +27,25 @@
#include "piiodevice.h" #include "piiodevice.h"
// Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false. // Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false.
typedef bool (*HeaderCheckFunc)(void * , uchar * , uchar * , int ); typedef bool (*PacketExtractorCheckFunc)(void * , uchar * , uchar * , int );
class PIP_EXPORT PIPacketExtractor: public PIIODevice class PIP_EXPORT PIPacketExtractor: public PIIODevice
{ {
PIIODEVICE(PIPacketExtractor) PIIODEVICE(PIPacketExtractor)
friend class PIConnection;
public: public:
enum SplitMode {
None,
Header,
Footer,
HeaderAndFooter,
Size,
Timeout
};
//! Contructs extractor with child device "device_", header content pointer "recHeaderPtr", header size "recHeaderSize" and payload size "recDataSize" //! Contructs extractor with child device "device_", header content pointer "recHeaderPtr", header size "recHeaderSize" and payload size "recDataSize"
PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0); PIPacketExtractor(PIIODevice * device_ = 0, SplitMode mode = None);
virtual ~PIPacketExtractor() {stop();} virtual ~PIPacketExtractor() {stop();}
@@ -53,17 +63,30 @@ public:
//! Set buffer size to "new_size" bytes, should be at least greater than whole packet size //! Set buffer size to "new_size" bytes, should be at least greater than whole packet size
void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size); memset(buffer.data(), 0, buffer.size()); memset(sbuffer.data(), 0, sbuffer.size());} void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size); memset(buffer.data(), 0, buffer.size()); memset(sbuffer.data(), 0, sbuffer.size());}
void setHeaderCheckSlot(HeaderCheckFunc f) {ret_func_header = f;} void setHeaderCheckSlot(PacketExtractorCheckFunc f) {ret_func_header = f;}
void setFooterCheckSlot(PacketExtractorCheckFunc f) {ret_func_footer = f;}
void setPayloadCheckSlot(ReadRetFunc f) {ret_func_ = f;}
//! Set header content pointer "recHeaderPtr", header size "recHeaderSize" and payload size "recDataSize" void setSplitMode(SplitMode mode) {setProperty("splitMode", int(mode)); mode_ = mode;}
void setPacketData(void * recHeaderPtr, int recHeaderSize, int recDataSize) {headerPtr = recHeaderPtr; headerSize = recHeaderSize; dataSize = recDataSize; packetSize = headerSize + dataSize; if (headerSize > 0) mheader.resize(headerSize);} void setPayloadSize(int size);
void setHeader(const PIByteArray & data);
void setFooter(const PIByteArray & data);
void setTimeout(double msecs) {setProperty("timeout", msecs); time_ = msecs;}
void setPacketSize(int size) {setProperty("packetSize", size); packetSize_ = size;}
SplitMode splitMode() const {return (SplitMode)(property("splitMode").toInt());}
int payloadSize() const {return property("payloadSize").toInt();}
PIByteArray header() const {return src_header;}
PIByteArray footer() const {return src_footer;}
double timeout() const {return property("timeout").toDouble();}
int packetSize() const {return property("packetSize").toInt();}
//! Returns missed by validating functions bytes count //! Returns missed by validating functions bytes count
ullong missedBytes() const {return missed;} ullong missedBytes() const {return missed;}
//! Returns missed by validating functions packets count, = missedBytes() / packetSize //! Returns missed by validating functions packets count, = missedBytes() / packetSize
ullong missedPackets() const {if (packetSize == 0) return missed; return missed / packetSize;} ullong missedPackets() const {/*if (packetSize_hf == 0) return missed; return missed / packetSize_hf*/; return missed_packets;}
//! Returns pointer to \a missedBytes() count. Useful for output to PIConsole //! Returns pointer to \a missedBytes() count. Useful for output to PIConsole
const ullong * missedBytes_ptr() const {return &missed;} const ullong * missedBytes_ptr() const {return &missed;}
@@ -82,6 +105,8 @@ public:
//! Directly call \a write() function of child %device //! Directly call \a write() function of child %device
int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);} int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);}
PIString constructFullPath() const;
EVENT2(packetReceived, uchar * , data, int, size) EVENT2(packetReceived, uchar * , data, int, size)
//! \events //! \events
@@ -95,25 +120,40 @@ public:
protected: protected:
/** \brief Function to validate header /** \brief Function to validate header
* \param src Your header content passed from constructor or with function \a setPacketData() * \param src Your header content
* \param rec Received header * \param rec Received header
* \param size Header size * \param size Header size
* \details Default implementation returns by-byte "src" with "rec" compare result */ * \details Default implementation returns by-byte "src" with "rec" compare result */
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;} virtual bool validateHeader(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;}
//! Function to validate packet paylod after successfully header validate. Default implementation returns \b true /** \brief Function to validate footer
virtual bool packetValidate(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;} * \param src Your footer content
* \param rec Received footer
* \param size Footer size
* \details Default implementation returns by-byte "src" with "rec" compare result */
virtual bool validateFooter(uchar * src, uchar * rec, int size) {if (ret_func_footer != 0) return ret_func_footer(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;}
/** \brief Function to validate payload
* \param rec Received payload
* \param size payload size
* \details Default implementation returns \b true */
virtual bool validatePayload(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;}
private: private:
void init_();
void propertyChanged(const PIString & );
bool threadedRead(uchar * readed, int size); bool threadedRead(uchar * readed, int size);
PIString fullPathPrefix() const {return "pckext";} PIString fullPathPrefix() const {return "pckext";}
bool openDevice() {if (dev == 0) return false; return dev->open();} bool openDevice() {if (dev == 0) return false; return dev->open();}
PIIODevice * dev; PIIODevice * dev;
PIByteArray mheader, buffer, sbuffer; PIByteArray mheader, buffer, sbuffer, tmpbuf, src_header, src_footer, trbuf;
HeaderCheckFunc ret_func_header; PacketExtractorCheckFunc ret_func_header, ret_func_footer;
void * headerPtr, * data; SplitMode mode_;
int buffer_size, dataSize, headerSize, packetSize, allReaded, addSize, curInd; void * data;
int buffer_size, dataSize, packetSize_hf, allReaded, addSize, curInd, footerInd, packetSize_;
double time_;
bool header_found;
ullong missed, missed_packets; ullong missed, missed_packets;

View File

@@ -53,7 +53,8 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * r
dataSize = recDataSize; dataSize = recDataSize;
sendDataPtr = (uchar * )sendDataPtr_; sendDataPtr = (uchar * )sendDataPtr_;
sendDataSize = sendDataSize_; sendDataSize = sendDataSize_;
packet_ext->setPacketData(recHeaderPtr, recHeaderSize, recDataSize); packet_ext->setHeader(PIByteArray(recHeaderPtr, recHeaderSize));
packet_ext->setPayloadSize(recDataSize);
} }
@@ -83,7 +84,7 @@ PIProtocol::~PIProtocol() {
void PIProtocol::init() { void PIProtocol::init() {
packet_ext = new PIPacketExtractor(); packet_ext = new PIPacketExtractor(0, PIPacketExtractor::Header);
packet_ext->setThreadedReadData(this); packet_ext->setThreadedReadData(this);
packet_ext->setThreadedReadSlot(receiveEvent); packet_ext->setThreadedReadSlot(receiveEvent);
packet_ext->setHeaderCheckSlot(headerValidateEvent); packet_ext->setHeaderCheckSlot(headerValidateEvent);
@@ -94,6 +95,7 @@ void PIProtocol::init() {
mp_owner = 0; mp_owner = 0;
net_diag = PIProtocol::Unknown; net_diag = PIProtocol::Unknown;
cur_pckt = 0; cur_pckt = 0;
packets[0] = packets[1] = pckt_cnt = pckt_cnt_max = 0;
diagTimer = 0; diagTimer = 0;
timeout_ = 3.f; timeout_ = 3.f;
sendTimer = new PITimer(sendEvent, this); sendTimer = new PITimer(sendEvent, this);
@@ -259,11 +261,11 @@ void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PI
} }
if (history_write_send) { if (history_write_send) {
history_path_send = sb.getValue("historyFile", "./history_" + protName + "_send_" + history_path_send = sb.getValue("historyFile", "./history_" + protName + "_send_" +
date2string(currentDate(), "__dd_mm_yyyy_") + PIDate::current().toString("__dd_mm_yyyy_") +
time2string(currentTime(), "_hh_mm_ss_")).value(); PITime::current().toString("_hh_mm_ss_")).value();
history_id_send = sb.getValue("historyID", 0, &ok); history_id_send = sb.getValue("historyID", 0, &ok);
if (!ok) { if (!ok) {
history_id_send = protName.toByteArray().checksumCRC16() + 1; history_id_send = ushort(protName.toByteArray().checksumPlain32()) + 1;
piCoutObj << "Warning: no sender history ID defined, write with ID = " << history_id_send; piCoutObj << "Warning: no sender history ID defined, write with ID = " << history_id_send;
} }
history_file_send.open(history_path_send, PIIODevice::WriteOnly); history_file_send.open(history_path_send, PIIODevice::WriteOnly);
@@ -432,11 +434,11 @@ void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const
} }
if (history_write_rec) { if (history_write_rec) {
history_path_rec = rb.getValue("historyFile", "./history_" + protName + "_rec_" + history_path_rec = rb.getValue("historyFile", "./history_" + protName + "_rec_" +
date2string(currentDate(), "__dd_mm_yyyy_") + PIDate::current().toString("__dd_mm_yyyy_") +
time2string(currentTime(), "_hh_mm_ss_")).value(); PITime::current().toString("_hh_mm_ss_")).value();
history_id_rec = rb.getValue("historyID", 0, &ok); history_id_rec = rb.getValue("historyID", 0, &ok);
if (!ok) { if (!ok) {
history_id_rec = protName.toByteArray().checksumCRC16(); history_id_rec = ushort(protName.toByteArray().checksumPlain32());
piCoutObj << "Warning: no receiver history ID defined, write with ID = " << history_id_rec; piCoutObj << "Warning: no receiver history ID defined, write with ID = " << history_id_rec;
} }
history_file_rec.open(history_path_rec, PIIODevice::WriteOnly); history_file_rec.open(history_path_rec, PIIODevice::WriteOnly);

View File

@@ -100,8 +100,8 @@ public:
EVENT_HANDLER0(void, stopReceive); EVENT_HANDLER0(void, stopReceive);
void setExpectedFrequency(float frequency); // for connection quality diagnostic void setExpectedFrequency(float frequency); // for connection quality diagnostic
void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial
void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setPacketData(headerPtr, headerSize, dataSize);} void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize);}
void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setPacketData(headerPtr, headerSize, dataSize);} void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize);}
void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet
void setReceiverParameters(PIFlags<PISerial::Parameters> parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial void setReceiverParameters(PIFlags<PISerial::Parameters> parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;}

View File

@@ -344,7 +344,7 @@ PIByteArray PISerial::readData(int size, double timeout_ms) {
bool PISerial::openDevice() { bool PISerial::openDevice() {
piCout << "ser open" << path(); //piCout << "ser open" << path();
if (path().isEmpty()) return false; if (path().isEmpty()) return false;
#ifdef WINDOWS #ifdef WINDOWS
DWORD ds = 0, sm = 0; DWORD ds = 0, sm = 0;
@@ -519,6 +519,19 @@ bool PISerial::configureDevice(const void * e_main, const void * e_parent) {
} }
PIString PISerial::constructFullPath() const {
PIString ret(fullPathPrefix() + "://");
ret << path() << ":" << int(inSpeed()) << ":" << dataBitsCount();
if (parameters()[ParityControl]) {
if (parameters()[ParityOdd]) ret << ":O";
else ret << ":E";
} else ret << ":N";
if (parameters()[TwoStopBits]) ret << ":2";
else ret << ":1";
return ret;
}
void PISerial::configureFromFullPath(const PIString & full_path) { void PISerial::configureFromFullPath(const PIString & full_path) {
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {
@@ -553,9 +566,10 @@ PIStringList PISerial::availableDevices(bool test) {
HKEY key = 0; HKEY key = 0;
RegOpenKey(HKEY_LOCAL_MACHINE, (LPCTSTR)"HARDWARE\\DEVICEMAP\\SERIALCOMM", &key); RegOpenKey(HKEY_LOCAL_MACHINE, (LPCTSTR)"HARDWARE\\DEVICEMAP\\SERIALCOMM", &key);
if (key != 0) { if (key != 0) {
char name[256], data[1024]; char name[1024], data[1024];
DWORD name_len = 256, data_len = 1024, type = 0, index = 0; DWORD name_len = 1024, data_len = 1024, type = 0, index = 0;
while (RegEnumValue(key, index, (LPTSTR)name, &name_len, NULL, &type, (uchar * )data, &data_len) == ERROR_SUCCESS) { LONG ret;
while ((ret = RegEnumValue(key, index, (LPTSTR)name, &name_len, NULL, &type, (uchar * )data, &data_len)) != ERROR_NO_MORE_ITEMS) {
dl << PIString(data); dl << PIString(data);
index++; index++;
} }

View File

@@ -242,6 +242,8 @@ public:
//! \returns \b true if sended bytes count = size of string //! \returns \b true if sended bytes count = size of string
bool send(const PIByteArray & data, bool wait = false) {return (write(data.data(), data.size_s(), wait) == data.size_s());} bool send(const PIByteArray & data, bool wait = false) {return (write(data.data(), data.size_s(), wait) == data.size_s());}
PIString constructFullPath() const;
//! \brief Returns all available speeds for serial devices //! \brief Returns all available speeds for serial devices
static PIVector<int> availableSpeeds(); static PIVector<int> availableSpeeds();

View File

@@ -155,8 +155,8 @@ PIString & PIString::operator +=(const wstring & str) {
PIString & PIString::operator +=(const PIString & str) { PIString & PIString::operator +=(const PIString & str) {
uint l = str.size(); //uint l = str.size();
for (uint i = 0; i < l; ++i) push_back(str[i]); *((PIDeque<PIChar>*)this) << *((PIDeque<PIChar>*)&str);
return *this; return *this;
} }
@@ -208,23 +208,25 @@ bool PIString::operator >(const PIString & str) const {
PIString PIString::mid(const int start, const int len) const { PIString PIString::mid(const int start, const int len) const {
PIString str; //PIString str;
int s = start, l = len; int s = start, l = len;
if (l == 0) return str; if (l == 0) return PIString();
if (s < 0) { if (s < 0) {
l += s; l += s;
s = 0; s = 0;
} }
if (l < 0) { if (l < 0) {
for (uint i = s; i < size(); ++i) //for (uint i = s; i < size(); ++i)
str += at(i); // str += at(i);
return PIString(&(at(s)), size() - s);
} else { } else {
if (l > length() - s) if (l > length() - s)
l = length() - s; l = length() - s;
for (int i = s; i < s + l; ++i) //for (int i = s; i < s + l; ++i)
str += at(i); // str += at(i);
return PIString(&(at(s)), l);
} }
return str; return PIString();
} }
@@ -254,7 +256,9 @@ PIString & PIString::trim() {
for (int i = length() - 1; i >= 0; --i) for (int i = length() - 1; i >= 0; --i)
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12))
{fn = i; break;} {fn = i; break;}
*this = mid(st, fn - st + 1); //*this = mid(st, fn - st + 1);
if (fn < size_s() - 1) cutRight(size_s() - fn - 1);
if (st > 0) cutLeft(st);
return *this; return *this;
} }
@@ -281,6 +285,7 @@ PIString & PIString::replace(int from, int count, const PIString & with) {
PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) { PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) {
//piCout << "replace" << what << with;
if (what.isEmpty()) { if (what.isEmpty()) {
if (ok != 0) *ok = false; if (ok != 0) *ok = false;
return *this; return *this;
@@ -301,8 +306,9 @@ PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
PIString & PIString::insert(int index, const PIString & str) { PIString & PIString::insert(int index, const PIString & str) {
uint c = str.length(); //uint c = str.length();
for (uint i = 0; i < c; ++i) insert(index + i, str[i]); //for (uint i = 0; i < c; ++i) insert(index + i, str[i]);
PIDeque<PIChar>::insert(index, *((const PIDeque<PIChar>*)&str));
return *this; return *this;
} }
@@ -740,10 +746,10 @@ PIStringList& PIStringList::removeDuplicates() {
PIStringList l; PIStringList l;
PIString s; PIString s;
bool ae; bool ae;
for (uint i = 0; i < size(); ++i) { for (int i = 0; i < size_s(); ++i) {
ae = false; ae = false;
s = at(i); s = at(i);
for (uint j = 0; j < l.size(); ++j) { for (int j = 0; j < l.size_s(); ++j) {
if (s != l[j]) continue; if (s != l[j]) continue;
ae = true; break; ae = true; break;
} }

View File

@@ -31,11 +31,11 @@
class PIStringList; class PIStringList;
class PIP_EXPORT PIString: public PIVector<PIChar> class PIP_EXPORT PIString: public PIDeque<PIChar>
{ {
public: public:
//! Contructs an empty string //! Contructs an empty string
PIString(): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;} PIString(): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;}
//inline PIString & operator +=(const char c) {push_back(c); return *this;} //inline PIString & operator +=(const char c) {push_back(c); return *this;}
PIString & operator +=(const PIChar & c) {push_back(c); return *this;} PIString & operator +=(const PIChar & c) {push_back(c); return *this;}
@@ -49,56 +49,59 @@ public:
#endif #endif
//PIString(const char c) {*this += c;} //PIString(const char c) {*this += c;}
PIString(const PIString & o): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += o;} PIString(const PIString & o): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += o;}
//! Contructs string with single symbol "c" //! Contructs string with single symbol "c"
PIString(const PIChar & c): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += c;} PIString(const PIChar & c): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += c;}
PIString(const char c): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);} PIString(const char c): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);}
/*! \brief Contructs string from c-string "str" /*! \brief Contructs string from c-string "str"
* \details "str" should be null-terminated\n * \details "str" should be null-terminated\n
* Example: \snippet pistring.cpp PIString(char * ) */ * Example: \snippet pistring.cpp PIString(char * ) */
PIString(const char * str): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} PIString(const char * str): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;}
/*! \brief Contructs string from \c wchar_t c-string "str" /*! \brief Contructs string from \c wchar_t c-string "str"
* \details "str" should be null-terminated\n * \details "str" should be null-terminated\n
* Example: \snippet pistring.cpp PIString(wchar_t * ) */ * Example: \snippet pistring.cpp PIString(wchar_t * ) */
PIString(const wchar_t * str): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} PIString(const wchar_t * str): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;}
//! Contructs string from std::string "str" //! Contructs string from std::string "str"
PIString(const string & str): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} PIString(const string & str): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;}
#ifdef HAS_LOCALE #ifdef HAS_LOCALE
PIString(const wstring & str): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} PIString(const wstring & str): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;}
#endif #endif
//! Contructs string from byte array "ba" //! Contructs string from byte array "ba"
PIString(const PIByteArray & ba): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += ba;} PIString(const PIByteArray & ba): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += ba;}
//! \brief Contructs string from "len" characters of buffer "str"
PIString(const PIChar * str, const int len): PIDeque<PIChar>(str, size_t(len)) {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;}
/*! \brief Contructs string from "len" characters of buffer "str" /*! \brief Contructs string from "len" characters of buffer "str"
* \details Example: \snippet pistring.cpp PIString(char * , int) */ * \details Example: \snippet pistring.cpp PIString(char * , int) */
PIString(const char * str, const int len): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += string(str, len);} PIString(const char * str, const int len): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += string(str, len);}
/*! \brief Contructs string as sequence of characters "c" of buffer with length "len" /*! \brief Contructs string as sequence of characters "c" of buffer with length "len"
* \details Example: \snippet pistring.cpp PIString(int, char) */ * \details Example: \snippet pistring.cpp PIString(int, char) */
PIString(const int len, const char c): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} PIString(const int len, const char c): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
/*! \brief Contructs string as sequence of symbols "c" of buffer with length "len" /*! \brief Contructs string as sequence of symbols "c" of buffer with length "len"
* \details Example: \snippet pistring.cpp PIString(int, PIChar) */ * \details Example: \snippet pistring.cpp PIString(int, PIChar) */
PIString(const int len, const PIChar & c): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} PIString(const int len, const PIChar & c): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
PIString(const short & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const short & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ushort & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const ushort & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const int & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const int & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const uint & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const uint & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const long & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const long & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ulong & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const ulong & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const llong & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const llong & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ullong & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const ullong & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const float & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const float & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const double & value): PIVector<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} PIString(const double & value): PIDeque<PIChar>() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
//~PIString() {piMonitor.strings--; piMonitor.containers++;} //~PIString() {piMonitor.strings--; piMonitor.containers++;}
@@ -119,7 +122,7 @@ public:
//! Return symbol at index "pos" //! Return symbol at index "pos"
PIChar operator [](const int pos) const {return at(pos);} PIChar operator [](const int pos) const {return at(pos);}
//! Return const reference symbol at index "pos" //! Return reference to symbol at index "pos"
PIChar & operator [](const int pos) {return at(pos);} PIChar & operator [](const int pos) {return at(pos);}
//! Compare operator //! Compare operator
@@ -241,14 +244,20 @@ public:
/*! \brief Append string representation of "num" at the end of string /*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */ * \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string /*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */ * \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ushort & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string /*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */ * \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string /*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */ * \details Example: \snippet pistring.cpp PIString::<<(int) */
@@ -259,6 +268,13 @@ public:
PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;}
//! \brief Insert string "str" at the begin of string
PIString & prepend(const PIString & str) {insert(0, str); return *this;}
//! \brief Insert string "str" at the end of string
PIString & append(const PIString & str) {*this += str; return *this;}
/*! \brief Return part of string from symbol at index "start" and maximum length "len" /*! \brief Return part of string from symbol at index "start" and maximum length "len"
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid * \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid
* \sa \a left(), \a right() */ * \sa \a left(), \a right() */
@@ -330,9 +346,17 @@ public:
PIString & replaceAll(const PIString & what, const PIString & with); PIString & replaceAll(const PIString & what, const PIString & with);
PIString replaceAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;} PIString replaceAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;}
/*! \brief Repeat content of string "times" times and return this string
* \details Example: \snippet pistring.cpp PIString::repeat */
PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;}
/*! \brief Returns repeated "times" times string
* \details Example: \snippet pistring.cpp PIString::repeated */
PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);}
/*! \brief Insert symbol "c" after index "index" and return this string /*! \brief Insert symbol "c" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_0 */ * \details Example: \snippet pistring.cpp PIString::insert_0 */
PIString & insert(const int index, const PIChar & c) {PIVector<PIChar>::insert(index, c); return *this;} PIString & insert(const int index, const PIChar & c) {PIDeque<PIChar>::insert(index, c); return *this;}
/*! \brief Insert symbol "c" after index "index" and return this string /*! \brief Insert symbol "c" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_1 */ * \details Example: \snippet pistring.cpp PIString::insert_1 */
@@ -494,11 +518,11 @@ public:
//! \details Example: \snippet pistring.cpp PIString::findLast //! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const string str, const int start = 0) const {return findLast(PIString(str), start);} int findLast(const string str, const int start = 0) const {return findLast(PIString(str), start);}
//! \brief Search word "word" from symbol at index "start" and return last occur position. //! \brief Search word "word" from symbol at index "start" and return first occur position.
//! \details Example: \snippet pistring.cpp PIString::findWord //! \details Example: \snippet pistring.cpp PIString::findWord
int findWord(const PIString & word, const int start = 0) const; int findWord(const PIString & word, const int start = 0) const;
//! \brief Search C-style word "word" from symbol at index "start" and return last occur position. //! \brief Search C-style word "word" from symbol at index "start" and return first occur position.
//! \details Example: \snippet pistring.cpp PIString::findCWord //! \details Example: \snippet pistring.cpp PIString::findCWord
int findCWord(const PIString & word, const int start = 0) const; int findCWord(const PIString & word, const int start = 0) const;
@@ -801,7 +825,7 @@ inline char chrLwr(char c);
/*!\brief Strings array class /*!\brief Strings array class
* \details This class is based on \a PIVector<PIString> and * \details This class is based on \a PIVector<PIString> and
* expand it functionality. */ * expand it functionality. */
class PIP_EXPORT PIStringList: public PIVector<PIString> class PIP_EXPORT PIStringList: public PIDeque<PIString>
{ {
public: public:
@@ -820,7 +844,7 @@ public:
//! Contructs empty strings list with strings "s0", "s1", "s2" and "s3" //! Contructs empty strings list with strings "s0", "s1", "s2" and "s3"
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);} PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);}
PIStringList(const PIStringList & o): PIVector<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} PIStringList(const PIStringList & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
//! \brief Join all strings in one with delimiter "delim" and return it //! \brief Join all strings in one with delimiter "delim" and return it
@@ -831,14 +855,14 @@ public:
//! \details Example: \snippet pistring.cpp PIStringList::removeStrings //! \details Example: \snippet pistring.cpp PIStringList::removeStrings
PIStringList & removeStrings(const PIString & value) {for (uint i = 0; i < size(); ++i) {if (at(i) == value) {remove(i); --i;}} return *this;} PIStringList & removeStrings(const PIString & value) {for (uint i = 0; i < size(); ++i) {if (at(i) == value) {remove(i); --i;}} return *this;}
PIStringList & remove(uint num) {PIVector<PIString>::remove(num); return *this;} PIStringList & remove(uint num) {PIDeque<PIString>::remove(num); return *this;}
PIStringList & remove(uint num, uint count) {PIVector<PIString>::remove(num, count); return *this;} PIStringList & remove(uint num, uint count) {PIDeque<PIString>::remove(num, count); return *this;}
//! \brief Remove duplicated strings and return this //! \brief Remove duplicated strings and return this
//! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates //! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates
PIStringList & removeDuplicates(); PIStringList & removeDuplicates();
//! \brief //! \brief Trim all strings
//! \details Example: \snippet pistring.cpp PIStringList::trim //! \details Example: \snippet pistring.cpp PIStringList::trim
PIStringList & trim() {for (uint i = 0; i < size(); ++i) at(i).trim(); return *this;} PIStringList & trim() {for (uint i = 0; i < size(); ++i) at(i).trim(); return *this;}

View File

@@ -114,7 +114,7 @@ bool operator >(const PIDateTime & t0, const PIDateTime & t1) {
} }
PITime currentTime() { PITime PITime::current() {
time_t rt = time(0); time_t rt = time(0);
tm * pt = localtime(&rt); tm * pt = localtime(&rt);
PITime t; PITime t;
@@ -125,7 +125,7 @@ PITime currentTime() {
} }
PIDate currentDate() { PIDate PIDate::current() {
time_t rt = time(0); time_t rt = time(0);
tm * pt = localtime(&rt); tm * pt = localtime(&rt);
PIDate d; PIDate d;
@@ -136,7 +136,7 @@ PIDate currentDate() {
} }
PIDateTime currentDateTime() { PIDateTime PIDateTime::current() {
time_t rt = time(0); time_t rt = time(0);
tm * pt = localtime(&rt); tm * pt = localtime(&rt);
PIDateTime dt; PIDateTime dt;
@@ -151,7 +151,7 @@ PIDateTime currentDateTime() {
} }
PISystemTime currentSystemTime() { PISystemTime PISystemTime::current() {
#ifdef WINDOWS #ifdef WINDOWS
FILETIME ft, sft; FILETIME ft, sft;
GetSystemTimeAsFileTime(&ft); GetSystemTimeAsFileTime(&ft);

View File

@@ -141,6 +141,9 @@ public:
//! Contructs system time from nanoseconds "v" //! Contructs system time from nanoseconds "v"
static PISystemTime fromNanoseconds(double v) {long s = piFloord(v / 1000000000.); return PISystemTime(s, (v / 1000000000. - s) * 1000000000);} static PISystemTime fromNanoseconds(double v) {long s = piFloord(v / 1000000000.); return PISystemTime(s, (v / 1000000000. - s) * 1000000000);}
//! Returns current system time
static PISystemTime current();
//! Seconds of stored system time //! Seconds of stored system time
long seconds; long seconds;
@@ -169,6 +172,7 @@ struct PIP_EXPORT PITime {
int minutes; int minutes;
int hours; int hours;
PIString toString(const PIString & format = "h:mm:ss") const; PIString toString(const PIString & format = "h:mm:ss") const;
static PITime current();
}; };
PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1); PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1);
PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1); PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1);
@@ -183,6 +187,7 @@ struct PIP_EXPORT PIDate {
int month; int month;
int year; int year;
PIString toString(const PIString & format = "d.MM.yyyy") const; PIString toString(const PIString & format = "d.MM.yyyy") const;
static PIDate current();
}; };
PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1); PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1);
PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1); PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1);
@@ -212,6 +217,7 @@ struct PIP_EXPORT PIDateTime {
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();} void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
static PIDateTime fromSecondSinceEpoch(const time_t sec); static PIDateTime fromSecondSinceEpoch(const time_t sec);
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;} static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
static PIDateTime current();
}; };
inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();} inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();}
inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();} inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();}
@@ -222,14 +228,14 @@ inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);} inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);} inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
PIP_EXPORT PITime currentTime(); DEPRECATED inline PITime currentTime() {return PITime::current();} // obsolete, use PITime::current() instead
PIP_EXPORT PIDate currentDate(); DEPRECATED inline PIDate currentDate() {return PIDate::current();} // obsolete, use PIDate::current() instead
PIP_EXPORT PIDateTime currentDateTime(); DEPRECATED inline PIDateTime currentDateTime() {return PIDateTime::current();} // obsolete, use PIDateTime::current() instead
//! \relatesalso PISystemTime \brief Returns current system time //! \relatesalso PISystemTime \brief Returns current system time
PIP_EXPORT PISystemTime currentSystemTime(); DEPRECATED inline PISystemTime currentSystemTime() {return PISystemTime::current();} // obsolete, use PISystemTime::current() instead
PIP_EXPORT PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead DEPRECATED PIP_EXPORT PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead
PIP_EXPORT PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead DEPRECATED PIP_EXPORT PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead
PIP_EXPORT PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead DEPRECATED PIP_EXPORT PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead
#endif // PITIME_H #endif // PITIME_H

View File

@@ -309,7 +309,7 @@ void PITimer::start(double msecs) {
if (msecs < 0 || running_) return; if (msecs < 0 || running_) return;
interval_ = msecs; interval_ = msecs;
inc_time = PISystemTime::fromMilliseconds(msecs); inc_time = PISystemTime::fromMilliseconds(msecs);
st_time = currentSystemTime() + inc_time; st_time = PISystemTime::current() + inc_time;
deferred_ = false; deferred_ = false;
running_ = true; running_ = true;
PIThread::start(); PIThread::start();
@@ -320,9 +320,9 @@ void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
//piCoutObj << "defStart exec with" << delay_msecs << interval_msecs; //piCoutObj << "defStart exec with" << delay_msecs << interval_msecs;
if (interval_msecs < 0 || running_) return; if (interval_msecs < 0 || running_) return;
interval_ = interval_msecs; interval_ = interval_msecs;
PISystemTime cst = currentSystemTime(); PISystemTime cst = PISystemTime::current();
inc_time = PISystemTime::fromMilliseconds(interval_msecs); inc_time = PISystemTime::fromMilliseconds(interval_msecs);
st_time = currentSystemTime() + PISystemTime::fromMilliseconds(delay_msecs); st_time = PISystemTime::current() + PISystemTime::fromMilliseconds(delay_msecs);
if (st_time < cst) st_time = cst; if (st_time < cst) st_time = cst;
running_ = deferred_ = true; running_ = deferred_ = true;
PIThread::start(); PIThread::start();
@@ -334,7 +334,7 @@ void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_date
//piCoutObj << "defStart exec to" << start_datetime.toString() << interval_msecs; //piCoutObj << "defStart exec to" << start_datetime.toString() << interval_msecs;
if (interval_msecs < 0 || running_) return; if (interval_msecs < 0 || running_) return;
interval_ = interval_msecs; interval_ = interval_msecs;
PISystemTime cst = currentSystemTime(); PISystemTime cst = PISystemTime::current();
inc_time = PISystemTime::fromMilliseconds(interval_msecs); inc_time = PISystemTime::fromMilliseconds(interval_msecs);
st_time = start_datetime.toSystemTime(); st_time = start_datetime.toSystemTime();
if (st_time < cst) st_time = cst; if (st_time < cst) st_time = cst;
@@ -347,7 +347,7 @@ void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_date
void PITimer::run() { void PITimer::run() {
if (!running_) return; if (!running_) return;
while (deferred_) { while (deferred_) {
PISystemTime tst = st_time - currentSystemTime(); PISystemTime tst = st_time - PISystemTime::current();
if (tst.seconds > 0) { if (tst.seconds > 0) {
piMSleep(100); piMSleep(100);
if (!running_) return; if (!running_) return;
@@ -365,7 +365,7 @@ void PITimer::run() {
#ifdef WINDOWS #ifdef WINDOWS
tt_st = __PIQueryPerformanceCounter(); tt_st = __PIQueryPerformanceCounter();
#else #else
(st_time - currentSystemTime()).sleep(); (st_time - PISystemTime::current()).sleep();
st_time += inc_time; st_time += inc_time;
#endif #endif
//if (lockRun) lock(); //if (lockRun) lock();

View File

@@ -388,6 +388,13 @@ PICout operator<<(PICout s, const PIUSB::Endpoint & v) {
} }
PIString PIUSB::constructFullPath() const {
PIString ret(fullPathPrefix() + "://");
ret << PIString::fromNumber(vendorID(), 16).toLowerCase() << ":" << PIString::fromNumber(productID(), 16).toLowerCase() << ":" << deviceNumber() << ":" << endpointRead().address << ":" << endpointWrite().address;
return ret;
}
void PIUSB::configureFromFullPath(const PIString & full_path) { void PIUSB::configureFromFullPath(const PIString & full_path) {
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {

View File

@@ -100,8 +100,8 @@ public:
int deviceNumber() const {return property("deviceNumber").toInt();} int deviceNumber() const {return property("deviceNumber").toInt();}
int timeoutRead() const {return property("timeoutRead").toInt();} int timeoutRead() const {return property("timeoutRead").toInt();}
int timeoutWrite() const {return property("timeoutWrite").toInt();} int timeoutWrite() const {return property("timeoutWrite").toInt();}
const PIUSB::Endpoint & endpointRead() {return ep_read;} const PIUSB::Endpoint & endpointRead() const {return ep_read;}
const PIUSB::Endpoint & endpointWrite() {return ep_write;} const PIUSB::Endpoint & endpointWrite() const {return ep_write;}
const PIVector<PIUSB::Endpoint> & endpoints() const {return eps;} const PIVector<PIUSB::Endpoint> & endpoints() const {return eps;}
PIVector<PIUSB::Endpoint> endpointsRead(); PIVector<PIUSB::Endpoint> endpointsRead();
@@ -126,6 +126,8 @@ public:
void flush(); void flush();
PIString constructFullPath() const;
protected: protected:
PIString fullPathPrefix() const {return "usb";} PIString fullPathPrefix() const {return "usb";}
void configureFromFullPath(const PIString & full_path); void configureFromFullPath(const PIString & full_path);

View File

@@ -20,13 +20,42 @@
#include "pivariant.h" #include "pivariant.h"
/** \class PIVariant
* \brief Variant type
* \details
* \section PIVariant_sec0 Synopsis
* This class provides general type that can contains all standard types, some
* PIP types or custom type. In case of standard types this class also provides
* convertions between them.
*
* \section PIVariant_sec1 Usage
* %PIVariant useful if you want pass many variables with different types in
* single array, e.g.:
* \code{cpp}
* PIVector<PIVariant> array;
* array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF");
* piCout << array;
* piForeachC (PIVariant & i, array)
* piCout << i.toInt();
* \endcode
* Result:
* \code{cpp}
* {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)}
* 10
* 1
* 1
* 255
* \endcode
* */
PIVariant::PIVariant() { PIVariant::PIVariant() {
type_ = PIVariant::Invalid; type_ = PIVariant::Invalid;
memset(_vraw, 0, __PIVARIANT_UNION_SIZE__); memset(_vraw, 0, __PIVARIANT_UNION_SIZE__);
} }
void PIVariant::operator =(const PIVariant & v) { PIVariant & PIVariant::operator =(const PIVariant & v) {
type_ = v.type_; type_ = v.type_;
memcpy(_vraw, v._vraw, __PIVARIANT_UNION_SIZE__); memcpy(_vraw, v._vraw, __PIVARIANT_UNION_SIZE__);
_vbytearray = v._vbytearray; _vbytearray = v._vbytearray;
@@ -34,6 +63,7 @@ void PIVariant::operator =(const PIVariant & v) {
_vstring = v._vstring; _vstring = v._vstring;
_vstringlist = v._vstringlist; _vstringlist = v._vstringlist;
_vcustom = v._vcustom; _vcustom = v._vcustom;
return *this;
} }
@@ -134,6 +164,12 @@ PIString PIVariant::typeName(PIVariant::Type type) {
} }
/** \brief Returns variant content as boolean
* \details In case of numeric types returns \b true if value != 0. \n
* In case of String type returns \a PIString::toBool(). \n
* In case of StringList type returns \b false if string list is empty,
* otherwise returns \a PIString::toBool() of first string. \n
* In case of other types returns \b false. */
bool PIVariant::toBool() const { bool PIVariant::toBool() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -160,6 +196,13 @@ bool PIVariant::toBool() const {
} }
/** \brief Returns variant content as int
* \details In case of numeric types returns integer value. \n
* In case of String type returns \a PIString::toInt(). \n
* In case of StringList type returns \b 0 if string list is empty,
* otherwise returns \a PIString::toInt() of first string. \n
* In case of other types returns \b 0. */
int PIVariant::toInt() const { int PIVariant::toInt() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -179,13 +222,19 @@ int PIVariant::toInt() const {
case PIVariant::Complexd: return _vcomplexd.real(); case PIVariant::Complexd: return _vcomplexd.real();
case PIVariant::Complexld: return _vcomplexld.real(); case PIVariant::Complexld: return _vcomplexld.real();
case PIVariant::String: return _vstring.toInt(); case PIVariant::String: return _vstring.toInt();
case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toInt(); case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0; return _vstringlist.front().toInt();
default: break; default: break;
} }
return 0; return 0;
} }
/** \brief Returns variant content as long long
* \details In case of numeric types returns integer value. \n
* In case of String type returns \a PIString::toLLong(). \n
* In case of StringList type returns \b 0L if string list is empty,
* otherwise returns \a PIString::toLLong() of first string. \n
* In case of other types returns \b 0L. */
llong PIVariant::toLLong() const { llong PIVariant::toLLong() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -205,13 +254,19 @@ llong PIVariant::toLLong() const {
case PIVariant::Complexd: return _vcomplexd.real(); case PIVariant::Complexd: return _vcomplexd.real();
case PIVariant::Complexld: return _vcomplexld.real(); case PIVariant::Complexld: return _vcomplexld.real();
case PIVariant::String: return _vstring.toLLong(); case PIVariant::String: return _vstring.toLLong();
case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toLLong(); case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0L; return _vstringlist.front().toLLong();
default: break; default: break;
} }
return 0L; return 0L;
} }
/** \brief Returns variant content as float
* \details In case of numeric types returns float value. \n
* In case of String type returns \a PIString::toFloat(). \n
* In case of StringList type returns \b 0.f if string list is empty,
* otherwise returns \a PIString::toFloat() of first string. \n
* In case of other types returns \b 0.f. */
float PIVariant::toFloat() const { float PIVariant::toFloat() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -231,13 +286,19 @@ float PIVariant::toFloat() const {
case PIVariant::Complexd: return _vcomplexd.real(); case PIVariant::Complexd: return _vcomplexd.real();
case PIVariant::Complexld: return _vcomplexld.real(); case PIVariant::Complexld: return _vcomplexld.real();
case PIVariant::String: return _vstring.toFloat(); case PIVariant::String: return _vstring.toFloat();
case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toFloat(); case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.f; return _vstringlist.front().toFloat();
default: break; default: break;
} }
return 0.f; return 0.f;
} }
/** \brief Returns variant content as double
* \details In case of numeric types returns double value. \n
* In case of String type returns \a PIString::toDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toDouble() of first string. \n
* In case of other types returns \b 0.. */
double PIVariant::toDouble() const { double PIVariant::toDouble() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -257,13 +318,19 @@ double PIVariant::toDouble() const {
case PIVariant::Complexd: return _vcomplexd.real(); case PIVariant::Complexd: return _vcomplexd.real();
case PIVariant::Complexld: return _vcomplexld.real(); case PIVariant::Complexld: return _vcomplexld.real();
case PIVariant::String: return _vstring.toDouble(); case PIVariant::String: return _vstring.toDouble();
case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toDouble(); case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.; return _vstringlist.front().toDouble();
default: break; default: break;
} }
return 0.; return 0.;
} }
/** \brief Returns variant content as long double
* \details In case of numeric types returns long double value. \n
* In case of String type returns \a PIString::toLDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toLDouble() of first string. \n
* In case of other types returns \b 0.. */
ldouble PIVariant::toLDouble() const { ldouble PIVariant::toLDouble() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -283,13 +350,19 @@ ldouble PIVariant::toLDouble() const {
case PIVariant::Complexd: return _vcomplexd.real(); case PIVariant::Complexd: return _vcomplexd.real();
case PIVariant::Complexld: return _vcomplexld.real(); case PIVariant::Complexld: return _vcomplexld.real();
case PIVariant::String: return _vstring.toLDouble(); case PIVariant::String: return _vstring.toLDouble();
case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toLDouble(); case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.; return _vstringlist.front().toLDouble();
default: break; default: break;
} }
return 0.; return 0.;
} }
/** \brief Returns variant content as complex
* \details In case of numeric types returns complex value. \n
* In case of String type returns \a PIString::toDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toDouble() of first string. \n
* In case of other types returns \b 0.. */
complexd PIVariant::toComplexd() const { complexd PIVariant::toComplexd() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -309,13 +382,19 @@ complexd PIVariant::toComplexd() const {
case PIVariant::Complexd: return _vcomplexd.real(); case PIVariant::Complexd: return _vcomplexd.real();
case PIVariant::Complexld: return _vcomplexld.real(); case PIVariant::Complexld: return _vcomplexld.real();
case PIVariant::String: return _vstring.toDouble(); case PIVariant::String: return _vstring.toDouble();
case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toDouble(); case PIVariant::StringList: if (_vstringlist.isEmpty()) return complexd_0; return _vstringlist.front().toDouble();
default: break; default: break;
} }
return complexd_0; return complexd_0;
} }
/** \brief Returns variant content as long complex
* \details In case of numeric types returns long complex value. \n
* In case of String type returns \a PIString::toLDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toLDouble() of first string. \n
* In case of other types returns \b 0.. */
complexld PIVariant::toComplexld() const { complexld PIVariant::toComplexld() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: case PIVariant::Bool:
@@ -335,13 +414,17 @@ complexld PIVariant::toComplexld() const {
case PIVariant::Complexd: return _vcomplexd.real(); case PIVariant::Complexd: return _vcomplexd.real();
case PIVariant::Complexld: return _vcomplexld.real(); case PIVariant::Complexld: return _vcomplexld.real();
case PIVariant::String: return _vstring.toLDouble(); case PIVariant::String: return _vstring.toLDouble();
case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toLDouble(); case PIVariant::StringList: if (_vstringlist.isEmpty()) return complexld_0; return _vstringlist.front().toLDouble();
default: break; default: break;
} }
return complexld_0; return complexld_0;
} }
/** \brief Returns variant content as time
* \details In case of Time type returns time value. \n
* In case of DateTime type returns time part of value. \n
* In case of other types returns \a PITime(). */
PITime PIVariant::toTime() const { PITime PIVariant::toTime() const {
if (type_ == PIVariant::Time) return _vtime; if (type_ == PIVariant::Time) return _vtime;
if (type_ == PIVariant::DateTime) return _vtime; if (type_ == PIVariant::DateTime) return _vtime;
@@ -349,6 +432,10 @@ PITime PIVariant::toTime() const {
} }
/** \brief Returns variant content as date
* \details In case of Date type returns date value. \n
* In case of DateTime type returns date part of value. \n
* In case of other types returns \a PIDate(). */
PIDate PIVariant::toDate() const { PIDate PIVariant::toDate() const {
if (type_ == PIVariant::Date) return _vdate; if (type_ == PIVariant::Date) return _vdate;
if (type_ == PIVariant::DateTime) return *((PIDate*)(&(_vdatetime.day))); if (type_ == PIVariant::DateTime) return *((PIDate*)(&(_vdatetime.day)));
@@ -356,6 +443,11 @@ PIDate PIVariant::toDate() const {
} }
/** \brief Returns variant content as date and time
* \details In case of Time type returns time value with null date. \n
* In case of Date type returns date value with null time. \n
* In case of DateTime type returns date and time. \n
* In case of other types returns \a PIDateTime(). */
PIDateTime PIVariant::toDateTime() const { PIDateTime PIVariant::toDateTime() const {
if (type_ == PIVariant::DateTime) return _vdatetime; if (type_ == PIVariant::DateTime) return _vdatetime;
if (type_ == PIVariant::Time) return PIDateTime(_vtime); if (type_ == PIVariant::Time) return PIDateTime(_vtime);
@@ -364,12 +456,25 @@ PIDateTime PIVariant::toDateTime() const {
} }
/** \brief Returns variant content as system time
* \details In case of SystemTime type returns system time. \n
* In case of other types returns \a PISystemTime::fromSeconds() from
* double value of variant content. */
PISystemTime PIVariant::toSystemTime() const { PISystemTime PIVariant::toSystemTime() const {
if (type_ == PIVariant::SystemTime) return _vsystime; if (type_ == PIVariant::SystemTime) return _vsystime;
return PISystemTime::fromSeconds(toDouble()); return PISystemTime::fromSeconds(toDouble());
} }
/** \brief Returns variant content as string
* \details In case of numeric types returns \a PIString::fromNumber(). \n
* In case of String type returns string value. \n
* In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n
* In case of BitArray or ByteArray types returns number of bits/bytes. \n
* In case of Time, Date or DateTime types returns toString() of this values. \n
* In case of SystemTime types returns second and nanoseconds of time
* ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n
* In case of other types returns \b "". */
PIString PIVariant::toString() const { PIString PIVariant::toString() const {
switch (type_) { switch (type_) {
case PIVariant::Bool: return _vint == 0 ? "false" : "true"; case PIVariant::Bool: return _vint == 0 ? "false" : "true";
@@ -389,7 +494,7 @@ PIString PIVariant::toString() const {
case PIVariant::Complexd: return "(" + PIString::fromNumber(_vcomplexd.real()) + "; " + PIString::fromNumber(_vcomplexd.imag()) + ")"; case PIVariant::Complexd: return "(" + PIString::fromNumber(_vcomplexd.real()) + "; " + PIString::fromNumber(_vcomplexd.imag()) + ")";
case PIVariant::Complexld: return "(" + PIString::fromNumber(_vcomplexld.real()) + "; " + PIString::fromNumber(_vcomplexld.imag()) + ")"; case PIVariant::Complexld: return "(" + PIString::fromNumber(_vcomplexld.real()) + "; " + PIString::fromNumber(_vcomplexld.imag()) + ")";
case PIVariant::BitArray: return PIString::fromNumber(_vbitarray.bitSize()) + " bits"; case PIVariant::BitArray: return PIString::fromNumber(_vbitarray.bitSize()) + " bits";
case PIVariant::ByteArray: return PIString::fromNumber(_vbytearray.size()) + " bytes"; case PIVariant::ByteArray: return _vbytearray.toString();
case PIVariant::String: return _vstring; case PIVariant::String: return _vstring;
case PIVariant::StringList: return "(" + _vstringlist.join("; ") + ")"; case PIVariant::StringList: return "(" + _vstringlist.join("; ") + ")";
case PIVariant::Time: return _vtime.toString(); case PIVariant::Time: return _vtime.toString();
@@ -402,18 +507,27 @@ PIString PIVariant::toString() const {
} }
/** \brief Returns variant content as strings list
* \details In case of StringList type returns strings list value. \n
* In case of other types returns \a PIStringList with one string value of variant content. */
PIStringList PIVariant::toStringList() const { PIStringList PIVariant::toStringList() const {
if (type_ == PIVariant::StringList) return _vstringlist; if (type_ == PIVariant::StringList) return _vstringlist;
return PIStringList(toString()); return PIStringList(toString());
} }
/** \brief Returns variant content as bit array
* \details In case of BitArray type returns bit array value. \n
* In case of other types returns \a PIBitArray from \a toLLong() value. */
PIBitArray PIVariant::toBitArray() const { PIBitArray PIVariant::toBitArray() const {
if (type_ == PIVariant::BitArray) return _vbitarray; if (type_ == PIVariant::BitArray) return _vbitarray;
return PIBitArray(ullong(toLLong())); return PIBitArray(ullong(toLLong()));
} }
/** \brief Returns variant content as byte array
* \details In case of ByteArray type returns byte array value. \n
* In case of other types returns empty \a PIByteArray. */
PIByteArray PIVariant::toByteArray() const { PIByteArray PIVariant::toByteArray() const {
if (type_ == PIVariant::ByteArray) return _vbytearray; if (type_ == PIVariant::ByteArray) return _vbytearray;
return PIByteArray(); return PIByteArray();

View File

@@ -49,88 +49,192 @@
class PIP_EXPORT PIVariant { class PIP_EXPORT PIVariant {
friend PICout operator <<(PICout s, const PIVariant & v); friend PICout operator <<(PICout s, const PIVariant & v);
public: public:
//! Type of %PIVariant content
enum Type { enum Type {
Invalid = 0, Invalid /** Invalid type , default type of empty contructor */ = 0 ,
Bool, Bool /** bool */ ,
Char, Char /** char */ ,
UChar, UChar /** uchar */ ,
Short, Short /** short */ ,
UShort, UShort /** ushort */ ,
Int, Int /** int */ ,
UInt, UInt /** uint */ ,
Long, Long /** long */ ,
ULong, ULong /** ulong */ ,
LLong, LLong /** llong */ ,
ULLong, ULLong /** ullong */ ,
Float, Float /** float */ ,
Double, Double /** double */ ,
LDouble, LDouble /** ldouble */ ,
Complexd, Complexd /** complexd */ ,
Complexld, Complexld /** complexld */ ,
BitArray, BitArray /** PIBitArray */ ,
ByteArray, ByteArray /** PIByteArray */ ,
String, String /** PIString */ ,
StringList, StringList /** PIStringList */ ,
Time, Time /** PITime */ ,
Date, Date /** PIDate */ ,
DateTime, DateTime /** PIDateTime */ ,
SystemTime, SystemTime /** PISystemTime */ ,
Custom = 0xFF Custom /** Custom */ = 0xFF
}; };
//! Empty constructor, \a type() will be set to \a Invalid
PIVariant(); PIVariant();
//! Constructs variant from string
PIVariant(const char * v) {setValue(PIString(v));} PIVariant(const char * v) {setValue(PIString(v));}
//! Constructs variant from boolean
PIVariant(const bool v) {setValue(v);} PIVariant(const bool v) {setValue(v);}
//! Constructs variant from char
PIVariant(const char v) {setValue(v);} PIVariant(const char v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const uchar v) {setValue(v);} PIVariant(const uchar v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const short v) {setValue(v);} PIVariant(const short v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const ushort v) {setValue(v);} PIVariant(const ushort v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const int & v) {setValue(v);} PIVariant(const int & v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const uint & v) {setValue(v);} PIVariant(const uint & v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const long & v) {setValue(v);} PIVariant(const long & v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const ulong & v) {setValue(v);} PIVariant(const ulong & v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const llong & v) {setValue(v);} PIVariant(const llong & v) {setValue(v);}
//! Constructs variant from integer
PIVariant(const ullong & v) {setValue(v);} PIVariant(const ullong & v) {setValue(v);}
//! Constructs variant from float
PIVariant(const float & v) {setValue(v);} PIVariant(const float & v) {setValue(v);}
//! Constructs variant from double
PIVariant(const double & v) {setValue(v);} PIVariant(const double & v) {setValue(v);}
//! Constructs variant from long double
PIVariant(const ldouble & v) {setValue(v);} PIVariant(const ldouble & v) {setValue(v);}
//! Constructs variant from complex
PIVariant(const complexd & v) {setValue(v);} PIVariant(const complexd & v) {setValue(v);}
//! Constructs variant from complex
PIVariant(const complexld & v) {setValue(v);} PIVariant(const complexld & v) {setValue(v);}
//! Constructs variant from bit array
PIVariant(const PIBitArray & v) {setValue(v);} PIVariant(const PIBitArray & v) {setValue(v);}
//! Constructs variant from byte array
PIVariant(const PIByteArray & v) {setValue(v);} PIVariant(const PIByteArray & v) {setValue(v);}
//! Constructs variant from string
PIVariant(const PIString & v) {setValue(v);} PIVariant(const PIString & v) {setValue(v);}
//! Constructs variant from strings list
PIVariant(const PIStringList & v) {setValue(v);} PIVariant(const PIStringList & v) {setValue(v);}
//! Constructs variant from time
PIVariant(const PITime & v) {setValue(v);} PIVariant(const PITime & v) {setValue(v);}
//! Constructs variant from date
PIVariant(const PIDate & v) {setValue(v);} PIVariant(const PIDate & v) {setValue(v);}
//! Constructs variant from date and time
PIVariant(const PIDateTime & v) {setValue(v);} PIVariant(const PIDateTime & v) {setValue(v);}
//! Constructs variant from system time
PIVariant(const PISystemTime & v) {setValue(v);} PIVariant(const PISystemTime & v) {setValue(v);}
//! Set variant content and type to string
void setValue(const char * v) {setValue(PIString(v));} void setValue(const char * v) {setValue(PIString(v));}
//! Set variant content and type to boolean
void setValue(const bool v) {type_ = PIVariant::Bool; _vint = (v ? 1 : 0);} void setValue(const bool v) {type_ = PIVariant::Bool; _vint = (v ? 1 : 0);}
//! Set variant content and type to char
void setValue(const char v) {type_ = PIVariant::Char; _vint = v;} void setValue(const char v) {type_ = PIVariant::Char; _vint = v;}
//! Set variant content and type to integer
void setValue(const uchar v) {type_ = PIVariant::UChar; _vint = v;} void setValue(const uchar v) {type_ = PIVariant::UChar; _vint = v;}
//! Set variant content and type to integer
void setValue(const short v) {type_ = PIVariant::Short; _vint = v;} void setValue(const short v) {type_ = PIVariant::Short; _vint = v;}
//! Set variant content and type to integer
void setValue(const ushort v) {type_ = PIVariant::UShort; _vint = v;} void setValue(const ushort v) {type_ = PIVariant::UShort; _vint = v;}
//! Set variant content and type to integer
void setValue(const int & v) {type_ = PIVariant::Int; _vint = v;} void setValue(const int & v) {type_ = PIVariant::Int; _vint = v;}
//! Set variant content and type to integer
void setValue(const uint & v) {type_ = PIVariant::UInt; _vint = v;} void setValue(const uint & v) {type_ = PIVariant::UInt; _vint = v;}
//! Set variant content and type to integer
void setValue(const long & v) {type_ = PIVariant::Long; _vint = v;} void setValue(const long & v) {type_ = PIVariant::Long; _vint = v;}
//! Set variant content and type to integer
void setValue(const ulong & v) {type_ = PIVariant::ULong; _vint = v;} void setValue(const ulong & v) {type_ = PIVariant::ULong; _vint = v;}
//! Set variant content and type to integer
void setValue(const llong & v) {type_ = PIVariant::LLong; _vllong = v;} void setValue(const llong & v) {type_ = PIVariant::LLong; _vllong = v;}
//! Set variant content and type to integer
void setValue(const ullong & v) {type_ = PIVariant::ULLong; _vllong = v;} void setValue(const ullong & v) {type_ = PIVariant::ULLong; _vllong = v;}
//! Set variant content and type to float
void setValue(const float & v) {type_ = PIVariant::Float; _vfloat = v;} void setValue(const float & v) {type_ = PIVariant::Float; _vfloat = v;}
//! Set variant content and type to double
void setValue(const double & v) {type_ = PIVariant::Double; _vdouble = v;} void setValue(const double & v) {type_ = PIVariant::Double; _vdouble = v;}
//! Set variant content and type to long double
void setValue(const ldouble & v) {type_ = PIVariant::LDouble; _vldouble = v;} void setValue(const ldouble & v) {type_ = PIVariant::LDouble; _vldouble = v;}
//! Set variant content and type to complex
void setValue(const complexd & v) {type_ = PIVariant::Complexd; _vcomplexd = v;} void setValue(const complexd & v) {type_ = PIVariant::Complexd; _vcomplexd = v;}
//! Set variant content and type to complex
void setValue(const complexld & v) {type_ = PIVariant::Complexld; _vcomplexld = v;} void setValue(const complexld & v) {type_ = PIVariant::Complexld; _vcomplexld = v;}
//! Set variant content and type to bit array
void setValue(const PIBitArray & v) {type_ = PIVariant::BitArray; _vbitarray = v;} void setValue(const PIBitArray & v) {type_ = PIVariant::BitArray; _vbitarray = v;}
//! Set variant content and type to byte array
void setValue(const PIByteArray & v) {type_ = PIVariant::ByteArray; _vbytearray = v;} void setValue(const PIByteArray & v) {type_ = PIVariant::ByteArray; _vbytearray = v;}
//! Set variant content and type to string
void setValue(const PIString & v) {type_ = PIVariant::String; _vstring = v;} void setValue(const PIString & v) {type_ = PIVariant::String; _vstring = v;}
//! Set variant content and type to strings list
void setValue(const PIStringList & v) {type_ = PIVariant::StringList; _vstringlist = v;} void setValue(const PIStringList & v) {type_ = PIVariant::StringList; _vstringlist = v;}
//! Set variant content and type to time
void setValue(const PITime & v) {type_ = PIVariant::Time; _vtime = v;} void setValue(const PITime & v) {type_ = PIVariant::Time; _vtime = v;}
//! Set variant content and type to date
void setValue(const PIDate & v) {type_ = PIVariant::Date; _vdate = v;} void setValue(const PIDate & v) {type_ = PIVariant::Date; _vdate = v;}
//! Set variant content and type to date and time
void setValue(const PIDateTime & v) {type_ = PIVariant::DateTime; _vdatetime = v;} void setValue(const PIDateTime & v) {type_ = PIVariant::DateTime; _vdatetime = v;}
//! Set variant content and type to system time
void setValue(const PISystemTime & v) {type_ = PIVariant::SystemTime; _vsystime = v;} void setValue(const PISystemTime & v) {type_ = PIVariant::SystemTime; _vsystime = v;}
bool toBool() const; bool toBool() const;
int toInt() const; int toInt() const;
llong toLLong() const; llong toLLong() const;
@@ -148,6 +252,10 @@ public:
PIBitArray toBitArray() const; PIBitArray toBitArray() const;
PIByteArray toByteArray() const; PIByteArray toByteArray() const;
/** \brief Returns variant content as custom type
* \details In case of known types this function equivalent \a to<Type> function. \n
* Otherwise returns content as type T. */
template<typename T> template<typename T>
T toValue() const {if (_vcustom.size() != sizeof(T)) return T(); return *((T*)_vcustom.data());} T toValue() const {if (_vcustom.size() != sizeof(T)) return T(); return *((T*)_vcustom.data());}
/* /*
@@ -177,46 +285,89 @@ public:
operator const char*() const {return toString().data();} operator const char*() const {return toString().data();}
operator void*() const {return (void*)(toLLong());} operator void*() const {return (void*)(toLLong());}
*/ */
void operator =(const PIVariant & v);
void operator =(const char * v) {setValue(PIString(v));}
void operator =(const bool v) {setValue(v);}
void operator =(const char v) {setValue(v);}
void operator =(const uchar v) {setValue(v);}
void operator =(const short v) {setValue(v);}
void operator =(const ushort v) {setValue(v);}
void operator =(const int & v) {setValue(v);}
void operator =(const uint & v) {setValue(v);}
void operator =(const long & v) {setValue(v);}
void operator =(const ulong & v) {setValue(v);}
void operator =(const llong & v) {setValue(v);}
void operator =(const ullong & v) {setValue(v);}
void operator =(const float & v) {setValue(v);}
void operator =(const double & v) {setValue(v);}
void operator =(const ldouble & v) {setValue(v);}
void operator =(const complexd & v) {setValue(v);}
void operator =(const complexld & v) {setValue(v);}
void operator =(const PIBitArray & v) {setValue(v);}
void operator =(const PIByteArray & v) {setValue(v);}
void operator =(const PIString & v) {setValue(v);}
void operator =(const PIStringList & v) {setValue(v);}
void operator =(const PITime & v) {setValue(v);}
void operator =(const PIDate & v) {setValue(v);}
void operator =(const PIDateTime & v) {setValue(v);}
void operator =(const PISystemTime & v) {setValue(v);}
//! Assign operator
PIVariant & operator =(const PIVariant & v);
//! Assign operator
PIVariant & operator =(const char * v) {setValue(PIString(v)); return *this;}
//! Assign operator
PIVariant & operator =(const bool v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const char v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const uchar v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const short v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const ushort v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const int & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const uint & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const long & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const ulong & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const llong & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const ullong & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const float & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const double & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const ldouble & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const complexd & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const complexld & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIBitArray & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIByteArray & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIString & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIStringList & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PITime & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIDate & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIDateTime & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PISystemTime & v) {setValue(v); return *this;}
//! Compare operator
bool operator ==(const PIVariant & v) const; bool operator ==(const PIVariant & v) const;
//! Compare operator
bool operator !=(const PIVariant & v) const {return !(*this == v);} bool operator !=(const PIVariant & v) const {return !(*this == v);}
//! Returns type of variant content
PIVariant::Type type() const {return type_;} PIVariant::Type type() const {return type_;}
//! Returns type name of variant content
PIString typeName() const {return typeName(type_);} PIString typeName() const {return typeName(type_);}
//! Returns \b true if type is not Invalid
bool isValid() const {return type_ != PIVariant::Invalid;} bool isValid() const {return type_ != PIVariant::Invalid;}
/** \brief Returns new variant from custom type
* \details In case of known types this function equivalent \a PIVariant(T) constructors. \n
* Otherwise returns variant with content \a v and type Custom. */
template <typename T> template <typename T>
static PIVariant fromValue(const T & v) {PIVariant ret; ret._vcustom.resize(sizeof(T)); new((T*)(ret._vcustom.data()))T(v); ret.type_ = PIVariant::Custom; return ret;} static PIVariant fromValue(const T & v) {PIVariant ret; ret._vcustom.resize(sizeof(T)); new((T*)(ret._vcustom.data()))T(v); ret.type_ = PIVariant::Custom; return ret;}
//! Returns type from name
static PIVariant::Type typeFromName(const PIString & tname); static PIVariant::Type typeFromName(const PIString & tname);
//! Returns type name
static PIString typeName(PIVariant::Type type); static PIString typeName(PIVariant::Type type);
private: private:

View File

@@ -41,8 +41,7 @@ public:
PIVector(const PIVector<T> & other): piv_data(0), piv_size(0), piv_rsize(0) { PIVector(const PIVector<T> & other): piv_data(0), piv_size(0), piv_rsize(0) {
//printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name());
alloc(other.piv_size); alloc(other.piv_size);
for (size_t i = 0; i < piv_size; ++i) newT(piv_data, other.piv_data, piv_size);
new(piv_data + i)T(other.piv_data[i]);
//printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data); //printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data);
} }
PIVector(size_t piv_size, const T & f = T()): piv_data(0), piv_size(0), piv_rsize(0) { PIVector(size_t piv_size, const T & f = T()): piv_data(0), piv_size(0), piv_rsize(0) {
@@ -77,10 +76,11 @@ public:
return *this; return *this;
}*/ }*/
if (!oj) { if (!oj) {
deleteT(piv_data, piv_size);
alloc(other.piv_size); alloc(other.piv_size);
//zeroRaw(piv_data, piv_size); //zeroRaw(piv_data, piv_size);
for (size_t i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i)
new(piv_data + i)T(other.piv_data[i]); //piv_data[i] = other.piv_data[i]; elementNew(piv_data + i, other.piv_data[i]); //piv_data[i] = other.piv_data[i];
} else { } else {
printf("JUNK other\n"); printf("JUNK other\n");
} }
@@ -174,6 +174,7 @@ public:
size_t size() const {return piv_size;} size_t size() const {return piv_size;}
ssize_t size_s() const {return piv_size;} ssize_t size_s() const {return piv_size;}
size_t length() const {return piv_size;} size_t length() const {return piv_size;}
size_t capacity() const {return piv_rsize;}
bool isEmpty() const {return (piv_size == 0);} bool isEmpty() const {return (piv_size == 0);}
T & operator [](size_t index) {return piv_data[index];} T & operator [](size_t index) {return piv_data[index];}
@@ -197,7 +198,7 @@ public:
deleteT(piv_data, piv_size); deleteT(piv_data, piv_size);
//zeroRaw(piv_data, piv_size); //zeroRaw(piv_data, piv_size);
for (size_t i = 0; i < piv_size; ++i) for (size_t i = 0; i < piv_size; ++i)
new(piv_data + i)T(f); elementNew(piv_data + i, f);
return *this; return *this;
} }
PIVector<T> & assign(const T & f = T()) {return fill(f);} PIVector<T> & assign(const T & f = T()) {return fill(f);}
@@ -213,7 +214,7 @@ public:
alloc(new_size); alloc(new_size);
//if (sizeof(T) == 1) memset(&(piv_data[os]), f, ds); //if (sizeof(T) == 1) memset(&(piv_data[os]), f, ds);
//zeroRaw(&(piv_data[os]), new_size - os); //zeroRaw(&(piv_data[os]), new_size - os);
for (size_t i = os; i < new_size; ++i) new(piv_data + i)T(f); for (size_t i = os; i < new_size; ++i) elementNew(piv_data + i, f);
} }
return *this; return *this;
} }
@@ -226,18 +227,27 @@ public:
memmove(&(piv_data[index + 1]), &(piv_data[index]), os * sizeof(T)); memmove(&(piv_data[index + 1]), &(piv_data[index]), os * sizeof(T));
} }
//zeroRaw(&(piv_data[index]), 1); //zeroRaw(&(piv_data[index]), 1);
new(piv_data + index)T(v); elementNew(piv_data + index, v);
return *this;
}
PIVector<T> & insert(size_t index, const PIVector<T> & other) {
if (other.isEmpty()) return *this;
ssize_t os = piv_size - index;
alloc(piv_size + other.pid_size, true);
if (os > 0)
memmove(&(piv_data[index + other.piv_size]), &(piv_data[index]), os * sizeof(T));
newT(piv_data + index, other.piv_data, other.piv_size);
return *this; return *this;
} }
PIVector<T> & remove(size_t index, size_t count = 1) { PIVector<T> & remove(size_t index, size_t count = 1) {
if (count == 0) return *this;
if (index + count >= piv_size) { if (index + count >= piv_size) {
resize(index); resize(index);
return *this; return *this;
} }
size_t os = piv_size - index - count; size_t os = piv_size - index - count;
T * de = &(piv_data[index]); deleteT(&(piv_data[index]), count);
deleteT(de, count);
memmove(&(piv_data[index]), &(piv_data[index + count]), os * sizeof(T)); memmove(&(piv_data[index]), &(piv_data[index + count]), os * sizeof(T));
piv_size -= count; piv_size -= count;
return *this; return *this;
@@ -258,14 +268,13 @@ public:
PIVector<T> & removeOne(const T & v) {for (size_t i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); return *this;} return *this;} PIVector<T> & removeOne(const T & v) {for (size_t i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); return *this;} return *this;}
PIVector<T> & removeAll(const T & v) {for (llong i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); --i;} return *this;} PIVector<T> & removeAll(const T & v) {for (llong i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); --i;} return *this;}
PIVector<T> & push_back(const T & v) {alloc(piv_size + 1); new(piv_data + piv_size - 1)T(v); return *this;} PIVector<T> & push_back(const T & v) {alloc(piv_size + 1); elementNew(piv_data + piv_size - 1, v); return *this;}
PIVector<T> & append(const T & v) {return push_back(v);} PIVector<T> & append(const T & v) {return push_back(v);}
PIVector<T> & operator <<(const T & v) {return push_back(v);} PIVector<T> & operator <<(const T & v) {return push_back(v);}
PIVector<T> & operator <<(const PIVector<T> & t) { PIVector<T> & operator <<(const PIVector<T> & other) {
size_t ps = piv_size; size_t ps = piv_size;
alloc(piv_size + t.piv_size); alloc(piv_size + other.piv_size);
for (int i = 0; i < t.piv_size; ++i) newT(piv_data + ps, other.piv_data, other.piv_size);
new(piv_data + ps + i)T(t.piv_data[i]);
return *this; return *this;
} }
@@ -288,6 +297,10 @@ private:
while (s_ >> t) ++t; while (s_ >> t) ++t;
return (1 << t); return (1 << t);
} }
inline void newT(T * dst, const T * src, size_t s) {
for (size_t i = 0; i < s; ++i)
elementNew(dst + i, src[i]);
}
T * newRaw(size_t s) { T * newRaw(size_t s) {
//cout << std::dec << " ![("<<this<<")newRaw " << s << " elements ... <\n" << endl; //cout << std::dec << " ![("<<this<<")newRaw " << s << " elements ... <\n" << endl;
//uchar * ret = new uchar[s * sizeof(T)]; //uchar * ret = new uchar[s * sizeof(T)];
@@ -300,11 +313,11 @@ private:
if (piv_tdata == 0) piv_tdata = (T*)(malloc(s * sizeof(T))); if (piv_tdata == 0) piv_tdata = (T*)(malloc(s * sizeof(T)));
else piv_tdata = (T*)(realloc(piv_tdata, s * sizeof(T))); else piv_tdata = (T*)(realloc(piv_tdata, s * sizeof(T)));
}*/ }*/
void deleteT(T * d, size_t sz) { inline void deleteT(T * d, size_t sz) {
//cout << " ~[("<<this<<")deleteT " << std::dec << sz << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl; //cout << " ~[("<<this<<")deleteT " << std::dec << sz << " elements " << std::hex << "0x" << (llong)d << " ... <\n" << endl;
if ((uchar*)d != 0) { if ((uchar*)d != 0) {
for (size_t i = 0; i < sz; ++i) for (size_t i = 0; i < sz; ++i)
d[i].~T(); elementDelete(d[i]);
//zeroRaw(d, sz); //zeroRaw(d, sz);
} }
//cout << " > ok]~" << endl; //cout << " > ok]~" << endl;
@@ -320,6 +333,8 @@ private:
if ((uchar*)d != 0) memset(d, 0, s*sizeof(T)); if ((uchar*)d != 0) memset(d, 0, s*sizeof(T));
//cout << " > ok]~" << endl; //cout << " > ok]~" << endl;
} }
inline void elementNew(T * to, const T & from) {new(to)T(from);}
inline void elementDelete(T & from) {from.~T();}
void dealloc() {deleteRaw(piv_data);} void dealloc() {deleteRaw(piv_data);}
inline void alloc(size_t new_size) { inline void alloc(size_t new_size) {
if (new_size <= piv_rsize) { if (new_size <= piv_rsize) {
@@ -348,7 +363,7 @@ private:
T * piv_data; T * piv_data;
size_t piv_size, piv_rsize; size_t piv_size, piv_rsize;
}; };
/*
#define __PIVECTOR_SIMPLE_FUNCTIONS__(T) \ #define __PIVECTOR_SIMPLE_FUNCTIONS__(T) \
template<> inline PIVector<T>::~PIVector() {dealloc(); _reset();} \ template<> inline PIVector<T>::~PIVector() {dealloc(); _reset();} \
template<> inline PIVector<T> & PIVector<T>::push_back(const T & v) {alloc(piv_size + 1); piv_data[piv_size - 1] = v; return *this;} \ template<> inline PIVector<T> & PIVector<T>::push_back(const T & v) {alloc(piv_size + 1); piv_data[piv_size - 1] = v; return *this;} \
@@ -377,6 +392,7 @@ private:
return *this; \ return *this; \
} \ } \
template<> inline PIVector<T> & PIVector<T>::remove(size_t index, size_t count) { \ template<> inline PIVector<T> & PIVector<T>::remove(size_t index, size_t count) { \
if (count == 0) return *this; \
if (index + count >= piv_size) { \ if (index + count >= piv_size) { \
resize(index); \ resize(index); \
return *this; \ return *this; \
@@ -399,7 +415,12 @@ __PIVECTOR_SIMPLE_FUNCTIONS__(llong)
__PIVECTOR_SIMPLE_FUNCTIONS__(ullong) __PIVECTOR_SIMPLE_FUNCTIONS__(ullong)
__PIVECTOR_SIMPLE_FUNCTIONS__(float) __PIVECTOR_SIMPLE_FUNCTIONS__(float)
__PIVECTOR_SIMPLE_FUNCTIONS__(double) __PIVECTOR_SIMPLE_FUNCTIONS__(double)
__PIVECTOR_SIMPLE_FUNCTIONS__(ldouble) __PIVECTOR_SIMPLE_FUNCTIONS__(ldouble)*/
#define __PIVECTOR_SIMPLE_TYPE__(T) \
template<> inline void PIVector<T>::newT(T * dst, const T * src, size_t s) {memcpy(dst, src, s * sizeof(T));} \
template<> inline void PIVector<T>::deleteT(T * d, size_t sz) {;} \
template<> inline void PIVector<T>::elementNew(T * to, const T & from) {(*to) = from;} \
template<> inline void PIVector<T>::elementDelete(T & from) {;}
#else #else
@@ -484,7 +505,7 @@ public:
#endif #endif
}; };
#define __PIVECTOR_SIMPLE_FUNCTIONS__(T) #define __PIVECTOR_SIMPLE_TYPE__(T)
#endif #endif