diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c20124c..ee50668e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(pip) cmake_minimum_required(VERSION 2.6) include_directories(${CMAKE_CURRENT_SOURCE_DIR} .) include(CheckFunctionExists) -set(VERSION "0.0305") +set(VERSION "0.0306") set(SOVERSION ${VERSION}) set(CMAKE_BUILD_TYPE "Release") set(LIBS) @@ -51,12 +51,12 @@ endif () if (${WIN32}) list(APPEND LIBS ws2_32 Iphlpapi) - include(GenerateExportHeader) execute_process(COMMAND "make_rc_win.bat" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) list(APPEND CPPS "pip_resource_win.o") add_library(pip SHARED ${CPPS}) - generate_export_header(pip) if (${CMAKE_C_COMPILER} STREQUAL "cl") + include(GenerateExportHeader) + generate_export_header(pip) add_definitions("/O2 /Ob2 /Ot") else () add_definitions("-O2") @@ -65,13 +65,12 @@ else () add_definitions("-O2") if (DEFINED ENV{QNX_HOST}) list(APPEND LIBS socket) + add_definitions("-ftemplate-depth-32") add_library(pip STATIC ${CPPS}) else () list(APPEND LIBS pthread rt) - include(GenerateExportHeader) add_definitions("-Wall -g3") add_library(pip SHARED ${CPPS}) - generate_export_header(pip) endif () endif () target_link_libraries(pip ${LIBS}) diff --git a/main.cpp b/main.cpp index 7e496bf8..d0f15a9e 100644 --- a/main.cpp +++ b/main.cpp @@ -245,8 +245,10 @@ int main (int argc, char * argv[]) { console.enableExitCapture(); PIProtocol p("/home/peri4/work/ISPUM/nosit_VM6/protocols.conf", "gas", 0, 0, &a__, 4, &b__, 4); p.start(); + console.addTab("ftab", 'f'); console.addVariable("service", &p); - console.start(); + console.addTab("stab", 's'); + //console.start(); console.startServer("cons"); console.waitForFinish(); return 0; diff --git a/pibytearray.cpp b/pibytearray.cpp index 127755e9..518cec11 100644 --- a/pibytearray.cpp +++ b/pibytearray.cpp @@ -19,6 +19,74 @@ #include "pibytearray.h" +/*! \class PIByteArray + * \brief Byte array + * \details This class based on PIVector and provide some handle function + * to manipulate it. + * + * \section PIByteArray_sec0 Usage + * 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 + * places data at the end of arraym restore operators takes data from the beginning + * of array. + * In addition there are Base 64 convertions and checksums: + * * plain 8-bit + * * plain 32-bit + * * CRC 8-bit + * * CRC 16-bit + * * CRC 32-bit + * + */ + + +#pragma pack(push, 1) + +const char PIByteArray::base64Table[64] = { +0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, +0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, +0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, +0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, +0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, +0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, +0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, +0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f}; + +const char PIByteArray::base64InvTable[256] = { +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3F, +0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, +0x3C, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, +0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, +0x17, 0x18, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, +0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, +0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, +0x31, 0x32, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + +#pragma pack(pop) + int PIHuffman::nodeCompare(const void * f, const void * s) { return (reinterpret_cast(const_cast(s))->freq - diff --git a/pibytearray.h b/pibytearray.h index 32389dde..d4298425 100644 --- a/pibytearray.h +++ b/pibytearray.h @@ -1,3 +1,6 @@ +/*! \file pibytearray.h + * \brief Byte array +*/ /* PIP - Platform Independent Primitives Byte array @@ -20,56 +23,13 @@ #ifndef PIBYTEARRAY_H #define PIBYTEARRAY_H +#ifdef DOXYGEN +//! This macro allow stream template operators for write and read any type from byte array. Use it with attention! +# define PIP_BYTEARRAY_STREAM_ANY_TYPE +#endif + #include "pibitarray.h" -#pragma pack(push, 1) - -static const char base64Table[64] = { -0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, -0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, -0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, -0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, -0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, -0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, -0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, -0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f}; - -static const char base64InvTable[256] = { -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3F, -0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, -0x3C, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, -0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, -0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, -0x17, 0x18, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, -0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, -0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, -0x31, 0x32, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - -#pragma pack(pop) - class PIByteArray; class PIHuffman { @@ -90,17 +50,28 @@ private: PIVector nodes; }; -class PIP_EXPORT PIByteArray: public PIVector { +class PIP_EXPORT PIByteArray: public PIVector +{ public: + + //! Contructs an empty byte array PIByteArray() {;} + + //! Contructs 0-filled byte array size "size" PIByteArray(const uint size) {resize(size);} + + //! Contructs 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]);} - + + + //! Help struct to store/restore custom blocks of data to/from PIByteArray struct RawData { friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v); friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v); public: + //! Contructs data block RawData(void * data, int size) {d = data; s = size;} + //! Contructs data block RawData(const void * data, const int size) {d = const_cast(data); s = size;} RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;} private: @@ -108,11 +79,19 @@ public: int s; }; + //! Return resized byte array PIByteArray resized(int new_size) {PIByteArray tv(*this); tv.resize(new_size); return tv;} + //! Convert data to Base 64 and return this byte array PIByteArray & convertToBase64(); + + //! Convert data from Base 64 and return this byte array PIByteArray & convertFromBase64(); + + //! Return converted to Base 64 data PIByteArray toBase64() {PIByteArray ba(*this); ba.convertToBase64(); return ba;} + + //! Return converted from Base 64 data PIByteArray fromBase64() {PIByteArray ba(*this); ba.convertFromBase64(); return ba;} PIByteArray & compressRLE(uchar threshold = 192); @@ -122,7 +101,10 @@ public: PIByteArray & compressHuffman() {*this = huffman.compress(*this); return *this;} + //! Add to the end data "data" with size "size" PIByteArray & append(void * data, int size) {for (int i = 0; i < size; ++i) push_back(((uchar*)data)[i]); return *this;} + + //! Add to the end byte array "data" PIByteArray & append(const PIByteArray & data) {for (int i = 0; i < data.size_s(); ++i) push_back(data[i]); return *this;} /*PIByteArray & operator <<(short v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} PIByteArray & operator <<(ushort v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} @@ -132,10 +114,19 @@ public: PIByteArray & operator <<(ullong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}*/ //PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;} + //! Returns plain 8-bit checksum uchar checksumPlain8(); + + //! Returns plain 32-bit checksum uint checksumPlain32(); + + //! Returns CRC 8-bit checksum uchar checksumCRC8(); + + //! Returns CRC 16-bit checksum ushort checksumCRC16(); + + //! Returns CRC 32-bit checksum uint checksumCRC32(); void operator =(const PIVector & d) {resize(d.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = d[i];} @@ -156,65 +147,108 @@ private: } byte; }; + static const char base64Table[64]; + static const char base64InvTable[256]; static PIHuffman huffman; }; +//! \relatesalso PIByteArray \brief Output to std::ostream operator inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba) {s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; return s;} + +//! \relatesalso PIByteArray \brief Output to PICout operator inline PICout operator <<(PICout s, const PIByteArray & ba) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} #define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v)); +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << v.size_s(); int os = s.size_s(); s.enlarge(v.size_s()); if (v.size_s() > 0) memcpy(s.data(os), v.data(), v.size()); return s;} +//! \relatesalso PIByteArray \brief Store operator 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 template inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} +//! \relatesalso PIByteArray \brief Store operator template inline PIByteArray & operator <<(PIByteArray & s, const PIList & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} +//! \relatesalso PIByteArray \brief Store operator template inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} -//template -//inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;} +#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE +template +inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;} +#endif #undef PBA_OPERATOR_TO #define PBA_OPERATOR_FROM memcpy(&v, s.data(), sizeof(v)); s.remove(0, sizeof(v)); +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator inline PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); if (sz > 0) memcpy(v.data(), s.data(), v.size()); s.remove(0, v.size()); return s;} +//! \relatesalso PIByteArray \brief Restore operator 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 template inline PIByteArray & operator >>(PIByteArray & s, PIVector & 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 inline PIByteArray & operator >>(PIByteArray & s, PIList & 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 inline PIByteArray & operator >>(PIByteArray & s, PIDeque & 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;} -//template -//inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE +template +inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +#endif #undef PBA_OPERATOR_FROM +//! \relatesalso PIByteArray \brief Byte arrays compare operator inline bool operator ==(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return false; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return false; return true;} +//! \relatesalso PIByteArray \brief Byte arrays compare operator inline bool operator !=(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return true; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return true; return false;} #endif // PIBYTEARRAY_H diff --git a/piconfig.cpp b/piconfig.cpp index 2bcdc4f2..9abb53b8 100644 --- a/piconfig.cpp +++ b/piconfig.cpp @@ -19,6 +19,28 @@ #include "piconfig.h" +/*! \class PIConfig + * \brief Configuration file + * \details This class provide handle access to configuration file. + * + * \section PIConfig_sec0 Synopsis + * PIConfig reads configuration file and create internal dendritic + * representation of all entries of this file. You can easily read + * some values and write new. + * \image html piconfig.png + * + * \section PIConfig_sec1 Concepts + * Each entry of internal tree has type PIConfig::Entry. This class + * has next properties: + * * name + * * value + * * type + * * comment + * Entry class has many implicit convertions to common types: bolean, + * integers, float, double, PIString, PIStringList. + * + */ + PIConfig::Entry PIConfig::Branch::_empty; PIConfig::Entry PIConfig::Entry::_empty; diff --git a/piconfig.h b/piconfig.h index d80ea41f..0852f278 100644 --- a/piconfig.h +++ b/piconfig.h @@ -1,3 +1,6 @@ +/*! \file piconfig.h + * \brief Configuration file +*/ /* PIP - Platform Independent Primitives Config parser @@ -54,7 +57,9 @@ class PIP_EXPORT PIConfig: public PIFile friend class Entry; friend class Branch; public: + //! Contructs and read configuration file at path "path" in mode "mode" PIConfig(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + ~PIConfig() {/*piForeach (Entry * i, root._children) deleteEntry(i); close();*/} class Entry; @@ -172,10 +177,13 @@ public: int _line; }; + //! Returns top-level entry with name "vname", if doesn`t exists return entry with value "def" and set *exist to false Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exist = 0) const {return const_cast(this)->getValue(vname, def, exist);} + PICONFIG_GET_VALUE + //! Returns top-level entries with names matches "vname" Branch getValues(const PIString & vname); void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); @@ -192,12 +200,21 @@ public: void setValue(const PIString & name, const float value, bool write = true) {setValue(name, ftos(value), "f", write);} void setValue(const PIString & name, const double value, bool write = true) {setValue(name, dtos(value), "f", write);} + //! Returns root entry Entry & rootEntry() {return root;} + + //! Returns top-level entries count int entriesCount() const {return childCount(&root);} + + //! Returns if top-level entry with name "name" exists bool isEntryExists(const PIString & name) const {return entryExists(&root, name);} + //! Returns all top-level entries Branch allTree() {Branch b; piForeach (Entry * i, root._children) b << i; return b;} + + //! Returns all entries without children Branch allLeaves() {Branch b; allLeaves(b, &root); b.sort(Entry::compare); return b;} + int entryIndex(const PIString & name); PIString getName(uint number) {return entryByIndex(number)._name;} @@ -216,8 +233,11 @@ public: void readAll(); void writeAll(); - + + //! Returns current tree delimiter const PIString & delimiter() const {return delim;} + + //! Set current tree delimiter void setDelimiter(const PIString & d) {delim = d; setEntryDelim(&root, d); readAll();} private: diff --git a/piconsole.cpp b/piconsole.cpp index cf8d94a4..02b4bc41 100644 --- a/piconsole.cpp +++ b/piconsole.cpp @@ -356,7 +356,10 @@ void PIConsole::run() { const void * ptr = 0; if (tv.remote) { if (tv.type == 0) { - rstr << PIByteArray(tv.rdata); + rstr.clear(); + PIByteArray tba(tv.rdata); + tba >> rstr; + rstr.trim(); ptr = &rstr; } else ptr = tv.rdata.data(); @@ -380,12 +383,13 @@ void PIConsole::run() { case 14: clen = printValue(bitsValue(ptr, tv.bitFrom, tv.bitCount), tv.format); break; } if (clen + tv.offset < (uint)col_wid) { + PIString ts = PIString( #if defined(QNX) || defined(FREE_BSD) - string ts = PIString(col_wid - clen - tv.offset - 1, ' ').stdString(); + col_wid - clen - tv.offset - 1, ' '); #else - string ts = PIString(col_wid - clen - tv.offset, ' ').stdString(); + col_wid - clen - tv.offset, ' '); #endif - printf("%s", ts.c_str()); + printf("%s", ts.data()); } newLine(); } @@ -878,6 +882,7 @@ void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) { void PIConsole::peerTimer(void * data, int delim) { if (peer == 0) return; + //piCout << "timer" << delim; if (server_mode) { if (delim == 20) serverSendInfo(); diff --git a/piconsole.h b/piconsole.h index 3162a9eb..a5a8901d 100644 --- a/piconsole.h +++ b/piconsole.h @@ -1,3 +1,6 @@ +/*! \file piconsole.h + * \brief Console output class +*/ /* PIP - Platform Independent Primitives Console output/input @@ -158,7 +161,7 @@ public: void moveRight(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(n));} void moveLeft(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(-n));} void moveTo(int x = 0, int y = 0) {ccoord.X = x; ccoord.Y = y; SetConsoleCursorPosition(hOut, ccoord);} - void clearScreen() {FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); + void clearScreen() {toUpperLeft(); FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);} void clearScreenLower() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width * height - width * ccoord.Y + ccoord.X, ccoord, &written); FillConsoleOutputCharacter(hOut, ' ', width * height - width * ccoord.Y + ccoord.X, ccoord, &written);} diff --git a/picontainers.h b/picontainers.h index 6d8d47d0..ba357fd2 100644 --- a/picontainers.h +++ b/picontainers.h @@ -712,6 +712,7 @@ public: _CMap & insert(PIPair entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} Key key(Type value_) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();} Type & value(const Key & key_) {typename _stlc::iterator it = _stlc::find(key_); if (it == _stlc::end()) it->second = Type(); return it->second;} + Type & at(const Key & key_) {return value(key_);} Type value(const Key & key_) const {return _stlc::find(key_)->second;} }; diff --git a/picrc.h b/picrc.h index 4b0c08c0..1ea8f0c1 100644 --- a/picrc.h +++ b/picrc.h @@ -1,3 +1,6 @@ +/*! \file picrc.h + * \brief CRC checksum calculator +*/ /* PIP - Platform Independent Primitives Abstract input/output device diff --git a/pidiagnostics.h b/pidiagnostics.h index 993bac9d..dce3003a 100644 --- a/pidiagnostics.h +++ b/pidiagnostics.h @@ -1,3 +1,6 @@ +/*! \file pidiagnostics.h + * \brief Connection quality diagnostics +*/ /* PIP - Platform Independent Primitives Speed and quality in/out diagnostics diff --git a/piethernet.cpp b/piethernet.cpp index cd4c260d..96024990 100644 --- a/piethernet.cpp +++ b/piethernet.cpp @@ -72,6 +72,7 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) { PIEthernet::~PIEthernet() { piMonitor.ethernets--; if (server_thread_.isRunning()) server_thread_.terminate(); + stop(); closeSocket(sock); //if (buffer_ != 0) delete buffer_; //buffer_ = 0; @@ -110,7 +111,6 @@ bool PIEthernet::init() { #else BOOL bv = TRUE; if (params[PIEthernet::ReuseAddress]) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char * )&bv, sizeof(bv)); - setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (const char * )&bv, sizeof(bv)); #endif //cout << "inited " << sock << ": bc = " << params << endl; //fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/); @@ -170,6 +170,20 @@ bool PIEthernet::closeDevice() { } +void PIEthernet::closeSocket(int & sd) { + if (sd != -1) { +#ifdef WINDOWS + shutdown(sd, SD_BOTH); + closesocket(sd); +#else + shutdown(sock, SHUT_RDWR); + ::close(sd); +#endif + } + sd = -1; +} + + bool PIEthernet::joinMulticastGroup(const PIString & group) { if (sock == -1) init(); if (sock == -1) return false; @@ -195,7 +209,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) { piCoutObj << "[PIEthernet] Can`t join multicast group " << group << ", " << ethErrorString(); return false; } - leafs.insert(group, ret); + if (ret != sock) leafs.insert(group, ret); #else # ifndef QNX if (!params[Broadcast]) @@ -385,11 +399,13 @@ int PIEthernet::write(const void * data, int max_size) { /*if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST; else*/ saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); saddr_.sin_family = AF_INET; + //piCout << "[PIEth] write to" << ip_s << ":" << port_s << max_size << "bytes ..."; #ifdef WINDOWS return sendto(sock, (const char * )data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); #else return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); #endif + //piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok"; case TCP_Client: return ::send(sock, (const char *)data, max_size, 0); default: break; @@ -519,12 +535,22 @@ PIEthernet::InterfaceList PIEthernet::interfaces() { ci.address = getSockAddr(ret->ifa_addr); ci.netmask = getSockAddr(ret->ifa_netmask); ci.mac.clear(); +#ifdef QNX + int fd = ::open((PIString("/dev/io-net/") + ci.name).data(), O_RDONLY); + if (fd != 0) { + nic_config_t nic; + devctl(fd, DCMD_IO_NET_GET_CONFIG, &nic, sizeof(nic), 0); + ::close(fd); + ci.mac = macFromBytes(PIByteArray(nic.permanent_address, 6)); + } +#else if (s != -1) { struct ifreq ir; strcpy(ir.ifr_name, ret->ifa_name); if (ioctl(s, SIOCGIFHWADDR, &ir) == 0) ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6)); } +#endif ci.flags = 0; if (ret->ifa_flags & IFF_UP) ci.flags |= PIEthernet::ifActive; if (ret->ifa_flags & IFF_RUNNING) ci.flags |= PIEthernet::ifRunning; diff --git a/piethernet.h b/piethernet.h index ab7757e0..2f921729 100644 --- a/piethernet.h +++ b/piethernet.h @@ -1,3 +1,6 @@ +/*! \file piethernet.h + * \brief Ethernet device +*/ /* PIP - Platform Independent Primitives Ethernet, UDP/TCP Broadcast/Multicast @@ -145,10 +148,8 @@ protected: bool init(); bool openDevice(); bool closeDevice(); -#ifdef WINDOWS - void closeSocket(int & sd) {if (sd != -1) {shutdown(sd, SD_BOTH); closesocket(sd);} sd = -1;} -#else - void closeSocket(int & sd) {if (sd != -1) {shutdown(sock, SHUT_RDWR); ::close(sd);} sd = -1;} + void closeSocket(int & sd); +#ifndef WINDOWS static PIString getSockAddr(sockaddr * s) {return s == 0 ? PIString() : PIString(inet_ntoa(((sockaddr_in*)s)->sin_addr));} #endif diff --git a/pievaluator.cpp b/pievaluator.cpp index 2818231d..ec041f15 100644 --- a/pievaluator.cpp +++ b/pievaluator.cpp @@ -970,22 +970,22 @@ inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci) tmpvars[oi].value = value(ci.operators[0]) * complexd(rad2deg, 0.); break; case PIEvaluatorTypes::bfJ0: - tmpvars[oi].value = j0(value(ci.operators[0]).real()); + tmpvars[oi].value = piJ0(value(ci.operators[0]).real()); break; case PIEvaluatorTypes::bfJ1: - tmpvars[oi].value = j1(value(ci.operators[0]).real()); + tmpvars[oi].value = piJ1(value(ci.operators[0]).real()); break; case PIEvaluatorTypes::bfJN: - tmpvars[oi].value = jn(round(value(ci.operators[1]).real()), value(ci.operators[0]).real()); + tmpvars[oi].value = piJn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); break; case PIEvaluatorTypes::bfY0: - tmpvars[oi].value = y0(value(ci.operators[0]).real()); + tmpvars[oi].value = piY0(value(ci.operators[0]).real()); break; case PIEvaluatorTypes::bfY1: - tmpvars[oi].value = y1(value(ci.operators[0]).real()); + tmpvars[oi].value = piY1(value(ci.operators[0]).real()); break; case PIEvaluatorTypes::bfYN: - tmpvars[oi].value = yn(round(value(ci.operators[1]).real()), value(ci.operators[0]).real()); + tmpvars[oi].value = piYn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); break; case PIEvaluatorTypes::bfRandom: tmp = static_cast(rand()) / RAND_MAX; diff --git a/pievaluator.h b/pievaluator.h index 40b5e07d..9a366fae 100644 --- a/pievaluator.h +++ b/pievaluator.h @@ -1,3 +1,6 @@ +/*! \file pievaluator.h + * \brief Mathematic expressions calculator +*/ /* PIP - Platform Independent Primitives Evaluator designed for stream computing diff --git a/pifile.h b/pifile.h index 77711f62..f8574a4b 100644 --- a/pifile.h +++ b/pifile.h @@ -1,3 +1,6 @@ +/*! \file pifile.h + * \brief Local file +*/ /* PIP - Platform Independent Primitives File diff --git a/piincludes.cpp b/piincludes.cpp index 1754eb60..1556681d 100644 --- a/piincludes.cpp +++ b/piincludes.cpp @@ -214,6 +214,34 @@ void PICout::applyFormat(PICoutFormat f) { } -/*! \mainpage Title - * This is main page +/*! \mainpage What is PIP + * 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 + * projects much more quickly, efficiently and customizable than on pure C++. + * Library contains more classes, some of them are pure abstract, some classes + * can be used as they are, some classes should be inherited to new classes. + * PIP provide classes: + * * direct output to console (\a PICout) + * * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack) + * * string (\a PIString, \a PIStringList) + * * base object (events and handlers) (\a PIObject) + * * thread (\a PIThread) + * * timer (\a PITimer) + * * console (information output) (\a PIConsole) + * * stand-alone + * * server + * * client + * * i/o devices + * * base class (\a PIIODevice) + * * file (\a PIFile) + * * serial port (\a PISerial) + * * ethernet (\a PIEthernet) + * * USB (\a PIUSB) + * * packets extractor (\a PIPacketExtractor) + * * command-line arguments parser (\a PICLI) + * * math evaluator (\a PIEvaluator) + * * peering net node (\a PIPeer) + * * process (\a PIProcess) + * * state machine (\a PIStateMachine) + * */ diff --git a/piincludes.h b/piincludes.h index 6e51a0f0..09737057 100644 --- a/piincludes.h +++ b/piincludes.h @@ -39,7 +39,7 @@ #define PIP_VERSION_REVISION PIP_VERSION & 0xFF //! Suffix of PIP version -#define PIP_VERSION_SUFFIX "" +#define PIP_VERSION_SUFFIX "_r1" #ifdef DOXYGEN @@ -207,6 +207,11 @@ # include # include # include +# ifdef QNX +# include +# include +# include +# endif #endif #ifdef MAC_OS # include @@ -813,6 +818,7 @@ public: case Quote: std::cout << '"'; break; }; return *this; + } //! Output operator for \a PIFlags values diff --git a/piiodevice.cpp b/piiodevice.cpp index 8db6bc67..74a5369b 100644 --- a/piiodevice.cpp +++ b/piiodevice.cpp @@ -100,6 +100,16 @@ PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool } +PIIODevice::~PIIODevice() { + stop(); + if (opened_) { + closeDevice(); + if (!opened_) + closed(); + } +} + + void PIIODevice::check_start(void * data, int delim) { //cout << "check " << tread_started_ << endl; if (open()) { diff --git a/piiodevice.h b/piiodevice.h index 1119ed3f..b981616c 100644 --- a/piiodevice.h +++ b/piiodevice.h @@ -45,7 +45,7 @@ public: }; PIIODevice(const PIString & path, DeviceMode type = ReadWrite, bool initNow = true); - virtual ~PIIODevice() {stop(); if (opened_) {closeDevice(); if (!opened_) closed();}} + virtual ~PIIODevice(); //! Current open mode of device DeviceMode mode() const {return mode_;} @@ -122,7 +122,7 @@ public: void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) PIThread::start();} //! Stop threaded read - void stopThreadedRead() {PIThread::stop();} + void stopThreadedRead() {PIThread::terminate();} //! Return \b true if threaded write is started @@ -132,7 +132,7 @@ public: void startThreadedWrite() {if (!write_thread.isRunning()) write_thread.startOnce();} //! Stop threaded write - void stopThreadedWrite() {write_thread.stop();} + void stopThreadedWrite() {write_thread.terminate();} //! Clear threaded write task queue void clearThreadedWriteQueue() {write_thread.lock(); write_queue.clear(); write_thread.unlock();} diff --git a/pikbdlistener.h b/pikbdlistener.h index 508439e3..8ff6414f 100644 --- a/pikbdlistener.h +++ b/pikbdlistener.h @@ -1,3 +1,6 @@ +/*! \file pikbdlistener.h + * \brief Keyboard console input listerner +*/ /* PIP - Platform Independent Primitives Keyboard grabber for console diff --git a/pimath.cpp b/pimath.cpp index 1d44b3f5..79a6ccb6 100644 --- a/pimath.cpp +++ b/pimath.cpp @@ -20,8 +20,8 @@ #include "pimath.h" +double piJ0(const double & v) { #ifndef PIP_MATH_J0 -double j0(const double & v) { double x = v; double xsq; double nn; @@ -92,12 +92,14 @@ double j0(const double & v) { q1 = 5428918384092285160.200195092 + xsq * q1; q1 = 493378725179413356211.3278438 + xsq * q1; return p1 / q1; -} +#else + return j0(v); #endif +} +double piJ1(const double & v) { #ifndef PIP_MATH_J1 -double j1(const double & v) { double x = v; double s; double xsq; @@ -172,12 +174,14 @@ double j1(const double & v) { q1 = 1162398708003212287858.529400 + xsq * q1; result = s * x * p1 / q1; return result; -} +#else + return j1(v); #endif +} +double piJn(int n, const double & v) { #ifndef PIP_MATH_JN -double jn(const int & n, const double & v) { double x = v; double pkm2; double pkm1; @@ -202,18 +206,18 @@ double jn(const int & n, const double & v) { x = -x; } if (n == 0) { - result = sg * j0(x); + result = sg * piJ0(x); return result; } if (n == 1) { - result = sg * j1(x); + result = sg * piJ1(x); return result; } if (n == 2) { if (x == 0) result = 0; else - result = sg * (2.0 * j1(x) / x - j0(x)); + result = sg * (2.0 * piJ1(x) / x - piJ0(x)); return result; } if (x < 1E-16) { @@ -242,17 +246,19 @@ double jn(const int & n, const double & v) { k = k - 1; } while (k != 0); if (fabs(pk) > fabs(pkm1)) - ans = j1(x) / pk; + ans = piJ1(x) / pk; else - ans = j0(x) / pkm1; + ans = piJ0(x) / pkm1; result = sg * ans; return result; -} +#else + return jn(n, v); #endif +} +double piY0(const double & v) { #ifndef PIP_MATH_Y0 -double y0(const double & v) { double x = v; double nn; double xsq; @@ -321,14 +327,16 @@ double y0(const double & v) { q4 = 23928830434997818.57439356652 + xsq * q4; q4 = 4192417043410839973.904769661 + xsq * q4; q4 = 372645883898616588198.9980 + xsq * q4; - result = p4 / q4 + 2 / M_PI * j0(x) * log(x); + result = p4 / q4 + 2 / M_PI * piJ0(x) * log(x); return result; -} +#else + return y0(v); #endif +} +double piY1(const double & v) { #ifndef PIP_MATH_Y1 -double y1(const double & v) { double x = v; double nn; double xsq; @@ -396,14 +404,16 @@ double y1(const double & v) { q4 = 29549879358971486742.90758119 + xsq * q4; q4 = 5435310377188854170800.653097 + xsq * q4; q4 = 508206736694124324531442.4152 + xsq * q4; - result = x * p4 / q4 + 2 / M_PI * (j1(x) * log(x) - 1 / x); + result = x * p4 / q4 + 2 / M_PI * (piJ1(x) * log(x) - 1 / x); return result; -} +#else + return y1(v); #endif +} +double piYn(int n, const double & v) { #ifndef PIP_MATH_YN -double yn(const int & n, const double & v) { int i; double x = v; double a; @@ -418,15 +428,15 @@ double yn(const int & n, const double & v) { s = -1; } if (n == 0) { - result = y0(x); + result = piY0(x); return result; } if (n == 1) { - result = s * y1(x); + result = s * piY1(x); return result; } - a = y0(x); - b = y1(x); + a = piY0(x); + b = piY1(x); for (i = 1; i <= n - 1; i++) { tmp = b; b = 2 * i / x * b - a; @@ -434,8 +444,10 @@ double yn(const int & n, const double & v) { } result = s * b; return result; -} +#else + return yn(n, v); #endif +} double randomn(double dv, double sv) { diff --git a/pimath.h b/pimath.h index 310546bf..620e2413 100644 --- a/pimath.h +++ b/pimath.h @@ -1,3 +1,6 @@ +/*! \file pimath.h + * \brief Many mathematical functions and classes +*/ /* PIP - Platform Independent Primitives Math @@ -27,6 +30,12 @@ #else # include # include +# undef PIP_MATH_J0 +# undef PIP_MATH_J1 +# undef PIP_MATH_JN +# undef PIP_MATH_Y0 +# undef PIP_MATH_Y1 +# undef PIP_MATH_YN #endif #ifndef M_LN2 @@ -110,24 +119,12 @@ inline complexd log2(const complexd & c) {return log(c) / M_LN2;} inline complexd log10(const complexd & c) {return log(c) / M_LN10;} # endif #endif -#ifndef PIP_MATH_J0 - __attribute__ ((unused)) static double j0(const double & v); -#endif -#ifndef PIP_MATH_J1 -__attribute__ ((unused)) static double j1(const double & v); -#endif -#ifndef PIP_MATH_JN -__attribute__ ((unused)) static double jn(const int & n, const double & v); -#endif -#ifndef PIP_MATH_Y0 -__attribute__ ((unused)) static double y0(const double & v); -#endif -#ifndef PIP_MATH_Y1 -__attribute__ ((unused)) static double y1(const double & v); -#endif -#ifndef PIP_MATH_YN -__attribute__ ((unused)) static double yn(const int & n, const double & v); -#endif +double piJ0(const double & v); +double piJ1(const double & v); +double piJn(int n, const double & v); +double piY0(const double & v); +double piY1(const double & v); +double piYn(int n, const double & v); inline double toDb(double val) {return 10. * log10(val);} inline double fromDb(double val) {return pow(10., val / 10.);} inline double toRad(double deg) {return deg * M_PI_180;} diff --git a/pimutex.h b/pimutex.h index b7c68bdd..265f7202 100644 --- a/pimutex.h +++ b/pimutex.h @@ -1,3 +1,6 @@ +/*! \file pimutex.h + * \brief Mutex +*/ /* PIP - Platform Independent Primitives Mutex diff --git a/pipacketextractor.h b/pipacketextractor.h index ade0ad30..18a00d72 100644 --- a/pipacketextractor.h +++ b/pipacketextractor.h @@ -1,3 +1,6 @@ +/*! \file pipacketextractor.h + * \brief Packets extractor +*/ /* PIP - Platform Independent Primitives Packets extractor diff --git a/pipeer.cpp b/pipeer.cpp index 23dfa7bb..db7b3106 100644 --- a/pipeer.cpp +++ b/pipeer.cpp @@ -21,7 +21,7 @@ #define _PIPEER_PORT_SYNC_START 13313 #define _PIPEER_PORT_SYNC_END 13353 -#define _PIPEER_IP_MULTICAST "239.13.3.12" +#define _PIPEER_IP_MULTICAST "230.13.3.12" #define _PIPEER_MSG_SIZE 8192 PIPeer::PIPeer(const PIString & name): PIObject() { @@ -29,6 +29,7 @@ PIPeer::PIPeer(const PIString & name): PIObject() { setName(name); self_info.name = name_; self_info.dist = 0; + eth_send = 0; //joinMulticastGroup("239.240.241.242"); srand(uint(PITimer::elapsed_system_m())); //id_ = name() + "_" + PIString::fromNumber(rand()); @@ -37,21 +38,24 @@ PIPeer::PIPeer(const PIString & name): PIObject() { sl.removeAll("127.0.0.1"); sl << "127.0.0.1"; initMulticasts(sl); initEths(sl); - //piCout << "Peer" << name_; + sendSelfInfo(); timer.addDelimiter(5); timer.start(1000); - sendSelfInfo(); } PIPeer::~PIPeer() { piForeach (PIEthernet * i, mc_eths) i->stopThreadedRead(); + if (eth_send != 0) + eth_send->stopThreadedRead(); sendSelfRemove(); destroyMulticasts(); piForeach (PIEthernet * i, eths) delete i; eths.clear(); + if (eth_send != 0) + delete eth_send; } @@ -88,6 +92,9 @@ void PIPeer::initEths(const PIStringList & al) { } } } + eth_send = new PIEthernet(); + eth_send->setParameters(0); + eth_send->setDebug(false); } @@ -116,6 +123,7 @@ void PIPeer::initMulticasts(const PIStringList & al) { if (!ce->open()) continue; if (is_main) if (!ce->joinMulticastGroup(_PIPEER_IP_MULTICAST)) continue; //piCout << "mc binded to" << ce->path(); + ce->setName(is_main ? "no_send" : ""); mc_eths << ce; if (is_main || is_bc) { if (is_main) rec_mc = true; @@ -175,14 +183,6 @@ PIPeer::PeerInfo * PIPeer::quickestPeer(const PIString & to) { } -bool PIPeer::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) { - if (peer->_neth == 0) return false; - //piCout << "send to" << peer->name << peer->_naddress << ba.size_s() << "bytes"; - diag_d.sended(ba.size_s()); - return peer->_neth->send(peer->_naddress, ba.data(), ba.size_s()); -} - - bool PIPeer::send(const PIString & to, const void * data, int size) { PeerInfo * dp = quickestPeer(to); if (dp == 0) { @@ -193,6 +193,7 @@ bool PIPeer::send(const PIString & to, const void * data, int size) { ba << int(4) << self_info.name << to << int(0) << size; PIByteArray fmsg(data, size), cmsg; int msg_count = (size - 1) / _PIPEER_MSG_SIZE + 1; + //piCout << "[PIPeer] send" << size << "bytes in" << msg_count << "packets ..."; for (int i = 0; i < msg_count; ++i) { int csize = (i == msg_count - 1) ? ((size - 1) % _PIPEER_MSG_SIZE + 1) : _PIPEER_MSG_SIZE; cmsg.clear(); @@ -201,17 +202,23 @@ bool PIPeer::send(const PIString & to, const void * data, int size) { cmsg.append(fmsg.data(i * _PIPEER_MSG_SIZE), csize); if (!sendToNeighbour(dp, cmsg)) return false; } + //piCout << "[PIPeer] send" << size << "bytes ok"; return true; } bool PIPeer::dataRead(uchar * readed, int size) { - diag_d.received(size); + if (size < 16) return true; PIByteArray ba(readed, size), sba; int type, cnt, rec_size; PIString from, to; - ba >> type >> from >> to >> cnt >> rec_size; - //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << type << from << to << cnt << rec_size; + ba >> type; + //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << type; + if (type != 4) return true; + PIMutexLocker locker(eth_mutex); + diag_d.received(size); + ba >> from >> to >> cnt >> rec_size; + //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << /*type << from << to << cnt <<*/ rec_size; if (type == 4) { // data packet if (to == self_info.name) { // my packet int msg_count, cmsg; @@ -256,17 +263,20 @@ bool PIPeer::dataRead(uchar * readed, int size) { bool PIPeer::multicastRead(uchar * data, int size) { + if (size < 8) return true; + int type; + PIByteArray ba(data, size); + ba >> type; + if (type <= 0 || type >= 4) return true; + PeerInfo pi; + PIVector rpeers; + ba >> pi.name; + //piCout << "read type" << type << "from" << pi.name; + if (pi.name == name_) return true; PIMutexLocker locker(mc_mutex); diag_s.received(size); - int header; - PeerInfo pi; - PIByteArray ba(data, size); - PIVector rpeers; - ba >> header >> pi.name; - //piCout << "read type" << header << "from" << pi.name; - if (pi.name == name_) return true; //piCout << "analyz ..."; - switch (header) { + switch (type) { case 1: // new peer accepted //piCout << "new peer packet ..."; if (hasPeer(pi.name)) break; @@ -346,17 +356,31 @@ bool PIPeer::multicastRead(uchar * data, int size) { } +bool PIPeer::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) { + if (peer->_neth == 0) return false; + //piCout << "[PIPeer] sendToNeighbour" << (eth_send->readAddress()) << peer->_naddress << ba.size_s() << "bytes ..."; + //bool ok = peer->_neth->send(peer->_naddress, ba.data(), ba.size_s()); + bool ok = eth_send->send(peer->_naddress, ba.data(), ba.size_s()); + //piCout << "[PIPeer] sendToNeighbour" << (ok ? "ok" : "fail"); + if (ok) diag_d.sended(ba.size_s()); + return ok; +} + + void PIPeer::sendMulticast(const PIByteArray & ba) { + //piCout << "send muticast ..."; piForeach (PIEthernet * e, mc_eths) { + if (e->name() == "no_send") continue; for (int p = _PIPEER_PORT_SYNC_START; p < _PIPEER_PORT_SYNC_END; ++p) { e->setSendPort(p); //errorClear(); - //piCout << "send to" << e->sendAddress() << e->send(ba); + //piCout << "send to" << e->path() << e->sendAddress();// << e->send(ba); //piCout << PIEthernet::ethErrorString(); e->send(ba); diag_s.sended(ba.size_s()); } } + //piCout << "send muticast ok"; } diff --git a/pipeer.h b/pipeer.h index 2c971a51..3caff714 100644 --- a/pipeer.h +++ b/pipeer.h @@ -1,3 +1,6 @@ +/*! \file pipeer.h + * \brief Peering net node +*/ /* PIP - Platform Independent Primitives Peer - named I/O ethernet node, forming self-organized peering network @@ -145,8 +148,9 @@ private: PIVector eths; PIVector mc_eths; + PIEthernet * eth_send; PITimer timer; - PIMutex mc_mutex; + PIMutex mc_mutex, eth_mutex; bool rec_mc, rec_bc; PeerInfo self_info; diff --git a/piprocess.h b/piprocess.h index a3ddf923..8498862e 100644 --- a/piprocess.h +++ b/piprocess.h @@ -1,3 +1,6 @@ +/*! \file piprocess.h + * \brief Process +*/ /* PIP - Platform Independent Primitives Process diff --git a/piprotocol.h b/piprotocol.h index 61163499..0c87fad1 100644 --- a/piprotocol.h +++ b/piprotocol.h @@ -1,3 +1,6 @@ +/*! \file piprotocol.h + * \brief Highly configurable from file device +*/ /* PIP - Platform Independent Primitives Protocol, input/output channel (COM, UDP) diff --git a/piserial.h b/piserial.h index dd0e9a7e..b87d02f9 100644 --- a/piserial.h +++ b/piserial.h @@ -1,3 +1,6 @@ +/*! \file piserial.h + * \brief Serial device +*/ /* PIP - Platform Independent Primitives COM diff --git a/pisignals.h b/pisignals.h index 3cd8c872..e6fcd0b5 100644 --- a/pisignals.h +++ b/pisignals.h @@ -1,3 +1,6 @@ +/*! \file pisignals.h + * \brief System signals +*/ /* PIP - Platform Independent Primitives Signals diff --git a/pistring.cpp b/pistring.cpp index d530390d..af153f39 100644 --- a/pistring.cpp +++ b/pistring.cpp @@ -249,10 +249,10 @@ PIString & PIString::cutMid(const int start, const int len) { PIString & PIString::trim() { int st = 0, fn = 0; for (int i = 0; i < length(); ++i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r') + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) {st = i; break;} for (int i = length() - 1; i >= 0; --i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r') + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) {fn = i; break;} *this = mid(st, fn - st + 1); return *this; @@ -262,10 +262,10 @@ PIString & PIString::trim() { PIString PIString::trimmed() const { int st = 0, fn = 0; for (int i = 0; i < length(); ++i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r') + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) {st = i; break;} for (int i = length() - 1; i >= 0; --i) - if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r') + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) {fn = i; break;} return mid(st, fn - st + 1); } diff --git a/pistring.h b/pistring.h index eca88141..ce76ed4b 100644 --- a/pistring.h +++ b/pistring.h @@ -676,7 +676,7 @@ inline PICout operator <<(PICout s, const PIString & v) {s.space(); s.quote(); s inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {int l = v.lengthAscii(); s << l; if (l <= 0) return s; int os = s.size_s(); s.enlarge(l); memcpy(s.data(os), v.data(), l); return s;} //! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {int l; s >> l; if (l <= 0) return s; v = PIString((const char * )s.data(), l); s.remove(0, l); return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {if (s.size() < 4) {v.clear(); return s;} int l; s >> l; if (l <= 0) return s; v = PIString((const char * )s.data(), l); s.remove(0, l); return s;} //! \relatesalso PIString \brief Return concatenated string diff --git a/pithread.cpp b/pithread.cpp index 9ff6b122..bd564e27 100644 --- a/pithread.cpp +++ b/pithread.cpp @@ -63,6 +63,7 @@ void piUSleep(int usecs) { PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay): PIObject() { piMonitor.threads++; + thread = 0; data_ = data; ret_func = func; running = lockRun = false; @@ -74,6 +75,7 @@ PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay) PIThread::PIThread(bool startNow, int timer_delay): PIObject() { piMonitor.threads++; + thread = 0; ret_func = 0; running = lockRun = false; priority_ = piNormal; @@ -84,7 +86,7 @@ PIThread::PIThread(bool startNow, int timer_delay): PIObject() { PIThread::~PIThread() { piMonitor.threads--; - if (!running) return; + if (!running || thread == 0) return; #ifndef WINDOWS pthread_cancel(thread); #else diff --git a/pitimer.cpp b/pitimer.cpp index 384e016d..aa391165 100644 --- a/pitimer.cpp +++ b/pitimer.cpp @@ -1,4 +1,4 @@ -/* +/*ccc PIP - Platform Independent Primitives Timer Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com @@ -20,6 +20,33 @@ #include "pitimer.h" #include "pisystemtests.h" + +/*! \class PITimer + * \brief Timer + * + * \section PITimer_sec0 Synopsis + * This class implements timer function. PIP timers supports 3 way to tick notify, + * frequency delimiters and time measurements. + * \section PITimer_sec1 Notify variants + * Notify variants: + * * "slot" - static function with format void func(void * data, int delimiter); + * * event - \a void timeout(void * data, int delimiter); + * * virtual function - \a void tick(void * data, int delimiter). + * All this variant are equivalent, use most applicable. + * \section PITimer_sec2 Frequency delimiters + * Frequency delimiter is an integer number and "slot" function. If "slot" function is null + * timer main "slot" will be used. Each delimiter numbers tick timer will be execute + * delimiters or timer main "slot" function with \b delimiter value = delimiter number. + * Example: \snippet pitimer.cpp delimiter + * \section PITimer_sec3 Time measurements + * PITimer can be used as time measurer. Function \a reset() set time mark to current + * system time, then functions double elapsed_*() returns time elapsed from this mark. + * These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m" + * and "s"; + * Example: \snippet pitimer.cpp elapsed +*/ + + bool operator ==(const PITime & t0, const PITime & t1) { return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds); } diff --git a/pitimer.h b/pitimer.h index 5fed2921..0b70d59f 100644 --- a/pitimer.h +++ b/pitimer.h @@ -1,3 +1,6 @@ +/*! \file pitimer.h + * \brief Timer +*/ /* PIP - Platform Independent Primitives Timer @@ -153,31 +156,38 @@ class PIP_EXPORT PITimer { PIOBJECT(PITimer) public: + + //! \brief Constructs timer with execution function \b slot and common data \b data. PITimer(TimerEvent slot = 0, void * data = 0, bool threaded = true); PITimer(bool threaded); virtual ~PITimer(); + + //! \brief Set custom data. void setData(void * data_) {data = data_;} + + //! \brief Set timer execution function. void setSlot(TimerEvent slot) {ret_func = slot;} + + //! \brief Returns current loop delay. double interval() const {return interval_;} -#ifndef PIP_TIMER_RT + + EVENT_HANDLER0(void, reset) { # ifdef WINDOWS - EVENT_HANDLER0(void, reset) {t_st = GetCurrentTime();} + t_st = GetCurrentTime(); # elif defined(MAC_OS) - EVENT_HANDLER0(void, reset) {clock_get_time(__pi_mac_clock, &t_st);} + clock_get_time(__pi_mac_clock, &t_st); # else - EVENT_HANDLER0(void, reset) {clock_gettime(0, &t_st);} + clock_gettime(0, &t_st); # endif - EVENT_HANDLER1(bool, start, int, timer_delay) {start(double(timer_delay)); return true;} + } + EVENT_HANDLER1(void, start, int, msecs) {start(double(msecs));} EVENT_HANDLER1(void, start, double, msecs); - EVENT_HANDLER0(void, stop) {running_ = false;} EVENT_HANDLER2(void, deferredStart, double, interval_msecs, double, delay_msecs); EVENT_HANDLER2(void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime); +#ifndef PIP_TIMER_RT + EVENT_HANDLER0(void, stop) {running_ = false; PIThread::stop();} #else - EVENT_HANDLER0(void, reset) {clock_gettime(0, &t_st);} - EVENT_HANDLER1(void, start, double, msecs); - EVENT_HANDLER2(void, deferredStart, double, interval_msecs, double, delay_msecs); - EVENT_HANDLER2(void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime); EVENT_HANDLER0(void, stop); EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);} EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs); @@ -186,9 +196,17 @@ public: EVENT_HANDLER0(void, lock) {mutex_.lock();} EVENT_HANDLER0(void, unlock) {mutex_.unlock();} #endif + + //! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot. void addDelimiter(int delim, TimerEvent slot = 0) {ret_funcs << TimerSlot(slot, delim);} + + //! \brief Remove all frequency delimiters \b delim. void removeDelimiter(int delim) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}} + + //! \brief Remove all frequency delimiters with slot \b slot. void removeDelimiter(TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot) {ret_funcs.remove(i); i--;}} + + //! \brief Remove all frequency delimiters \b delim with slot \b slot. void removeDelimiter(int delim, TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot && ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}} void setDelimiterValue(int delim, int value) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].delim == delim) ret_funcs[i].tick = value;} void setDelimiterValue(TimerEvent slot, int value) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot) ret_funcs[i].tick = value;} @@ -197,20 +215,40 @@ public: int delimiterValue(int delim, TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot && ret_funcs[i].delim == delim) return ret_funcs[i].tick; return -1;} EVENT_HANDLER0(void, clearDelimiters) {ret_funcs.clear();} + + //! \brief Returns nanoseconds elapsed from last \a reset() execution or from timer creation. double elapsed_n(); // nanoseconds + + //! \brief Returns microseconds elapsed from last \a reset() execution or from timer creation. double elapsed_u(); // microseconds + + //! \brief Returns milliseconds elapsed from last \a reset() execution or from timer creation. double elapsed_m(); // milliseconds + + //! \brief Returns seconds elapsed from last \a reset() execution or from timer creation. double elapsed_s(); // seconds + double reset_time_n(); // nanoseconds double reset_time_u(); // microseconds double reset_time_m(); // milliseconds double reset_time_s(); // seconds + + + //! \brief Returns time mark of last \a reset() execution or timer creation. PISystemTime reset_time(); + + //! \brief Returns nanoseconds representation of current system time. static double elapsed_system_n(); // nanoseconds + + //! \brief Returns microseconds representation of current system time. static double elapsed_system_u(); // microseconds + + //! \brief Returns milliseconds representation of current system time. static double elapsed_system_m(); // milliseconds + + //! \brief Returns seconds representation of current system time. static double elapsed_system_s(); // seconds @@ -244,7 +282,60 @@ public: EVENT2(timeout, void * , data, int, delimiter) +//! \handlers +//! \{ + + /** \fn void reset() + * \brief Set internal time mark to current system time + * \details This function used for set start time mark. Later + * you can find out elapsed time from this time mark to any + * moment of time with \a elapsed_s(), \a elapsed_m(), + * \a elapsed_u() or \a elapsed_n() function. + * \sa \a elapsed_s(), \a elapsed_m(), \a elapsed_u(), \a elapsed_n() */ + + /** \fn void start(int msecs) + * \brief Start timer with \b msecs loop delay + * \details Start execution of timer functions with frequency = 1 / msecs Hz. */ + + /** \fn void start(double msecs) + * \brief Start timer with \b msecs loop delay + * \details Start execution of timer functions with frequency = 1. / msecs Hz. + * Instead of \a start(int msecs) function this variant allow start timer + * with frequencies more than 1 kHz. */ + + //! \fn void stop() + //! \brief Stop timer + + /** \fn void deferredStart(double interval_msecs, double delay_msecs) + * \brief Start timer with \b interval_msecs loop delay after \b delay_msecs delay. + * \details Timer wait \b delay_msecs milliseconds and then normally starts with + * \b interval_msecs loop delay. + * \sa \a void start(double msecs), \a void deferredStart(double interval_msecs, const PIDateTime & start_datetime) */ + + /** \fn void deferredStart(double interval_msecs, const PIDateTime & start_datetime) + * \brief Start timer with \b interval_msecs loop delay after \b start_datetime date and time. + * \details Timer wait until \b start_datetime and then normally starts with + * \b interval_msecs loop delay. + * \sa \a void start(double msecs), \a void deferredStart(double interval_msecs, double delay_msecs) */ + + //! \fn void clearDelimiters() + //! \brief Remove all frequency delimiters. + +//! \} +//! \events +//! \{ + + /** \fn void timeout(void * data, int delimiter) + * \brief Raise on timer tick + * \details \b Data can be set with function \a setData(void * data) or from constructor. + * \b Delimiter if frequency delimiter, 1 for main loop. */ + + +//! \} + protected: + //! Virtual timer execution function, similar to "slot" or event \a void timeout(void * data, int delimiter). + //! By default is empty. virtual void tick(void * data, int delimiter) {;} private: diff --git a/piusb.h b/piusb.h index 5a61ace9..f04de800 100644 --- a/piusb.h +++ b/piusb.h @@ -1,3 +1,6 @@ +/*! \file piusb.h + * \brief USB device +*/ /* PIP - Platform Independent Primitives USB, based on libusb diff --git a/remote_console/main.cpp b/remote_console/main.cpp index faafff9b..39f97a2e 100644 --- a/remote_console/main.cpp +++ b/remote_console/main.cpp @@ -31,8 +31,6 @@ void key_event(char key, void * ) { if (ind < 0 || ind >= as.size_s()) return; selected = true; console.connectToServer(as[ind]); - console.clearScreen(); - piCout << "Connecting to" << console.selectedServer() << "..."; } int main(int argc, char * argv[]) { @@ -52,7 +50,7 @@ int main(int argc, char * argv[]) { } } if (!selected) return 0; - console.clearScreen(); + //console.clearScreen(); piCout << "Connecting to" << console.selectedServer() << "..."; while (!PIKbdListener::exiting) { msleep(20); diff --git a/serial.odg b/serial.odg deleted file mode 100644 index 97246b8a..00000000 Binary files a/serial.odg and /dev/null differ diff --git a/serial_.emf b/serial_.emf deleted file mode 100644 index 6ec3f2a6..00000000 Binary files a/serial_.emf and /dev/null differ diff --git a/serial_.odg b/serial_.odg deleted file mode 100644 index 9e2ecc01..00000000 Binary files a/serial_.odg and /dev/null differ diff --git a/serial_.svg b/serial_.svg deleted file mode 100644 index 30bae2a5..00000000 --- a/serial_.svg +++ /dev/null @@ -1,2 +0,0 @@ - -Данные**ЗаголовокПолезные данныеДанные**Заголовок следующего пакетаПакет принят верно (функция возврата возвратила истину)**ДанныеПакет принят неверно (функция возврата возвратила ложь)**Поиск заголовка в текущем пакете********* \ No newline at end of file