code format

This commit is contained in:
2022-12-14 14:13:52 +03:00
parent 430a41fefc
commit c2b8a8d6da
297 changed files with 27331 additions and 24162 deletions
+14 -15
View File
@@ -5,22 +5,22 @@
* \~russian Базовый класс для PICloudClient и PICloudServer
*/
/*
PIP - Platform Independent Primitives
PICloud Base - Base class for PICloudClient and PICloud Server
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PICloud Base - Base class for PICloudClient and PICloud Server
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICLOUDBASE_H
@@ -31,8 +31,7 @@
#include "pistreampacker.h"
class PIP_CLOUD_EXPORT PICloudBase
{
class PIP_CLOUD_EXPORT PICloudBase {
public:
PICloudBase();
+20 -19
View File
@@ -5,22 +5,22 @@
* \~russian Клиент PICloud
*/
/*
PIP - Platform Independent Primitives
PICloud Client
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PICloud Client
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICLOUDCLIENT_H
@@ -32,17 +32,19 @@
//! \brief PICloudClient
class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase
{
class PIP_CLOUD_EXPORT PICloudClient
: public PIIODevice
, public PICloudBase {
PIIODEVICE(PICloudClient, "");
public:
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudClient();
void setServerName(const PIString & server_name);
void setKeepConnection(bool on);
bool isConnected() const {return is_connected;}
ssize_t bytesAvailable() const override {return buff.size();}
bool isConnected() const { return is_connected; }
ssize_t bytesAvailable() const override { return buff.size(); }
void interrupt() override;
EVENT(connected);
@@ -53,7 +55,7 @@ protected:
bool closeDevice() override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
private:
EVENT_HANDLER1(void, _readed, PIByteArray &, data);
@@ -66,7 +68,6 @@ private:
PIConditionVariable cond_connect;
std::atomic_bool is_connected;
std::atomic_bool is_deleted;
};
#endif // PICLOUDCLIENT_H
+14 -14
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Cloud Cloud
//! \~\brief
@@ -51,8 +51,8 @@
#ifndef PICLOUDMODULE_H
#define PICLOUDMODULE_H
#include "picloudtcp.h"
#include "picloudclient.h"
#include "picloudserver.h"
#include "picloudtcp.h"
#endif // PICLOUDMODULE_H
+23 -19
View File
@@ -5,22 +5,22 @@
* \~russian Сервер PICloud
*/
/*
PIP - Platform Independent Primitives
PICloud Server
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PICloud Server
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICLOUDSERVER_H
@@ -30,27 +30,31 @@
#include "piconditionvar.h"
class PIP_CLOUD_EXPORT PICloudServer: public PIIODevice, public PICloudBase
{
class PIP_CLOUD_EXPORT PICloudServer
: public PIIODevice
, public PICloudBase {
PIIODEVICE(PICloudServer, "");
public:
//! PICloudServer
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudServer();
class Client : public PIIODevice {
class Client: public PIIODevice {
PIIODEVICE(PICloudServer::Client, "");
friend class PICloudServer;
public:
Client(PICloudServer * srv = nullptr, uint id = 0);
virtual ~Client();
protected:
bool openDevice() override;
bool closeDevice() override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
ssize_t bytesAvailable() const override {return buff.size();}
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
ssize_t bytesAvailable() const override { return buff.size(); }
void interrupt() override;
private:
@@ -67,7 +71,7 @@ public:
PIVector<PICloudServer::Client *> clients() const;
EVENT1(newConnection, PICloudServer::Client * , client);
EVENT1(newConnection, PICloudServer::Client *, client);
protected:
bool openDevice() override;
+24 -26
View File
@@ -5,30 +5,30 @@
* \~russian TCP слой PICloud
*/
/*
PIP - Platform Independent Primitives
PICloud TCP transport
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PICloud TCP transport
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICLOUDTCP_H
#define PICLOUDTCP_H
#include "pimutex.h"
#include "pip_cloud_export.h"
#include "pistring.h"
#include "pimutex.h"
class PIEthernet;
@@ -37,7 +37,6 @@ class PIStreamPacker;
namespace PICloud {
class PIP_CLOUD_EXPORT TCP {
public:
enum Version {
@@ -47,21 +46,21 @@ public:
enum Role {
InvalidRole = 0,
Server = 1,
Client = 2,
Server = 1,
Client = 2,
};
enum Type {
InvalidType = 0,
Connect = 1,
Disconnect = 2,
Data = 3,
Ping = 4,
Connect = 1,
Disconnect = 2,
Data = 3,
Ping = 4,
};
TCP(PIStreamPacker * s);
void setRole(Role r);
Role role() const {return (Role)header.role;}
Role role() const { return (Role)header.role; }
void setServerName(const PIString & server_name_);
PIString serverName() const;
@@ -82,8 +81,8 @@ private:
struct Header {
Header();
uchar version; // PICloud::Version
uchar type; // PICloud::Type
uchar role; // PICloud::Role
uchar type; // PICloud::Type
uchar role; // PICloud::Role
};
Header header;
@@ -91,9 +90,8 @@ private:
PIString server_name;
PIStreamPacker * streampacker;
PIMutex mutex_send;
};
}
} // namespace PICloud
#endif // PICLOUDTCP_H
+23 -23
View File
@@ -1,52 +1,52 @@
/*
PIP - Platform Independent Primitives
C++ code info structs
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
C++ code info structs
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picodeinfo.h"
#include "pivariant.h"
PIString PICodeInfo::EnumInfo::memberName(int value_) const {
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
if (e.value == value_)
return e.name.toString();
piForeachC(PICodeInfo::EnumeratorInfo & e, members)
if (e.value == value_) return e.name.toString();
return PIString();
}
int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const {
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
if (e.name.toString() == name_)
return e.value;
piForeachC(PICodeInfo::EnumeratorInfo & e, members)
if (e.name.toString() == name_) return e.value;
return -1;
}
PIVariantTypes::Enum PICodeInfo::EnumInfo::toPIVariantEnum() {
PIVariantTypes::Enum en(name.toString());
for (auto m: members) en << m.toPIVariantEnumerator();
for (auto m: members)
en << m.toPIVariantEnumerator();
if (!en.isEmpty()) en.selectValue(members.front().value);
return en;
}
PIMap<PIConstChars, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
PIMap<PIConstChars, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;
PIMap<PIConstChars, PICodeInfo::ClassInfo *> * PICodeInfo::classesInfo;
PIMap<PIConstChars, PICodeInfo::EnumInfo *> * PICodeInfo::enumsInfo;
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions;
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * PICodeInfo::accessTypeFunctions;
@@ -55,7 +55,7 @@ bool __PICodeInfoInitializer__::_inited_ = false;
PIVariant PICodeInfo::getMemberAsVariant(const void * p, const char * class_name, const char * member_name) {
if (!p || !class_name || !member_name || !accessTypeFunctions || !accessValueFunctions) return PIVariant();
AccessTypeFunction atf = accessTypeFunctions->value(class_name, (AccessTypeFunction)0);
AccessTypeFunction atf = accessTypeFunctions->value(class_name, (AccessTypeFunction)0);
AccessValueFunction avf = accessValueFunctions->value(class_name, (AccessValueFunction)0);
if (!atf || !avf) return PIVariant();
return PIVariant::fromValue(avf(p, member_name), PIStringAscii(atf(member_name)));
+68 -53
View File
@@ -5,22 +5,22 @@
* \~russian Структуры для C++ кода. Подробнее \ref code_model.
*/
/*
PIP - Platform Independent Primitives
C++ code info structs
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
C++ code info structs
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -45,29 +45,34 @@ namespace PICodeInfo {
//! Модификаторы типа
enum TypeFlag {
NoFlag,
Const /** const */ = 0x01,
Static /** static */ = 0x02,
Mutable /** mutable */ = 0x04,
Const /** const */ = 0x01,
Static /** static */ = 0x02,
Mutable /** mutable */ = 0x04,
Volatile /** volatile */ = 0x08,
Inline /** inline */ = 0x10,
Virtual /** virtual */ = 0x20,
Extern /** extern */ = 0x40
Inline /** inline */ = 0x10,
Virtual /** virtual */ = 0x20,
Extern /** extern */ = 0x40
};
typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
typedef PIMap<PIString, PIString> MetaMap;
typedef PIByteArray(*AccessValueFunction)(const void *, const char *);
typedef const char*(*AccessTypeFunction)(const char *);
typedef PIByteArray (*AccessValueFunction)(const void *, const char *);
typedef const char * (*AccessTypeFunction)(const char *);
//! \~english Type information
//! \~russian Информация о типе
struct PIP_EXPORT TypeInfo {
TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {name = n; type = t; flags = f; bits = b;}
TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {
name = n;
type = t;
flags = f;
bits = b;
}
//! \~english Returns if variable if bitfield
//! \~russian Возвращает битовым ли полем является переменная
bool isBitfield() const {return bits > 0;}
bool isBitfield() const { return bits > 0; }
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
@@ -94,7 +99,6 @@ struct PIP_EXPORT TypeInfo {
//! \~english Method information
//! \~russian Информация о методе
struct PIP_EXPORT FunctionInfo {
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
MetaMap meta;
@@ -116,7 +120,7 @@ struct PIP_EXPORT FunctionInfo {
//! \~english Class or struct information
//! \~russian Информация о классе или структуре
struct PIP_EXPORT ClassInfo {
ClassInfo() {has_name = true;}
ClassInfo() { has_name = true; }
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
@@ -148,15 +152,18 @@ struct PIP_EXPORT ClassInfo {
//! \~english Subclass list
//! \~russian Список наследников
PIVector<PICodeInfo::ClassInfo * > children_info;
PIVector<PICodeInfo::ClassInfo *> children_info;
};
//! \~english Enumerator information
//! \~russian Информация об элементе перечисления
struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {name = n; value = v;}
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name.toString());}
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {
name = n;
value = v;
}
PIVariantTypes::Enumerator toPIVariantEnumerator() { return PIVariantTypes::Enumerator(value, name.toString()); }
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
@@ -175,7 +182,6 @@ struct PIP_EXPORT EnumeratorInfo {
//! \~english Enum information
//! \~russian Информация о перечислении
struct PIP_EXPORT EnumInfo {
//! \~english Returns member name with value "value"
//! \~russian Возвращает имя элемента со значением "value"
PIString memberName(int value) const;
@@ -202,7 +208,7 @@ struct PIP_EXPORT EnumInfo {
};
inline PICout operator <<(PICout s, const PICodeInfo::TypeInfo & v) {
inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
if (v.flags[Inline]) s << "inline ";
if (v.flags[Virtual]) s << "virtual ";
if (v.flags[Mutable]) s << "mutable ";
@@ -210,22 +216,26 @@ inline PICout operator <<(PICout s, const PICodeInfo::TypeInfo & v) {
if (v.flags[Static]) s << "static ";
if (v.flags[Const]) s << "const ";
s << v.type;
if (!v.name.isEmpty())
s << " " << v.name;
if (!v.name.isEmpty()) s << " " << v.name;
return s;
}
inline PICout operator <<(PICout s, const PICodeInfo::EnumeratorInfo & v) {s << v.name << " = " << v.value << " Meta" << v.meta; return s;}
inline PICout operator<<(PICout s, const PICodeInfo::EnumeratorInfo & v) {
s << v.name << " = " << v.value << " Meta" << v.meta;
return s;
}
inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
s.saveAndSetControls(0);
s << "class " << v.name;
if (!v.parents.isEmpty()) {
s << ": ";
bool first = true;
for (const auto & i: v.parents) {
if (first) first = false;
else s << ", ";
if (first)
first = false;
else
s << ", ";
s << i;
}
}
@@ -234,14 +244,15 @@ inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
s << PICoutManipulators::Tab << i.return_type << " " << i.name << "(";
bool fa = true;
for (const auto & a: i.arguments) {
if (fa) fa = false;
else s << ", ";
if (fa)
fa = false;
else
s << ", ";
s << a;
}
s << ") Meta" << i.meta << ";\n";
}
if (!v.functions.isEmpty() && !v.variables.isEmpty())
s << "\n";
if (!v.functions.isEmpty() && !v.variables.isEmpty()) s << "\n";
for (const auto & i: v.variables) {
s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n";
}
@@ -250,13 +261,15 @@ inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
return s;
}
inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) {
s.saveAndSetControls(0);
s << "enum " << v.name << " Meta" << v.meta << " {\n";
for (const auto & i: v.members) {
bool f = true;
if (f) f = false;
else s << ", ";
if (f)
f = false;
else
s << ", ";
s << PICoutManipulators::Tab << i << "\n";
}
s << "}\n";
@@ -267,11 +280,11 @@ inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
//! \~english Pointer to single storage of PICodeInfo::ClassInfo, access by name
//! \~russian Указатель на единое хренилище PICodeInfo::ClassInfo, доступ по имени
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::ClassInfo * > * classesInfo;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::ClassInfo *> * classesInfo;
//! \~english Pointer to single storage of PICodeInfo::EnumInfo, access by name
//! \~russian Указатель на единое хренилище PICodeInfo::EnumInfo, доступ по имени
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::EnumInfo * > * enumsInfo;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
@@ -294,23 +307,25 @@ inline const char * getMemberType(const char * class_name, const char * member_n
PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name);
template<typename T, typename std::enable_if< std::is_assignable<T&, const T&>::value, int>::type = 0>
void serialize(PIByteArray & ret, const T & v) {ret << v;}
template<typename T, typename std::enable_if<std::is_assignable<T &, const T &>::value, int>::type = 0>
void serialize(PIByteArray & ret, const T & v) {
ret << v;
}
template<typename T, typename std::enable_if<!std::is_assignable<T&, const T&>::value, int>::type = 0>
template<typename T, typename std::enable_if<!std::is_assignable<T &, const T &>::value, int>::type = 0>
void serialize(PIByteArray & ret, const T & v) {}
}
} // namespace PICodeInfo
class PIP_EXPORT __PICodeInfoInitializer__ {
public:
__PICodeInfoInitializer__() {
if (_inited_) return;
_inited_ = true;
PICodeInfo::classesInfo = new PIMap<PIConstChars, PICodeInfo::ClassInfo * >;
PICodeInfo::enumsInfo = new PIMap<PIConstChars, PICodeInfo::EnumInfo * >;
_inited_ = true;
PICodeInfo::classesInfo = new PIMap<PIConstChars, PICodeInfo::ClassInfo *>;
PICodeInfo::enumsInfo = new PIMap<PIConstChars, PICodeInfo::EnumInfo *>;
PICodeInfo::accessValueFunctions = new PIMap<PIConstChars, PICodeInfo::AccessValueFunction>;
PICodeInfo::accessTypeFunctions = new PIMap<PIConstChars, PICodeInfo::AccessTypeFunction>;
PICodeInfo::accessTypeFunctions = new PIMap<PIConstChars, PICodeInfo::AccessTypeFunction>;
}
static bool _inited_;
};
+13 -13
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Code Code
//! \~\brief
+474 -262
View File
@@ -1,26 +1,25 @@
/*
PIP - Platform Independent Primitives
C++ code parser
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
C++ code parser
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picodeparser.h"
PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
PIStringList arg_vals;
while (!args_.isEmpty()) {
@@ -32,29 +31,32 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
PIString ca;
if (bi >= 0 && bi < ci) {
ca = args_.left(args_.takeLeft(bi).toInt());
ci -= ca.size_s(); bi -= ca.size_s();
ci -= ca.size_s();
bi -= ca.size_s();
ca += '(' + args_.takeRange('(', ')') + ')';
} else {
ca = args_.takeLeft(ci);
}
arg_vals << ca;
args_.trim(); args_.takeLeft(1); args_.trim();
args_.trim();
args_.takeLeft(1);
args_.trim();
}
if (args.size() != arg_vals.size()) {
piCout << ("Error: in expansion of macro \"" + name + '(' + args.join(", ") + ")\": expect")
<< args.size() << "arguments but takes" << arg_vals.size() << "!";
piCout << ("Error: in expansion of macro \"" + name + '(' + args.join(", ") + ")\": expect") << args.size() << "arguments but takes"
<< arg_vals.size() << "!";
if (ok != 0) *ok = false;
return PIString();
}
PIString ret = value;
for (int i = 0; i < args.size_s(); ++i) {
const PIString & an(args[i]), av(arg_vals[i]);
const PIString &an(args[i]), av(arg_vals[i]);
int ind(-1);
while ((ind = ret.find(an, ind + 1)) >= 0) {
PIChar ppc, pc, nc;
if (ind > 1) ppc = ret[ind - 2];
if (ind > 0) pc = ret[ind - 1];
if (ind + an.size_s() < ret.size_s()) nc = ret.mid(ind + an.size_s(),1)[0];
if (ind + an.size_s() < ret.size_s()) nc = ret.mid(ind + an.size_s(), 1)[0];
if (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars
ind--;
ret.replace(ind, an.size_s() + 1, '\"' + av + '\"');
@@ -72,9 +74,8 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
}
PICodeParser::PICodeParser() {
macros_iter = 32;
macros_iter = 32;
with_includes = true;
clear();
includes << "";
@@ -86,62 +87,61 @@ void PICodeParser::parseFile(const PIString & file, bool follow_includes) {
parseFileInternal(file, follow_includes);
/*piCout << "\n\n";
piForeachC (Entity * c, entities) {
piCout << "";
piCout << c->type << c->name << c->parent_scope << c->parents << c->children << c->meta;
if (c->parent_scope)
piCout << "parent" << c->parent_scope->name;
piCout << "Functions:";
piForeachC (Member & m, c->functions)
piCout << m.type << m.name << m.meta;
piCout << "Members:";
piForeachC (Member & m, c->members)
piCout << m.type << m.name << m.meta;
piCout << "";
piCout << c->type << c->name << c->parent_scope << c->parents << c->children << c->meta;
if (c->parent_scope)
piCout << "parent" << c->parent_scope->name;
piCout << "Functions:";
piForeachC (Member & m, c->functions)
piCout << m.type << m.name << m.meta;
piCout << "Members:";
piForeachC (Member & m, c->members)
piCout << m.type << m.name << m.meta;
}
piCout << "\n\nDefines:";
piForeachC (Define & m, defines)
piCout << PIStringAscii("define") << m.first << m.second;
piCout << PIStringAscii("define") << m.first << m.second;
piCout << "\n\nMacros:";
piForeachC (Macro & m, macros)
piCout << "Macro:" << m.name << m.args << m.value;
piCout << "Macro:" << m.name << m.args << m.value;
piCout << "\n\nClasses:";
piCout << "\n\nEnums:";
piForeachC (Enum & c, enums) {
piCout << PIStringAscii("enum") << c.name << c.meta;
piForeachC (EnumeratorInfo & e, c.members)
piCout << " " << e.name << '=' << e.value << e.meta;
piCout << PIStringAscii("enum") << c.name << c.meta;
piForeachC (EnumeratorInfo & e, c.members)
piCout << " " << e.name << '=' << e.value << e.meta;
}
piCout << "\n\nTypedefs:";
piForeachC (Typedef & c, typedefs)
piCout << PIStringAscii("typedef") << c;*/
piCout << PIStringAscii("typedef") << c;*/
}
void PICodeParser::parseFiles(const PIStringList & files, bool follow_includes) {
clear();
piForeachC (PIString & f, files)
piForeachC(PIString & f, files)
parseFileInternal(f, follow_includes);
/*piCout << "\n\nDefines:";
piForeachC (Define & m, defines)
piCout << PIStringAscii("define") << m.first << m.second;
piCout << PIStringAscii("define") << m.first << m.second;
piCout << "\n\nMacros:";
piForeachC (Macro & m, macros)
piCout << "Macro:" << m.name << m.args << m.value;
piCout << "Macro:" << m.name << m.args << m.value;
piCout << "\n\nClasses:";
piForeachC (Entity * c, entities)
piCout << PIStringAscii("class") << c->name << c->parents;
piCout << PIStringAscii("class") << c->name << c->parents;
piCout << "\n\nEnums:";
piForeachC (Enum & c, enums)
piCout << PIStringAscii("enum") << c.name << c.members;
piCout << PIStringAscii("enum") << c.name << c.members;
piCout << "\n\nTypedefs:";
piForeachC (Typedef & c, typedefs)
piCout << PIStringAscii("typedef") << c;*/
piCout << PIStringAscii("typedef") << c;*/
}
bool PICodeParser::isEnum(const PIString & name) {
piForeachC (Enum & e, enums)
if (e.name == name)
return true;
piForeachC(Enum & e, enums)
if (e.name == name) return true;
return false;
}
@@ -149,19 +149,19 @@ bool PICodeParser::isEnum(const PIString & name) {
bool PICodeParser::parseFileInternal(const PIString & file, bool follow_includes) {
if (proc_files[file]) return true;
with_includes = follow_includes;
cur_file = file;
cur_file = file;
PIFile f(file, PIIODevice::ReadOnly);
int ii = 0;
while (!f.isOpened() && ii < (includes.size_s() - 1)) {
f.setPath(includes[++ii] + '/' + file);
//piCout << "try" << f.path();
// piCout << "try" << f.path();
f.open(PIIODevice::ReadOnly);
}
if (!f.isOpened()) {
piCout << ("Error: can`t open file \"" + file + "\"!");
return false;
}
//piCout << "add" << file;
// piCout << "add" << file;
proc_files << f.path();
PIString fc = PIString::fromUTF8(f.readAll());
piCout << "parsing" << f.path() << "...";
@@ -174,7 +174,8 @@ bool PICodeParser::parseFileInternal(const PIString & file, bool follow_includes
void PICodeParser::clear() {
piForeach (Entity * i, entities) delete i;
piForeach(Entity * i, entities)
delete i;
defines.clear();
macros.clear();
enums.clear();
@@ -184,40 +185,145 @@ void PICodeParser::clear() {
cur_namespace.clear();
main_file.clear();
evaluator.clearCustomVariables();
cur_def_vis = Global;
anon_num = 0;
cur_def_vis = Global;
anon_num = 0;
PIStringList defs = PIStringAscii(PICODE_DEFINES).split(",");
piForeachC (PIString & d, defs)
piForeachC(PIString & d, defs)
defines << Define(d, "");
defines << Define(PIStringAscii("PICODE"), "") << custom_defines;
macros << Macro(PIStringAscii("PIOBJECT"), "", PIStringList() << "name")
<< Macro(PIStringAscii("PIOBJECT_PARENT"), "", PIStringList() << "parent")
<< Macro(PIStringAscii("PIOBJECT_SUBCLASS"), "", PIStringList() << "name" << "parent")
<< Macro(PIStringAscii("PIOBJECT_SUBCLASS"),
"",
PIStringList() << "name"
<< "parent")
<< Macro(PIStringAscii("PIIODEVICE"), "", PIStringList() << "name")
<< Macro(PIStringAscii("NO_COPY_CLASS"), "", PIStringList() << "name")
<< Macro(PIStringAscii("PRIVATE_DECLARATION"))
<< Macro(PIStringAscii("NO_COPY_CLASS"), "", PIStringList() << "name") << Macro(PIStringAscii("PRIVATE_DECLARATION"))
<< Macro(PIStringAscii("EVENT" ), "void name();", PIStringList() << "name")
<< Macro(PIStringAscii("EVENT"), "void name();", PIStringList() << "name")
<< Macro(PIStringAscii("EVENT0"), "void name();", PIStringList() << "name")
<< Macro(PIStringAscii("EVENT1"), "void name(a0 n0);", PIStringList() << "name" << "a0" << "n0")
<< Macro(PIStringAscii("EVENT2"), "void name(a0 n0, a1 n1);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1")
<< Macro(PIStringAscii("EVENT3"), "void name(a0 n0, a1 n1, a2 n2);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
<< Macro(PIStringAscii("EVENT4"), "void name(a0 n0, a1 n1, a2 n2, a3 n3);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
<< Macro(PIStringAscii("EVENT1"),
"void name(a0 n0);",
PIStringList() << "name"
<< "a0"
<< "n0")
<< Macro(PIStringAscii("EVENT2"),
"void name(a0 n0, a1 n1);",
PIStringList() << "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1")
<< Macro(PIStringAscii("EVENT3"),
"void name(a0 n0, a1 n1, a2 n2);",
PIStringList() << "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1"
<< "a2"
<< "n2")
<< Macro(PIStringAscii("EVENT4"),
"void name(a0 n0, a1 n1, a2 n2, a3 n3);",
PIStringList() << "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1"
<< "a2"
<< "n2"
<< "a3"
<< "n3")
<< Macro(PIStringAscii("EVENT_HANDLER" ), "ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_HANDLER0"), "ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_HANDLER1"), "ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
<< Macro(PIStringAscii("EVENT_HANDLER2"), "ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
<< Macro(PIStringAscii("EVENT_HANDLER3"), "ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
<< Macro(PIStringAscii("EVENT_HANDLER4"), "ret name(a0 n0, a1 n1, a2 n2, a3 n3)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
<< Macro(PIStringAscii("EVENT_HANDLER"),
"ret name()",
PIStringList() << "ret"
<< "name")
<< Macro(PIStringAscii("EVENT_HANDLER0"),
"ret name()",
PIStringList() << "ret"
<< "name")
<< Macro(PIStringAscii("EVENT_HANDLER1"),
"ret name(a0 n0)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0")
<< Macro(PIStringAscii("EVENT_HANDLER2"),
"ret name(a0 n0, a1 n1)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1")
<< Macro(PIStringAscii("EVENT_HANDLER3"),
"ret name(a0 n0, a1 n1, a2 n2)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1"
<< "a2"
<< "n2")
<< Macro(PIStringAscii("EVENT_HANDLER4"),
"ret name(a0 n0, a1 n1, a2 n2, a3 n3)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1"
<< "a2"
<< "n2"
<< "a3"
<< "n3")
<< Macro(PIStringAscii("EVENT_VHANDLER" ), "virtual ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_VHANDLER0"), "virtual ret name()", PIStringList() << "ret" << "name")
<< Macro(PIStringAscii("EVENT_VHANDLER1"), "virtual ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
<< Macro(PIStringAscii("EVENT_VHANDLER2"), "virtual ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
<< Macro(PIStringAscii("EVENT_VHANDLER3"), "virtual ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
<< Macro(PIStringAscii("EVENT_VHANDLER4"), "virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
;
<< Macro(PIStringAscii("EVENT_VHANDLER"),
"virtual ret name()",
PIStringList() << "ret"
<< "name")
<< Macro(PIStringAscii("EVENT_VHANDLER0"),
"virtual ret name()",
PIStringList() << "ret"
<< "name")
<< Macro(PIStringAscii("EVENT_VHANDLER1"),
"virtual ret name(a0 n0)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0")
<< Macro(PIStringAscii("EVENT_VHANDLER2"),
"virtual ret name(a0 n0, a1 n1)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1")
<< Macro(PIStringAscii("EVENT_VHANDLER3"),
"virtual ret name(a0 n0, a1 n1, a2 n2)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1"
<< "a2"
<< "n2")
<< Macro(PIStringAscii("EVENT_VHANDLER4"),
"virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)",
PIStringList() << "ret"
<< "name"
<< "a0"
<< "n0"
<< "a1"
<< "n1"
<< "a2"
<< "n2"
<< "a3"
<< "n3");
}
@@ -238,7 +344,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
char c = 0, pc = 0;
PIString pfc, line, ccmn, tmp;
PIMap<PIString, PIString> cchars;
/// Remove comments, join multiline '*' and replace '*' to $n (cchars)
fc.replaceAll("\r\n", '\n');
fc.replaceAll('\r', '\n');
@@ -247,7 +353,8 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
if (i > 0) pc = c;
c = fc[i].toAscii();
if (c == '"' && !mlc && pc != '\'') {
if (i > 0) if (fc[i - 1] == '\\') continue;
if (i > 0)
if (fc[i - 1] == '\\') continue;
cc = !cc;
continue;
}
@@ -258,46 +365,62 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
continue;
}
if (cc) continue;
if (fc.mid(i, 2) == "/*") {mlc = true; mls = i; ++i; continue;}
if (fc.mid(i, 2) == "*/" && mlc) {mlc = false; fc.cutMid(mls, i - mls + 2); i = mls - 1; continue;}
if (fc.mid(i, 2) == "//" && !mlc) {ole = fc.find('\n', i); fc.cutMid(i, ole < 0 ? -1 : ole - i); --i; continue;}
if (fc.mid(i, 2) == "/*") {
mlc = true;
mls = i;
++i;
continue;
}
if (fc.mid(i, 2) == "*/" && mlc) {
mlc = false;
fc.cutMid(mls, i - mls + 2);
i = mls - 1;
continue;
}
if (fc.mid(i, 2) == "//" && !mlc) {
ole = fc.find('\n', i);
fc.cutMid(i, ole < 0 ? -1 : ole - i);
--i;
continue;
}
}
pfc = procMacros(fc);
if (main) return true;
bool replaced = true;
bool replaced = true;
int replaced_cnt = 0;
while (replaced) {
//piCout << "MACRO iter" << replaced_cnt;
// piCout << "MACRO iter" << replaced_cnt;
if (replaced_cnt >= macros_iter) {
piCout << "Error: recursive macros detected!";
break;//return false;
break; // return false;
}
replaced_cnt++;
replaced = false;
piForeachC (Define & d, defines) {
piForeachC(Define & d, defines) {
int ind(-1);
while ((ind = pfc.find(d.first, ind + 1)) >= 0) {
PIChar pc, nc;
if (ind > 0) pc = pfc[ind - 1];
if (ind + d.first.size_s() < pfc.size_s()) nc = pfc.mid(ind + d.first.size_s(),1)[0];
if (ind + d.first.size_s() < pfc.size_s()) nc = pfc.mid(ind + d.first.size_s(), 1)[0];
if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue;
pfc.replace(ind, d.first.size_s(), d.second);
ind -= d.first.size_s() - d.second.size_s();
replaced = true;
}
}
piForeachC (Macro & m, macros) {
piForeachC(Macro & m, macros) {
int ind(-1);
while ((ind = pfc.find(m.name, ind + 1)) >= 0) {
PIChar pc, nc;
if (ind > 0) pc = pfc[ind - 1];
if (ind + m.name.size_s() < pfc.size_s()) nc = pfc.mid(ind + m.name.size_s(),1)[0];
if (ind + m.name.size_s() < pfc.size_s()) nc = pfc.mid(ind + m.name.size_s(), 1)[0];
if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue;
PIString ret, range; bool ok(false);
PIString ret, range;
bool ok(false);
range = pfc.mid(ind + m.name.size_s()).takeRange('(', ')');
ret = m.expand(range, &ok);
ret = m.expand(range, &ok);
if (!ok) return false;
int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind;
pfc.replace(ind, rlen, ret);
@@ -308,9 +431,9 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
}
replaceMeta(pfc);
//piCout << PICoutManipulators::NewLine << "file" << cur_file << pfc;
int pl = -1;
// piCout << PICoutManipulators::NewLine << "file" << cur_file << pfc;
int pl = -1;
cur_def_vis = Global;
while (!pfc.isEmpty()) {
pfc.trim();
@@ -331,14 +454,22 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
pfc.takeRange('<', '>');
bool def = !isDeclaration(pfc, 0, &end);
pfc.cutLeft(end);
if (def) pfc.takeRange('{', '}');
else pfc.takeSymbol();
if (def)
pfc.takeRange('{', '}');
else
pfc.takeSymbol();
continue;
}
if (pfc.left(5) == s_class || pfc.left(6) == s_struct || pfc.left(5) == s_union) {
int dind = pfc.find('{', 0), find = pfc.find(';', 0);
if (dind < 0 && find < 0) {pfc.cutLeft(6); continue;}
if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;}
if (dind < 0 && find < 0) {
pfc.cutLeft(6);
continue;
}
if (dind < 0 || find < dind) {
pfc.cutLeft(6);
continue;
}
ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
pfc.remove(0, ccmn.size());
parseClass(0, ccmn, false);
@@ -356,8 +487,10 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
if (pfc.left(7) == s_typedef) {
pfc.cutLeft(7);
typedefs << parseTypedef(pfc.takeLeft(pfc.find(';')));
if (typedefs.back().first.isEmpty()) typedefs.pop_back();
else root_.typedefs << typedefs.back();
if (typedefs.back().first.isEmpty())
typedefs.pop_back();
else
root_.typedefs << typedefs.back();
pfc.takeSymbol();
continue;
}
@@ -375,7 +508,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
}
parseMember(&root_, str);
}
return true;
}
@@ -384,45 +517,49 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
static const PIString s_ss = PIStringAscii(" ");
static const PIString s_M = PIStringAscii("$M");
static const PIString s_class = PIStringAscii("class");
PIString cd = fc.trimmed().removeAll('\n').replaceAll('\t', ' ').replaceAll(s_ss, ' '), pn;
PIString cd = fc.trimmed().removeAll('\n').replaceAll('\t', ' ').replaceAll(s_ss, ' '), pn;
MetaMap meta;
int ind = cd.find(s_M);
if (ind >= 0) {
meta = tmp_meta.value(cd.takeMid(ind, 5));
cd.replaceAll(s_ss, ' ');
}
//piCout << "found class <****\n" << cd << "\n****>";
// piCout << "found class <****\n" << cd << "\n****>";
ind = cd.find(':');
PIVector<Entity * > parents;
PIVector<Entity *> parents;
if (ind > 0) {
PIStringList pl = cd.takeMid(ind + 1).trim().split(',');
cd.cutRight(1);
Entity * pe = 0;
piForeachC (PIString & p, pl) {
if (p.contains(' ')) pn = p.mid(p.find(' ') + 1);
else pn = p;
piForeachC(PIString & p, pl) {
if (p.contains(' '))
pn = p.mid(p.find(' ') + 1);
else
pn = p;
pe = findEntityByName(pn);
if (pe == 0) ;//{piCout << "Error: can`t find" << pn;}
else parents << pe;
if (pe == 0)
; //{piCout << "Error: can`t find" << pn;}
else
parents << pe;
}
}
PIString typename_ = cd.left(6).trim();
bool is_class = typename_ == s_class;
Visibility vis = cur_def_vis;
cur_def_vis = (is_class ? Private : Public);
PIString cn = cd.mid(6).trim();
bool has_name = !cn.isEmpty();
bool is_class = typename_ == s_class;
Visibility vis = cur_def_vis;
cur_def_vis = (is_class ? Private : Public);
PIString cn = cd.mid(6).trim();
bool has_name = !cn.isEmpty();
if (cn.isEmpty()) cn = PIStringAscii("<unnamed_") + PIString::fromNumber(anon_num++) + '>';
//piCout << "found " << typename_ << cn;
// piCout << "found " << typename_ << cn;
if (cn.isEmpty()) return 0;
Entity * e = new Entity();
e->meta = meta;
e->name = cur_namespace + cn;
e->type = typename_;
e->has_name = has_name;
e->parents = parents;
Entity * e = new Entity();
e->meta = meta;
e->name = cur_namespace + cn;
e->type = typename_;
e->has_name = has_name;
e->parents = parents;
e->visibility = vis;
e->file = cur_file;
e->file = cur_file;
entities << e;
return e;
}
@@ -441,37 +578,49 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
static const PIString s_typedef = PIStringAscii("typedef");
static const PIString s_namespace = PIStringAscii("namespace");
static const PIString s_template = PIStringAscii("template");
Visibility prev_vis = cur_def_vis;
Visibility prev_vis = cur_def_vis;
int dind = fc.find('{'), find = fc.find(';'), end = 0;
if (dind < 0 && find < 0) return;
if (dind < 0 || find < dind) {
fc.left(find);
return;
}
//piCout << "parse class <****\n" << fc << "\n****>";
// piCout << "parse class <****\n" << fc << "\n****>";
Entity * ce = parent;
if (!is_namespace) {
ce = parseClassDeclaration(fc.takeLeft(dind));
fc.trim().cutLeft(1).cutRight(1).trim();
}
//piCout << "found class <****\n" << fc << "\n****>";
///if (!ce) return PIString();
// piCout << "found class <****\n" << fc << "\n****>";
/// if (!ce) return PIString();
if (ce) {
if (parent) parent->children << ce;
ce->parent_scope = parent;
}
int ps = -1;
bool def = false;
int ps = -1;
bool def = false;
PIString prev_namespace = cur_namespace, stmp;
if (ce) cur_namespace += ce->name + s_ns;
//piCout << "parse class" << ce->name << "namespace" << cur_namespace;
//piCout << "\nparse class" << ce->name << "namespace" << cur_namespace;
// piCout << "parse class" << ce->name << "namespace" << cur_namespace;
// piCout << "\nparse class" << ce->name << "namespace" << cur_namespace;
while (!fc.isEmpty()) {
PIString cw = fc.takeCWord(), tmp;
//piCout << "\ntaked word" << cw;
if (cw == s_public ) {cur_def_vis = Public; fc.cutLeft(1); continue;}
if (cw == s_protected) {cur_def_vis = Protected; fc.cutLeft(1); continue;}
if (cw == s_private ) {cur_def_vis = Private; fc.cutLeft(1); continue;}
// piCout << "\ntaked word" << cw;
if (cw == s_public) {
cur_def_vis = Public;
fc.cutLeft(1);
continue;
}
if (cw == s_protected) {
cur_def_vis = Protected;
fc.cutLeft(1);
continue;
}
if (cw == s_private) {
cur_def_vis = Private;
fc.cutLeft(1);
continue;
}
if (cw == s_namespace) {
PIString prev_namespace = cur_namespace, ccmn;
cur_namespace += fc.takeCWord() + s_ns;
@@ -486,10 +635,10 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
fc.takeSymbol();
continue;
}
tmp = fc.takeLeft(fc.find('{'));
tmp = fc.takeLeft(fc.find('{'));
stmp = fc.takeRange('{', '}');
fc.takeSymbol();
stmp = cw + ' ' + tmp + '{' + stmp + '}';
stmp = cw + ' ' + tmp + '{' + stmp + '}';
parseClass(ce, stmp, false);
continue;
}
@@ -501,14 +650,16 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
fc.takeSymbol();
continue;
}
if (cw == s_friend) {fc.cutLeft(fc.find(';') + 1); continue;}
if (cw == s_friend) {
fc.cutLeft(fc.find(';') + 1);
continue;
}
if (cw == s_typedef) {
if (ce) {
ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';')));
typedefs << ce->typedefs.back();
typedefs.back().first.insert(0, cur_namespace);
if (ce->typedefs.back().first.isEmpty())
ce->typedefs.pop_back();
if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back();
}
fc.takeSymbol();
continue;
@@ -517,20 +668,25 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
fc.takeRange('<', '>');
def = !isDeclaration(fc, 0, &end);
fc.cutLeft(end);
if (def) fc.takeRange('{', '}');
else fc.takeSymbol();
if (def)
fc.takeRange('{', '}');
else
fc.takeSymbol();
continue;
}
def = !isDeclaration(fc, 0, &end);
tmp = (cw + fc.takeLeft(end)).trim();
if (!tmp.isEmpty() && ce)
parseMember(ce, tmp);
if (def) fc.takeRange('{', '}');
else fc.takeSymbol();
if (ps == fc.size_s()) {fc.cutLeft(1);}
if (!tmp.isEmpty() && ce) parseMember(ce, tmp);
if (def)
fc.takeRange('{', '}');
else
fc.takeSymbol();
if (ps == fc.size_s()) {
fc.cutLeft(1);
}
ps = fc.size_s();
}
cur_def_vis = prev_vis;
cur_def_vis = prev_vis;
cur_namespace = prev_namespace;
}
@@ -539,7 +695,7 @@ PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) {
PICodeParser::MetaMap ret;
if (fc.isEmpty()) return ret;
PIStringList ml = fc.split(',');
piForeachC (PIString & m, ml) {
piForeachC(PIString & m, ml) {
int i = m.find('=');
if (i < 0) {
ret[m.trimmed()] = PIString();
@@ -550,55 +706,61 @@ PICodeParser::MetaMap PICodeParser::parseMeta(PIString & fc) {
ret[m.left(i).trim()] = mv;
}
}
//piCout << ms << ret;
// piCout << ms << ret;
return ret;
}
bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta) {
static const PIString s_ss = PIStringAscii(" ");
static const PIString s_M = PIStringAscii("$M");
//piCout << PIStringAscii("enum") << name << fc;
static const PIString s_M = PIStringAscii("$M");
// piCout << PIStringAscii("enum") << name << fc;
Enum e(name);
e.meta = meta;
PIStringList vl(fc.split(','));
PIString vn;
int cv = -1, ind = 0;
piForeach (PIString & v, vl) {
piForeach(PIString & v, vl) {
MetaMap meta;
int mi = v.find(s_M);
if (mi >= 0) {
meta = tmp_meta.value(v.takeMid(mi, 5));
v.replaceAll(s_ss, ' ');
}
vn = v; ind = v.find('=');
if (ind > 0) {cv = v.right(v.size_s() - ind - 1).toInt(); vn = v.left(ind);}
vn = v;
ind = v.find('=');
if (ind > 0) {
cv = v.right(v.size_s() - ind - 1).toInt();
vn = v.left(ind);
}
if (ind < 0) ++cv;
e.members << EnumeratorInfo(vn.trim(), cv, meta);
}
if (!e.members.isEmpty())
if (e.members.back().name.isEmpty())
e.members.pop_back();
if (e.members.back().name.isEmpty()) e.members.pop_back();
enums << e;
return true;
}
PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) {
//piCout << "parse typedef" << fc;
// piCout << "parse typedef" << fc;
Typedef td;
fc.replaceAll('\t', ' ');
if (fc.contains('(')) {
int start = fc.find('('), end = fc.find(')');
td.first = fc.takeMid(start + 1, end - start - 1).trim();
if (td.first.left(1) == PIChar('*')) {td.first.cutLeft(1).trim(); fc.insert(start + 1, '*');}
if (td.first.left(1) == PIChar('*')) {
td.first.cutLeft(1).trim();
fc.insert(start + 1, '*');
}
td.second = fc.trim();
} else {
td.first = fc.takeMid(fc.findLast(' ')).trim();
td.first = fc.takeMid(fc.findLast(' ')).trim();
td.second = fc.trim();
}
//piCout << "found typedef" << td;
// piCout << "found typedef" << td;
return td;
}
@@ -634,22 +796,26 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
if (fc.trim().isEmpty()) return true;
if (fc.find(s_operator) >= 0) return true;
tmp_temp.clear();
//piCout << "parse member" << fc;
// piCout << "parse member" << fc;
int ts = fc.find('<'), te = 0;
PIString ctemp, crepl;
while (ts >= 0) {
ctemp = fc.mid(ts).takeRange('<', '>');
if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find('<', te); continue;}
if (ctemp.isEmpty()) {
te = ts + 1;
ts = fc.find('<', te);
continue;
}
crepl = s_T + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, '0');
fc.replace(ts, ctemp.size_s() + 2, crepl);
tmp_temp[crepl] = '<' + ctemp + '>';
ts = fc.find('<', te);
ts = fc.find('<', te);
}
fc.replaceAll('\n', ' ').replaceAll('\t', ' ').replaceAll(s_ss, ' ').replaceAll(s_cs, ',').replaceAll(s_sb, '(').replaceAll(s_sM, s_M);
//piCout << "parse member" << fc;
// piCout << "parse member" << fc;
PIStringList tl, al;
Member me;
//piCout << fc;
// piCout << fc;
if (fc.contains('(')) {
MetaMap meta;
int ind = fc.find(s_M);
@@ -659,16 +825,16 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
}
fc.cutRight(fc.size_s() - fc.findLast(')') - 1);
te = fc.find('(');
//piCout << fc;
// piCout << fc;
for (ts = te - 1; ts >= 0; --ts)
if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break;
//piCout << "takeMid" << ts + 1 << te - ts - 1;
// piCout << "takeMid" << ts + 1 << te - ts - 1;
me.meta = meta;
me.name = fc.takeMid(ts + 1, te - ts - 1);
if (me.name == parent->name) return true;
me.arguments_full = fc.takeMid(ts + 2).cutRight(1).split(',');
me.type = fc.cutRight(1).trim();
me.visibility = cur_def_vis;
me.type = fc.cutRight(1).trim();
me.visibility = cur_def_vis;
if (me.type.find(s_inline_s) >= 0) {
me.attributes |= Inline;
me.type.removeAll(s_inline_s);
@@ -683,20 +849,18 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
}
normalizeEntityNamespace(me.type);
int i = 0;
//piCout << me.arguments_full;
piForeach (PIString & a, me.arguments_full)
if ((i = a.find('=')) > 0)
a.cutRight(a.size_s() - i).trim();
// piCout << me.arguments_full;
piForeach(PIString & a, me.arguments_full)
if ((i = a.find('=')) > 0) a.cutRight(a.size_s() - i).trim();
for (int j = 0; j < me.arguments_full.size_s(); ++j)
if (me.arguments_full[j] == s_void) {
me.arguments_full.remove(j);
--j;
}
me.arguments_type = me.arguments_full;
piForeach (PIString & a, me.arguments_type) {
piForeach(PIString & a, me.arguments_type) {
crepl.clear();
if (a.contains('['))
crepl = a.takeMid(a.find('['), a.findLast(']') - a.find('[') + 1);
if (a.contains('[')) crepl = a.takeMid(a.find('['), a.findLast(']') - a.find('[') + 1);
for (ts = a.size_s() - 1; ts >= 0; --ts)
if (!_isCChar(a[ts]) && !(a[ts].isDigit())) break;
a.cutRight(a.size_s() - ts - 1);
@@ -705,31 +869,34 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
a.trim();
}
restoreTmpTemp(&me);
//piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type;
// piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type;
parent->functions << me;
} else {
if (fc.endsWith(';')) fc.cutRight(1);
//piCout << "member" << fc;
// piCout << "member" << fc;
if (fc.startsWith(s_using) || !(fc.contains(' ') || fc.contains('\t') || fc.contains('\n'))) return true;
int bits = extractMemberBits(fc);
tl = fc.split(',');
//piCout << "member" << fc << tl;
//piCout << "member after eb" << fc << ", bits =" << bits;
tl = fc.split(',');
// piCout << "member" << fc << tl;
// piCout << "member after eb" << fc << ", bits =" << bits;
if (tl.isEmpty()) return true;
piForeach (PIString & v, tl)
piForeach(PIString & v, tl)
removeAssignment(v);
bool vn = true;
ctemp = tl.front().trim();
ctemp = tl.front().trim();
PIString meta_t;
if (ctemp.contains(s_M)) {
meta_t = ctemp.takeMid(ctemp.find(s_M), 5);
ctemp.trim();
}
for (ts = ctemp.size_s() - 1; ts > 0; --ts) {
if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;}
else {if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;}
if (vn) {
if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;
} else {
if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;
}
}
me.type = ctemp.takeLeft(ts + 1);
me.type = ctemp.takeLeft(ts + 1);
me.visibility = cur_def_vis;
ctemp += meta_t;
restoreTmpTemp(&me);
@@ -757,21 +924,21 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
type.trim();
normalizeEntityNamespace(type);
tl[0] = ctemp.trim();
//piCout << "vars" << tl;
piForeachC (PIString & v, tl) {
// piCout << "vars" << tl;
piForeachC(PIString & v, tl) {
crepl.clear();
me.name = v.trimmed();
me.type = type;
restoreTmpMeta(&me);
if (me.name.isEmpty()) continue;
if (me.name.contains('['))
crepl = me.name.takeMid(me.name.find('['), me.name.findLast(']') - me.name.find('[') + 1);
if (me.name.contains('[')) crepl = me.name.takeMid(me.name.find('['), me.name.findLast(']') - me.name.find('[') + 1);
while (!me.name.isEmpty()) {
if (me.name.front() == PIChar('*') || me.name.front() == PIChar('&')) {
me.type += me.name.takeLeft(1);
me.name.trim();
} else break;
} else
break;
}
me.is_type_ptr = (me.type.right(1) == PIChar(']') || me.type.right(1) == PIChar('*'));
me.type += crepl;
@@ -781,12 +948,12 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
if (cdim.isEmpty()) break;
me.dims << cdim;
}
//PICout(PICoutManipulators::AddAll) << "var" << me.type << me.name << me.bits;
//piCout << "var" << v << me.type << me.name << me.bits;
// PICout(PICoutManipulators::AddAll) << "var" << me.type << me.name << me.bits;
// piCout << "var" << v << me.type << me.name << me.bits;
parent->members << me;
}
}
//piCout << "parse member" << fc;
// piCout << "parse member" << fc;
return true;
}
@@ -818,13 +985,25 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
break;
}
n.push_front(' ');
if (n.find(s_s_const_s) >= 0) {n.replaceAll(s_s_const_s, ""); pref += s_const_s;}
if (n.find(s_s_static_s) >= 0) {n.replaceAll(s_s_static_s, ""); pref += s_static_s;}
if (n.find(s_s_mutable_s) >= 0) {n.replaceAll(s_s_mutable_s, ""); pref += s_mutable_s;}
if (n.find(s_s_volatile_s) >= 0) {n.replaceAll(s_s_volatile_s, ""); pref += s_volatile_s;}
if (n.find(s_s_const_s) >= 0) {
n.replaceAll(s_s_const_s, "");
pref += s_const_s;
}
if (n.find(s_s_static_s) >= 0) {
n.replaceAll(s_s_static_s, "");
pref += s_static_s;
}
if (n.find(s_s_mutable_s) >= 0) {
n.replaceAll(s_s_mutable_s, "");
pref += s_mutable_s;
}
if (n.find(s_s_volatile_s) >= 0) {
n.replaceAll(s_s_volatile_s, "");
pref += s_volatile_s;
}
n.trim();
int f = 0;
piForeachC (Entity * e, entities) {
piForeachC(Entity * e, entities) {
if (e->name == n) {
n = (pref + n + suff).trim();
return;
@@ -836,20 +1015,20 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
return;
}
}
piForeachC (Enum & e, enums) {
piForeachC(Enum & e, enums) {
if ((f = e.name.find(n)) >= 0)
if (e.name.at(f - 1) == PIChar(':'))
if (e.name.find(cur_namespace) >= 0) {
//piCout << "change" << n << "to" << e.name + suff;
// piCout << "change" << n << "to" << e.name + suff;
n = pref + e.name + suff;
return;
}
}
piForeachC (Typedef & e, typedefs) {
piForeachC(Typedef & e, typedefs) {
if ((f = e.first.find(n)) >= 0)
if (e.first.at(f - 1) == PIChar(':'))
if (e.first.find(cur_namespace) >= 0) {
//piCout << "change" << n << "to" << e.name + suff;
// piCout << "change" << n << "to" << e.name + suff;
n = pref + e.first + suff;
return;
}
@@ -860,12 +1039,12 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
void PICodeParser::restoreTmpTemp(Member * e) {
static const PIString s_T = PIStringAscii("$T");
int i = 0;
piForeach (PIString & a, e->arguments_full) {
int i = 0;
piForeach(PIString & a, e->arguments_full) {
while ((i = a.find(s_T)) >= 0)
a.replace(i, 5, tmp_temp[a.mid(i, 5)]);
}
piForeach (PIString & a, e->arguments_type) {
piForeach(PIString & a, e->arguments_type) {
while ((i = a.find(s_T)) >= 0)
a.replace(i, 5, tmp_temp[a.mid(i, 5)]);
}
@@ -876,7 +1055,7 @@ void PICodeParser::restoreTmpTemp(Member * e) {
void PICodeParser::restoreTmpMeta(PICodeParser::Member * e) {
static const PIString s_M = PIStringAscii("$M");
int i = e->name.find(s_M);
int i = e->name.find(s_M);
if (i < 0) return;
e->meta = tmp_meta[e->name.takeMid(i, 5)];
}
@@ -898,7 +1077,7 @@ bool PICodeParser::macroCondition(const PIString & mif, PIString mifcond) {
static const PIString s_ifndef = PIStringAscii("ifndef");
static const PIString s_if = PIStringAscii("if");
static const PIString s_elif = PIStringAscii("elif");
//piCout << "macroCondition" << mif << mifcond;
// piCout << "macroCondition" << mif << mifcond;
if (mif == s_ifdef) return isDefineExists(mifcond);
if (mif == s_ifndef) return !isDefineExists(mifcond);
if (mif == s_if || mif == s_elif) {
@@ -917,52 +1096,65 @@ double PICodeParser::procMacrosCond(PIString fc) {
char cc, nc;
PIString ce;
fc.removeAll(s_defined);
//piCout << "procMacrosCond" << fc;
// piCout << "procMacrosCond" << fc;
while (!fc.isEmpty()) {
cc = fc[0].toAscii();
nc = (fc.size() > 1 ? fc[1].toAscii() : 0);
if (cc == '!') {neg = true; fc.pop_front(); continue;}
if (cc == '(') {br = true; brv = procMacrosCond(fc.takeRange('(', ')'));}
if (cc == '&' && nc == '&') {fc.remove(0, 2); oper = 1; continue;}
if (cc == '|' && nc == '|') {fc.remove(0, 2); oper = 2; continue;}
if (cc == '!') {
neg = true;
fc.pop_front();
continue;
}
if (cc == '(') {
br = true;
brv = procMacrosCond(fc.takeRange('(', ')'));
}
if (cc == '&' && nc == '&') {
fc.remove(0, 2);
oper = 1;
continue;
}
if (cc == '|' && nc == '|') {
fc.remove(0, 2);
oper = 2;
continue;
}
if (!br) {
ce = fc.takeCWord();
if (ce.isEmpty()) ce = fc.takeNumber();
}
if (first) {
first = false;
ret = br ? brv : defineValue(ce);
ret = br ? brv : defineValue(ce);
if (neg) ret = -ret;
} else {
//piCout << "oper" << oper << "with" << ce;
// piCout << "oper" << oper << "with" << ce;
if (!br) brv = defineValue(ce);
switch (oper) {
case 1: ret = ret && (neg ? -brv : brv); break;
case 2: ret = ret || (neg ? -brv : brv); break;
case 1: ret = ret && (neg ? -brv : brv); break;
case 2: ret = ret || (neg ? -brv : brv); break;
}
}
if (ps == fc.size_s()) fc.cutLeft(1);
ps = fc.size_s();
br = neg = false;
}
//piCout << "return" << ret;
// piCout << "return" << ret;
return ret;
}
bool PICodeParser::isDefineExists(const PIString & dn) {
piForeachC (Define & d, defines) {
if (d.first == dn)
return true;
piForeachC(Define & d, defines) {
if (d.first == dn) return true;
}
return false;
}
double PICodeParser::defineValue(const PIString & dn) {
piForeachC (Define & d, defines) {
if (d.first == dn)
return d.second.isEmpty() ? 1. : d.second.toDouble();
piForeachC(Define & d, defines) {
if (d.first == dn) return d.second.isEmpty() ? 1. : d.second.toDouble();
}
return dn.toDouble();
}
@@ -979,28 +1171,33 @@ void PICodeParser::replaceMeta(PIString & dn) {
ms = dn.findRange('(', ')', '\\', s + 6, &ml);
if (ms < 0) return;
PIString meta = dn.mid(ms, ml).trim();
PIString rm = s_M + PIString::fromNumber(tmp_meta.size_s()).expandLeftTo(3, '0');
PIString rm = s_M + PIString::fromNumber(tmp_meta.size_s()).expandLeftTo(3, '0');
dn.replace(s, ms + ml + 1 - s, rm);
//piCout << "FOUND META \"" << meta << '\"';
// piCout << "FOUND META \"" << meta << '\"';
tmp_meta[rm] = parseMeta(meta);
s = dn.find(s_PIMETA);
s = dn.find(s_PIMETA);
}
}
PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
piForeach (Entity * e, entities)
if (e->name == en)
return e;
piForeach(Entity * e, entities)
if (e->name == en) return e;
return 0;
}
bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) {
int dind = fc.find('{', start), find = fc.find(';', start);
//piCout << "isDeclaration" << dind << find << fc.left(10);
if (dind < 0 && find < 0) {if (end) *end = -1; return true;}
if (dind < 0 || find < dind) {if (end) *end = find; return true;}
// piCout << "isDeclaration" << dind << find << fc.left(10);
if (dind < 0 && find < 0) {
if (end) *end = -1;
return true;
}
if (dind < 0 || find < dind) {
if (end) *end = find;
return true;
}
if (end) *end = dind;
return false;
}
@@ -1013,7 +1210,7 @@ bool PICodeParser::isMainFile(const PIString & fc) {
if (csi < 0) csi = fc.find(PIStringAscii("\tmain"), si);
if (csi < 0) csi = fc.find(PIStringAscii("\nmain"), si);
if (csi < 0) return false;
si = csi;
si = csi;
int fi = fc.find('(', si + 5);
if (fi < 0) return false;
if (fi - si < 10) {
@@ -1038,68 +1235,80 @@ PIString PICodeParser::procMacros(PIString fc) {
int ifcnt = 0;
bool grab = false, skip = false, cond_ok = false;
PIString pfc, nfc, line, mif, mifcond;
//piCout << "procMacros\n<******" << fc << "\n******>";
// piCout << "procMacros\n<******" << fc << "\n******>";
fc += '\n';
while (!fc.isEmpty()) {
line = fc.takeLine().trimmed();
if (line.left(1) == PIChar('#')) {
mifcond = line.mid(1);
mif = mifcond.takeCWord();
//piCout << mif;
//piCout << "mif mifcond" << mif << mifcond << ifcnt;
mif = mifcond.takeCWord();
// piCout << mif;
// piCout << "mif mifcond" << mif << mifcond << ifcnt;
if (skip || grab) {
if (mif.left(2) == s_if) ifcnt++;
if (mif.left(5) == s_endif) {
if (ifcnt > 0) ifcnt--;
if (ifcnt > 0)
ifcnt--;
else {
//piCout << "main endif" << skip << grab;
// piCout << "main endif" << skip << grab;
if (grab) pfc += procMacros(nfc);
skip = grab = false;
continue;
}
}
if (mif.left(4) == s_elif && ifcnt == 0) {
//piCout << "main elif" << skip << grab << cond_ok;
// piCout << "main elif" << skip << grab << cond_ok;
if (cond_ok) {
if (grab) {
pfc += procMacros(nfc);
skip = true; grab = false;
skip = true;
grab = false;
}
continue;
}
if (skip) {
//piCout << "check elif" << skip << grab << cond_ok;
// piCout << "check elif" << skip << grab << cond_ok;
if (!macroCondition(mif, mifcond.trimmed())) continue;
//piCout << "check elif ok";
skip = false; grab = cond_ok = true;
// piCout << "check elif ok";
skip = false;
grab = cond_ok = true;
continue;
}
continue;
}
if (mif.left(4) == s_else && ifcnt == 0) {
//piCout << "main else" << skip << grab;
// piCout << "main else" << skip << grab;
if (grab) pfc += procMacros(nfc);
if (skip && !cond_ok) {skip = false; grab = true;}
else {skip = true; grab = false;}
if (skip && !cond_ok) {
skip = false;
grab = true;
} else {
skip = true;
grab = false;
}
continue;
}
if (grab) nfc += line + '\n';
continue;
}
if (mif.left(2) == s_if) {
//piCout << "main if";
// piCout << "main if";
skip = grab = cond_ok = false;
if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true;
else skip = true;
if (macroCondition(mif, mifcond.trimmed()))
grab = cond_ok = true;
else
skip = true;
ifcnt = 0;
nfc.clear();
} else {
parseDirective(line.cutLeft(1).trim());
//return false; /// WARNING: now skip errors
// return false; /// WARNING: now skip errors
}
} else {
if (grab) nfc += line + '\n';
else if (!skip) pfc += line + '\n';
if (grab)
nfc += line + '\n';
else if (!skip)
pfc += line + '\n';
}
}
return pfc;
@@ -1107,13 +1316,13 @@ PIString PICodeParser::procMacros(PIString fc) {
bool PICodeParser::parseDirective(PIString d) {
static const PIString s_include = PIStringAscii("include");
static const PIString s_define = PIStringAscii("define");
static const PIString s_undef = PIStringAscii("undef");
static const PIString s_PIMETA = PIStringAscii("PIMETA");
static const PIString s_include = PIStringAscii("include");
static const PIString s_define = PIStringAscii("define");
static const PIString s_undef = PIStringAscii("undef");
static const PIString s_PIMETA = PIStringAscii("PIMETA");
if (d.isEmpty()) return true;
PIString dname = d.takeCWord();
//piCout << "parseDirective" << d;
// piCout << "parseDirective" << d;
if (dname == s_include) {
d.replaceAll('<', '\"').replaceAll('>', '\"');
PIString cf = cur_file, ifc = d.takeRange('\"', '\"');
@@ -1125,7 +1334,7 @@ bool PICodeParser::parseDirective(PIString d) {
}
if (dname == s_define) {
PIString mname = d.takeCWord();
//piCout << mname;
// piCout << mname;
if (mname == s_PIMETA) return true;
if (d.left(1) == PIChar('(')) { // macro
PIStringList args = d.takeRange('(', ')').split(',').trim();
@@ -1150,7 +1359,10 @@ bool PICodeParser::parseDirective(PIString d) {
if (dname == s_undef) {
PIString mname = d.takeCWord();
for (int i = 0; i < defines.size_s(); ++i)
if (defines[i].first == mname) {defines.remove(i); --i;}
if (defines[i].first == mname) {
defines.remove(i);
--i;
}
return true;
}
return true;
+70 -59
View File
@@ -5,49 +5,59 @@
* \~russian Разбор C++ кода
*/
/*
PIP - Platform Independent Primitives
C++ code parser
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
C++ code parser
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICODEPARSER_H
#define PICODEPARSER_H
#include "pifile.h"
#include "pievaluator.h"
#include "pifile.h"
inline bool _isCChar(const PIChar & c) {return (c.isAlpha() || (c.toAscii() == '_'));}
inline bool _isCChar(const PIString & c) {if (c.isEmpty()) return false; return _isCChar(c[0]);}
inline bool _isCChar(const PIChar & c) {
return (c.isAlpha() || (c.toAscii() == '_'));
}
inline bool _isCChar(const PIString & c) {
if (c.isEmpty()) return false;
return _isCChar(c[0]);
}
class PIP_EXPORT PICodeParser {
public:
PICodeParser();
enum Visibility {Global, Public, Protected, Private};
enum Visibility {
Global,
Public,
Protected,
Private
};
enum Attribute {
NoAttributes = 0x0,
Const = 0x01,
Static = 0x02,
Mutable = 0x04,
Volatile = 0x08,
Inline = 0x10,
Virtual = 0x20,
Extern = 0x40
Const = 0x01,
Static = 0x02,
Mutable = 0x04,
Volatile = 0x08,
Inline = 0x10,
Virtual = 0x20,
Extern = 0x40
};
typedef PIFlags<Attribute> Attributes;
typedef PIPair<PIString, PIString> Define;
typedef PIPair<PIString, PIString> Typedef;
@@ -55,25 +65,25 @@ public:
struct PIP_EXPORT Macro {
Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) {
name = n;
name = n;
value = v;
args = a;
args = a;
}
PIString expand(PIString args_, bool * ok = 0) const;
PIString name;
PIString value;
PIStringList args;
};
struct PIP_EXPORT Member {
Member() {
visibility = Global;
size = 0;
bits = -1;
visibility = Global;
size = 0;
bits = -1;
is_type_ptr = false;
attributes = NoAttributes;
attributes = NoAttributes;
}
bool isBitfield() const {return bits > 0;}
bool isBitfield() const { return bits > 0; }
MetaMap meta;
PIString type;
PIString name;
@@ -86,12 +96,12 @@ public:
int size;
int bits;
};
struct PIP_EXPORT Entity {
Entity() {
visibility = Global;
has_name = true;
size = 0;
visibility = Global;
has_name = true;
size = 0;
parent_scope = 0;
}
MetaMap meta;
@@ -102,49 +112,51 @@ public:
int size;
bool has_name;
Entity * parent_scope;
PIVector<Entity * > parents;
PIVector<Entity * > children;
PIVector<Entity *> parents;
PIVector<Entity *> children;
PIVector<Member> functions;
PIVector<Member> members;
PIVector<Typedef> typedefs;
};
struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {name = n; value = v; meta = m;}
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {
name = n;
value = v;
meta = m;
}
MetaMap meta;
PIString name;
int value;
};
struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()) {
name = n;
}
Enum(const PIString & n = PIString()) { name = n; }
MetaMap meta;
PIString name;
PIVector<EnumeratorInfo> members;
};
void parseFile(const PIString & file, bool follow_includes = true);
void parseFiles(const PIStringList & files, bool follow_includes = true);
void includeDirectory(const PIString & dir) {includes << dir;}
void addDefine(const PIString & def_name, const PIString & def_value) {custom_defines << Define(def_name, def_value);}
void includeDirectory(const PIString & dir) { includes << dir; }
void addDefine(const PIString & def_name, const PIString & def_value) { custom_defines << Define(def_name, def_value); }
bool isEnum(const PIString & name);
Entity * findEntityByName(const PIString & en);
PIStringList parsedFiles() const {return PIStringList(proc_files.toVector());}
PIString mainFile() const {return main_file;}
const PICodeParser::Entity * global() const {return &root_;}
int macrosSubstitutionMaxIterations() const {return macros_iter;}
void setMacrosSubstitutionMaxIterations(int value) {macros_iter = value;}
PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); }
PIString mainFile() const { return main_file; }
const PICodeParser::Entity * global() const { return &root_; }
int macrosSubstitutionMaxIterations() const { return macros_iter; }
void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; }
PIVector<Define> defines, custom_defines;
PIVector<Macro> macros;
PIVector<Enum> enums;
PIVector<Typedef> typedefs;
PIVector<Entity * > entities;
PIVector<Entity *> entities;
private:
void clear();
bool parseFileInternal(const PIString & file, bool follow_includes);
@@ -169,7 +181,7 @@ private:
bool isDeclaration(const PIString & fc, int start, int * end);
bool isMainFile(const PIString & fc);
void normalizeEntityNamespace(PIString & n);
int macros_iter, anon_num;
bool with_includes;
PIEvaluator evaluator;
@@ -181,7 +193,6 @@ private:
PIString cur_namespace;
PIMap<PIString, PIString> tmp_temp;
PIMap<PIString, MetaMap> tmp_meta;
};
#endif // PICODEPARSER_H
+14 -14
View File
@@ -6,22 +6,22 @@
* \~russian Сжатие с помощью zlib
*/
/*
PIP - Platform Independent Primitives
Compress class using zlib
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Compress class using zlib
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Compress Compress
//! \~\brief
@@ -58,8 +58,8 @@
#ifndef PICOMPRESS_H
#define PICOMPRESS_H
#include "pip_compress_export.h"
#include "pibytearray.h"
#include "pip_compress_export.h"
//! \~english Compress "ba" with compression level "level", return empty %PIByteArray if no compression supports
//! \~russian Сжимает "ba" с уровнем сжатия "level", возвращает пустой %PIByteArray если нет поддержки
+13 -13
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Console Console
//! \~\brief
+16 -16
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Keyboard grabber for console
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Keyboard grabber for console
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pikbdlistener.h"
@@ -406,11 +406,11 @@ void PIKbdListener::readKeyboard() {
PRIVATE->ret = read(0, rc, 8);
/*piCout << "key" << PIString(rc).replaceAll("\e", "\\e");
for (int i = 0; i < PRIVATE->ret; ++i)
PICout(0) << PICoutManipulators::Hex << int(((uchar * )&rc)[i]) << ' ';
PICout(0) << PICoutManipulators::Hex << int(((uchar * )&rc)[i]) << ' ';
PICout(0) << "\n";
std::cout << PRIVATE->ret << " chars ";
for (int i = 0; i < PRIVATE->ret; ++i)
std::cout << "'" << (char)(rc[i]) << "' " << (int)(uchar)(rc[i]);
std::cout << "'" << (char)(rc[i]) << "' " << (int)(uchar)(rc[i]);
std::cout << std::endl;*/
if (rc[0] == 0) {
piMSleep(10);
@@ -523,7 +523,7 @@ void PIKbdListener::readKeyboard() {
}
/*cout << "wo mods (" << mod << ")\n";
for (int i = 0; i < PRIVATE->ret; ++i)
cout << "'" << (char)(rc[i]) << "' ";
cout << "'" << (char)(rc[i]) << "' ";
cout << endl;*/
}
if (ke.key == 0 && PRIVATE->ret > 1) ke.key = PIChar(rc).unicode16Code();
+13 -13
View File
@@ -5,22 +5,22 @@
* \~russian Консольный захват клавиатуры
*/
/*
PIP - Platform Independent Primitives
Keyboard grabber for console
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Keyboard grabber for console
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIKBDLISTENER_H
+75 -72
View File
@@ -5,104 +5,108 @@
* \~russian Консольный тайловый менеджер
*/
/*
PIP - Platform Independent Primitives
Console GUI
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Console GUI
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREEN_H
#define PISCREEN_H
#include "pip_console_export.h"
#include "piscreentile.h"
#include "piscreendrawer.h"
#include "piscreentile.h"
class PIP_CONSOLE_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
{
class PIP_CONSOLE_EXPORT PIScreen
: public PIThread
, public PIScreenTypes::PIScreenBase {
PIOBJECT_SUBCLASS(PIScreen, PIThread);
class SystemConsole;
public:
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
~PIScreen();
//! Directly call function from \a PIKbdListener
void enableExitCapture(int key = 'Q') {listener->enableExitCapture(key);}
//! Directly call function from \a PIKbdListener
void disableExitCapture() {listener->disableExitCapture();}
//! Directly call function from \a PIKbdListener
bool exitCaptured() const {return listener->exitCaptured();}
//! Directly call function from \a PIKbdListener
int exitKey() const {return listener->exitKey();}
int windowWidth() const {return console.width;}
int windowHeight() const {return console.height;}
bool isMouseEnabled() const {return mouse_;}
~PIScreen();
//! Directly call function from \a PIKbdListener
void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); }
//! Directly call function from \a PIKbdListener
void disableExitCapture() { listener->disableExitCapture(); }
//! Directly call function from \a PIKbdListener
bool exitCaptured() const { return listener->exitCaptured(); }
//! Directly call function from \a PIKbdListener
int exitKey() const { return listener->exitKey(); }
int windowWidth() const { return console.width; }
int windowHeight() const { return console.height; }
bool isMouseEnabled() const { return mouse_; }
void setMouseEnabled(bool on);
PIScreenTile * rootTile() {return &root;}
PIScreenTile * rootTile() { return &root; }
PIScreenTile * tileByName(const PIString & name);
void setDialogTile(PIScreenTile * t);
PIScreenTile * dialogTile() const {return tile_dialog;}
PIScreenDrawer * drawer() {return &drawer_;}
void clear() {drawer_.clear();}
void resize(int w, int h) {console.resize(w, h);}
PIScreenTile * dialogTile() const { return tile_dialog; }
PIScreenDrawer * drawer() { return &drawer_; }
void clear() { drawer_.clear(); }
void resize(int w, int h) { console.resize(w, h); }
EVENT_HANDLER0(void, waitForFinish);
EVENT_HANDLER0(void, start) {start(false);}
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER0(void, start) { start(false); }
EVENT_HANDLER1(void, start, bool, wait) {
PIThread::start(40);
if (wait) waitForFinish();
}
EVENT_HANDLER0(void, stop) { stop(false); }
EVENT_HANDLER1(void, stop, bool, clear);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data);
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e);
//! \handlers
//! \{
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e);
//! \handlers
//! \{
//! \fn void waitForFinish()
//! \brief block until finished (exit key will be pressed)
//! \fn void start(bool wait = false)
//! \brief Start console output and if "wait" block until finished (exit key will be pressed)
//! \fn void stop(bool clear = false)
//! \brief Stop console output and if "clear" clear the screen
//! \}
//! \events
//! \{
//! \}
//! \events
//! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
//! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e)
//! \brief Raise on some event "e" from tile "tile"
//! \}
//! \}
private:
class PIP_CONSOLE_EXPORT SystemConsole {
public:
@@ -131,7 +135,7 @@ private:
PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int width, height, pwidth, pheight;
int mouse_x, mouse_y;
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
PIVector<PIVector<PIScreenTypes::Cell>> cells, pcells;
};
void begin() override;
@@ -140,10 +144,10 @@ private:
void key_event(PIKbdListener::KeyEvent key);
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
static void key_eventS(PIKbdListener::KeyEvent key, void * t) {((PIScreen*)t)->key_event(key);}
PIVector<PIScreenTile*> tiles() {return root.children();}
PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e);
PIVector<PIScreenTile*> tilesUnderMouse(int x, int y);
static void key_eventS(PIKbdListener::KeyEvent key, void * t) { ((PIScreen *)t)->key_event(key); }
PIVector<PIScreenTile *> tiles() { return root.children(); }
PIVector<PIScreenTile *> prepareMouse(PIKbdListener::MouseEvent * e);
PIVector<PIScreenTile *> tilesUnderMouse(int x, int y);
bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent());
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e) override;
void tileRemovedInternal(PIScreenTile * t) override;
@@ -155,8 +159,7 @@ private:
PIKbdListener * listener;
PIKbdListener::KBFunc ret_func;
PIScreenTile root;
PIScreenTile * tile_focus, * tile_dialog;
PIScreenTile *tile_focus, *tile_dialog;
};
+31 -28
View File
@@ -5,22 +5,22 @@
* \~russian Тайл для PIScreen с API PIConsole
*/
/*
PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENCONSOLE_H
@@ -35,10 +35,15 @@
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
public:
TileVars(const PIString & n = PIString());
protected:
struct PIP_CONSOLE_EXPORT Variable {
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;}
bool isEmpty() const {return (ptr == 0);}
Variable() {
nx = ny = type = offset = bitFrom = bitCount = size = 0;
format = PIScreenTypes::CellFormat();
ptr = 0;
}
bool isEmpty() const { return (ptr == 0); }
PIString name;
PIScreenTypes::CellFormat format;
int nx;
@@ -50,16 +55,16 @@ protected:
int size;
const void * ptr;
/*void operator =(const Variable & src) {
name = src.name;
format = src.format;
nx = src.nx;
ny = src.ny;
type = src.type;
offset = src.offset;
bitFrom = src.bitFrom;
bitCount = src.bitCount;
size = src.size;
ptr = src.ptr;
name = src.name;
format = src.format;
nx = src.nx;
ny = src.ny;
type = src.type;
offset = src.offset;
bitFrom = src.bitFrom;
bitCount = src.bitCount;
size = src.size;
ptr = src.ptr;
}*/
};
PIVector<Variable> variables;
@@ -69,9 +74,7 @@ protected:
};
class PIP_CONSOLE_EXPORT PIScreenConsoleTile : public PIScreenTile
{
class PIP_CONSOLE_EXPORT PIScreenConsoleTile: public PIScreenTile {
public:
PIScreenConsoleTile();
};
+67 -31
View File
@@ -5,22 +5,22 @@
* \~russian Отрисовщик для PIScreen
*/
/*
PIP - Platform Independent Primitives
Drawer for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Drawer for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENDRAWER_H
@@ -30,10 +30,10 @@
#include "piscreentypes.h"
#include "pistring.h"
class PIP_CONSOLE_EXPORT PIScreenDrawer
{
class PIP_CONSOLE_EXPORT PIScreenDrawer {
friend class PIScreen;
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c);
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell>> & c);
public:
enum ArtChar {
LineVertical = 1,
@@ -46,26 +46,62 @@ public:
Unchecked,
Checked
};
void clear();
void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');}
void drawPixel(int x, int y, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawLine(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawFrame(int x0, int y0, int x1, int y1, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void drawText(int x, int y, const PIString & s, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Transparent, PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell> > & content);
PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));}
static void clear(PIVector<PIVector<PIScreenTypes::Cell> > & cells);
void clear();
void clearRect(int x0, int y0, int x1, int y1) { fillRect(x0, y0, x1, y1, ' '); }
void drawPixel(int x,
int y,
const PIChar & c,
PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0);
void drawLine(int x0,
int y0,
int x1,
int y1,
const PIChar & c,
PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0);
void drawRect(int x0,
int y0,
int x1,
int y1,
const PIChar & c,
PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0);
void drawFrame(int x0,
int y0,
int x1,
int y1,
PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0);
void drawText(int x,
int y,
const PIString & s,
PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Transparent,
PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0,
int y0,
int x1,
int y1,
const PIChar & c,
PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0);
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell>> & content);
PIChar artChar(const ArtChar type) const { return arts_.value(type, PIChar(' ')); }
static void clear(PIVector<PIVector<PIScreenTypes::Cell>> & cells);
private:
PIVector<PIVector<PIScreenTypes::Cell> > & cells;
PIVector<PIVector<PIScreenTypes::Cell>> & cells;
int width, height;
PIMap<ArtChar, PIChar> arts_;
};
+48 -42
View File
@@ -5,58 +5,66 @@
* \~russian Базовый тайл для PIScreen
*/
/*
PIP - Platform Independent Primitives
Basic PIScreen tile
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Basic PIScreen tile
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENTILE_H
#define PISCREENTILE_H
#include "pikbdlistener.h"
#include "pip_console_export.h"
#include "piscreentypes.h"
#include "pikbdlistener.h"
class PIScreenDrawer;
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject);
public:
PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
PIScreenTile(const PIString & n = PIString(),
PIScreenTypes::Direction d = PIScreenTypes::Vertical,
PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
virtual ~PIScreenTile();
void addTile(PIScreenTile * t);
void takeTile(PIScreenTile * t);
void removeTile(PIScreenTile * t);
PIScreenTile * parentTile() const {return parent;}
PIVector<PIScreenTile * > children(bool only_visible = false);
PIScreenTile * parentTile() const { return parent; }
PIVector<PIScreenTile *> children(bool only_visible = false);
PIScreenTile * childUnderMouse(int x, int y);
void show() {visible = true;}
void hide() {visible = false;}
void show() { visible = true; }
void hide() { visible = false; }
void setFocus();
bool hasFocus() const {return has_focus;}
void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;}
void setMargins(int l, int r, int t, int b) {marginLeft = l; marginRight = r; marginTop = t; marginBottom = b;}
bool hasFocus() const { return has_focus; }
void setMargins(int m) { marginLeft = marginRight = marginTop = marginBottom = m; }
void setMargins(int l, int r, int t, int b) {
marginLeft = l;
marginRight = r;
marginTop = t;
marginBottom = b;
}
int x() const { return x_; }
int y() const { return y_; }
int width() const { return width_; }
int height() const { return height_; }
int x() const {return x_;}
int y() const {return y_;}
int width() const {return width_;}
int height() const {return height_;}
PIScreenTypes::Direction direction;
PIScreenTypes::SizePolicy size_policy;
PIScreenTypes::FocusFlags focus_flags;
@@ -67,43 +75,41 @@ public:
int marginLeft, marginRight, marginTop, marginBottom;
int spacing;
bool visible;
protected:
//! Returns desired tile size in "w" and "h"
virtual void sizeHint(int & w, int & h) const;
//! Tile has been resized to "w"x"h"
virtual void resizeEvent(int w, int h) {}
//! Draw tile with drawer "d" in world-space coordinates
virtual void drawEvent(PIScreenDrawer * d) {}
//! Return "true" if you process key
virtual bool keyEvent(PIKbdListener::KeyEvent key) {return false;}
virtual bool keyEvent(PIKbdListener::KeyEvent key) { return false; }
//! Return "true" if you process event
virtual bool mouseEvent(PIKbdListener::MouseEvent me) {return false;}
virtual bool mouseEvent(PIKbdListener::MouseEvent me) { return false; }
//! Return "true" if you process wheel
virtual bool wheelEvent(PIKbdListener::WheelEvent we) {return false;}
virtual bool wheelEvent(PIKbdListener::WheelEvent we) { return false; }
void raiseEvent(PIScreenTypes::TileEvent e);
void setScreen(PIScreenTypes::PIScreenBase * s);
void deleteChildren();
void drawEventInternal(PIScreenDrawer * d);
void layout();
bool needLayout() {return size_policy != PIScreenTypes::Ignore;}
PIVector<PIScreenTile * > tiles;
bool needLayout() { return size_policy != PIScreenTypes::Ignore; }
PIVector<PIScreenTile *> tiles;
PIScreenTile * parent;
PIScreenTypes::PIScreenBase * screen;
int x_, y_, width_, height_;
bool has_focus;
private:
int pw, ph;
};
+36 -20
View File
@@ -5,22 +5,22 @@
* \~russian Различные тайлы для PIScreen
*/
/*
PIP - Platform Independent Primitives
Various tiles for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Various tiles for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENTILES_H
@@ -32,6 +32,7 @@
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile);
public:
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
TileSimple(const PIString & n = PIString());
@@ -39,6 +40,7 @@ public:
virtual ~TileSimple() {}
PIVector<Row> content;
PIScreenTypes::Alignment alignment;
protected:
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
@@ -50,16 +52,18 @@ class TileList;
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile);
friend class TileList;
public:
TileScrollBar(const PIString & n = PIString());
virtual ~TileScrollBar() {}
void setMinimum(int v);
void setMaximum(int v);
void setValue(int v);
int minimum() const {return minimum_;}
int maximum() const {return maximum_;}
int value() const {return value_;}
int minimum() const { return minimum_; }
int maximum() const { return maximum_; }
int value() const { return value_; }
int thickness;
protected:
void _check();
void sizeHint(int & w, int & h) const override;
@@ -72,6 +76,7 @@ protected:
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile);
public:
enum SelectionMode {
NoSelection,
@@ -92,6 +97,7 @@ public:
SelectionMode selection_mode;
PISet<int> selected;
int lhei, cur, offset;
protected:
void sizeHint(int & w, int & h) const override;
void resizeEvent(int w, int h) override;
@@ -106,6 +112,7 @@ protected:
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile);
public:
TileButton(const PIString & n = PIString());
virtual ~TileButton() {}
@@ -114,6 +121,7 @@ public:
};
PIScreenTypes::CellFormat format;
PIString text;
protected:
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
@@ -122,10 +130,9 @@ protected:
};
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile);
public:
TileButtons(const PIString & n = PIString());
virtual ~TileButtons() {}
@@ -136,14 +143,15 @@ public:
PIScreenTypes::Alignment alignment;
PIVector<Button> content;
int cur;
protected:
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
bool mouseEvent(PIKbdListener::MouseEvent me) override;
struct Rect {
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {}
int x0,y0,x1,y1;
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0), y0(_y0), x1(_x1), y1(_y1) {}
int x0, y0, x1, y1;
};
PIVector<Rect> btn_rects;
};
@@ -151,6 +159,7 @@ protected:
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile);
public:
TileCheck(const PIString & n = PIString());
virtual ~TileCheck() {}
@@ -160,6 +169,7 @@ public:
PIScreenTypes::CellFormat format;
PIString text;
bool toggled;
protected:
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
@@ -170,6 +180,7 @@ protected:
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile);
public:
TileProgress(const PIString & n = PIString());
virtual ~TileProgress() {}
@@ -178,6 +189,7 @@ public:
PIString suffix;
double maximum;
double value;
protected:
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
@@ -186,11 +198,13 @@ protected:
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);
public:
TilePICout(const PIString & n = PIString());
virtual ~TilePICout() {}
PIScreenTypes::CellFormat format;
int max_lines;
protected:
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
@@ -199,12 +213,14 @@ protected:
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile);
public:
TileInput(const PIString & n = PIString());
virtual ~TileInput() {}
PIScreenTypes::CellFormat format;
PIString text;
int max_length;
protected:
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
+149 -133
View File
@@ -5,22 +5,22 @@
* \~russian Типы для PIScreen
*/
/*
PIP - Platform Independent Primitives
Types for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Types for PIScreen
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENTYPES_H
@@ -33,139 +33,155 @@
class PIScreenTile;
namespace PIScreenTypes {
//! Color for chars or background
enum Color {
Default /** Default */,
Black /** Black */,
Red /** Red */,
Green /** Green */,
Blue /** Blue */,
Cyan /** Cyan */,
Magenta /** Magenta */,
Yellow /** Yellow */,
White /** White */,
Transparent /** Save previous color */
};
//! Flags for chars
enum CharFlag {
Bold /** Bold or bright */ = 0x1,
Blink /** Blink text */ = 0x2,
Underline /** Underline text */ = 0x4,
Inverse = 0x08
};
//! Alignment
enum Alignment {
Left /** Left */ ,
Center /** Center */ ,
Right /** Right */
};
//! Size policy
enum SizePolicy {
Fixed /** Fixed size */ ,
Preferred /** Preferred size */ ,
Expanding /** Maximum available size */ ,
Ignore /** Ignore layout logic */
};
//! Direction
enum Direction {
Horizontal /** Horizontal */ ,
Vertical /** Vertical */
};
//! Focus flags
enum FocusFlag {
CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab /** Focus passed to next tile by tab key */ = 0x2,
NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8,
NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical,
FocusOnMouse /** Tile focused on mouse press */ = 0x10,
FocusOnWheel /** Tile focused on wheel */ = 0x20,
FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel
};
typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags;
union PIP_CONSOLE_EXPORT CellFormat {
CellFormat(ushort f = 0) {raw_format = f;}
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_char = col_char;
color_back = col_back;
flags = flags_;
}
ushort raw_format;
struct {
ushort color_char : 4;
ushort color_back : 4;
ushort flags : 8;
};
bool operator ==(const CellFormat & c) const {return raw_format == c.raw_format;}
bool operator !=(const CellFormat & c) const {return raw_format != c.raw_format;}
};
struct PIP_CONSOLE_EXPORT Cell {
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;}
CellFormat format;
PIChar symbol;
bool operator ==(const Cell & c) const {return format == c.format && symbol == c.symbol;}
bool operator !=(const Cell & c) const {return format != c.format || symbol != c.symbol;}
Cell & operator =(const Cell & c) {
symbol = c.symbol;
if (c.format.color_back == Transparent) {
format.color_char = c.format.color_char;
format.flags = c.format.flags;
} else format = c.format;
return *this;
}
};
//! Color for chars or background
enum Color {
Default /** Default */,
Black /** Black */,
Red /** Red */,
Green /** Green */,
Blue /** Blue */,
Cyan /** Cyan */,
Magenta /** Magenta */,
Yellow /** Yellow */,
White /** White */,
Transparent /** Save previous color */
};
struct PIP_CONSOLE_EXPORT TileEvent {
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
int type;
PIVariant data;
};
class PIP_CONSOLE_EXPORT PIScreenBase {
public:
PIScreenBase() {}
virtual ~PIScreenBase() {}
virtual void tileEventInternal(PIScreenTile * , TileEvent) {}
virtual void tileRemovedInternal(PIScreenTile * ) {}
virtual void tileSetFocusInternal(PIScreenTile * ) {}
};
//! Flags for chars
enum CharFlag {
Bold /** Bold or bright */ = 0x1,
Blink /** Blink text */ = 0x2,
Underline /** Underline text */ = 0x4,
Inverse = 0x08
};
//! Alignment
enum Alignment {
Left /** Left */,
Center /** Center */,
Right /** Right */
};
//! Size policy
enum SizePolicy {
Fixed /** Fixed size */,
Preferred /** Preferred size */,
Expanding /** Maximum available size */,
Ignore /** Ignore layout logic */
};
//! Direction
enum Direction {
Horizontal /** Horizontal */,
Vertical /** Vertical */
};
//! Focus flags
enum FocusFlag {
CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab /** Focus passed to next tile by tab key */ = 0x2,
NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8,
NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical,
FocusOnMouse /** Tile focused on mouse press */ = 0x10,
FocusOnWheel /** Tile focused on wheel */ = 0x20,
FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel
};
typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags;
union PIP_CONSOLE_EXPORT CellFormat {
CellFormat(ushort f = 0) { raw_format = f; }
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_char = col_char;
color_back = col_back;
flags = flags_;
}
ushort raw_format;
struct {
ushort color_char: 4;
ushort color_back: 4;
ushort flags : 8;
};
bool operator==(const CellFormat & c) const { return raw_format == c.raw_format; }
bool operator!=(const CellFormat & c) const { return raw_format != c.raw_format; }
};
struct PIP_CONSOLE_EXPORT Cell {
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {
symbol = c;
format = f;
}
CellFormat format;
PIChar symbol;
bool operator==(const Cell & c) const { return format == c.format && symbol == c.symbol; }
bool operator!=(const Cell & c) const { return format != c.format || symbol != c.symbol; }
Cell & operator=(const Cell & c) {
symbol = c.symbol;
if (c.format.color_back == Transparent) {
format.color_char = c.format.color_char;
format.flags = c.format.flags;
} else
format = c.format;
return *this;
}
};
struct PIP_CONSOLE_EXPORT TileEvent {
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
int type;
PIVariant data;
};
class PIP_CONSOLE_EXPORT PIScreenBase {
public:
PIScreenBase() {}
virtual ~PIScreenBase() {}
virtual void tileEventInternal(PIScreenTile *, TileEvent) {}
virtual void tileRemovedInternal(PIScreenTile *) {}
virtual void tileSetFocusInternal(PIScreenTile *) {}
};
} // namespace PIScreenTypes
// inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
// inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator
//! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIScreenTypes::Cell) {
s << v.format.raw_format << v.symbol;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator
//! \~russian Оператор извлечения
BINARY_STREAM_READ(PIScreenTypes::Cell) {
s >> v.format.raw_format >> v.symbol;
return s;
}
//inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
//inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator
//! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIScreenTypes::Cell) {s << v.format.raw_format << v.symbol; return s;}
BINARY_STREAM_WRITE(PIScreenTypes::TileEvent) {
s << v.type << v.data;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator
//! \~russian Оператор извлечения
BINARY_STREAM_READ (PIScreenTypes::Cell) {s >> v.format.raw_format >> v.symbol; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator
//! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIScreenTypes::TileEvent) {s << v.type << v.data; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator
//! \~russian Оператор извлечения
BINARY_STREAM_READ (PIScreenTypes::TileEvent) {s >> v.type >> v.data; return s;}
BINARY_STREAM_READ(PIScreenTypes::TileEvent) {
s >> v.type >> v.data;
return s;
}
REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent)
+23 -24
View File
@@ -5,54 +5,54 @@
* \~russian Виртуальный терминал
*/
/*
PIP - Platform Independent Primitives
Virtual terminal
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Virtual terminal
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PITERMINAL_H
#define PITERMINAL_H
#include "pip_console_export.h"
#include "pikbdlistener.h"
#include "pip_console_export.h"
#include "piscreentypes.h"
class PIP_CONSOLE_EXPORT PITerminal: public PIThread
{
class PIP_CONSOLE_EXPORT PITerminal: public PIThread {
PIOBJECT_SUBCLASS(PITerminal, PIThread);
public:
//! Constructs %PITerminal
PITerminal();
~PITerminal();
int columns() const {return size_x;}
int rows() const {return size_y;}
int columns() const { return size_x; }
int rows() const { return size_y; }
bool resize(int cols, int rows);
void write(const PIByteArray & d);
void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m);
void write(PIKbdListener::KeyEvent ke);
PIVector<PIVector<PIScreenTypes::Cell> > content();
PIVector<PIVector<PIScreenTypes::Cell>> content();
static bool isSpecialKey(int k);
bool initialize();
void destroy();
private:
void initPrivate();
void readConsole();
@@ -72,8 +72,7 @@ private:
int size_x, size_y, cursor_x, cursor_y;
bool cursor_blink, cursor_visible;
PITimeMeasurer cursor_tm;
PIVector<PIVector<PIScreenTypes::Cell> > cells;
PIVector<PIVector<PIScreenTypes::Cell>> cells;
};
+14 -14
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Base macros for generic containers
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Base macros for generic containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picontainers.h"
@@ -29,6 +29,6 @@ size_t _PIContainerConstantsBase::calcMinCountPoT(size_t szof) {
elc *= 2;
++ret;
}
//printf("calcMinCount sizeof = %d, min_count = %d, pot = %d\n", szof, elc, ret);
// printf("calcMinCount sizeof = %d, min_count = %d, pot = %d\n", szof, elc, ret);
return ret;
}
+46 -34
View File
@@ -13,22 +13,22 @@
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/*
PIP - Platform Independent Primitives
Base macros for generic containers
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Base macros for generic containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONTAINERS_H
@@ -41,23 +41,24 @@
#else
# include <malloc.h>
#endif
#include <initializer_list>
#include <type_traits>
#include <string.h>
#include <new>
#include <algorithm>
#include <functional>
#include <initializer_list>
#include <new>
#include <string.h>
#include <type_traits>
template <typename C>
template<typename C>
class _PIReverseWrapper {
public:
_PIReverseWrapper(C & c): c_(c) {}
_PIReverseWrapper(const C & c): c_(const_cast<C&>(c)) {}
typename C::reverse_iterator begin() {return c_.rbegin();}
typename C::reverse_iterator end() {return c_.rend(); }
typename C::const_reverse_iterator begin() const {return c_.rbegin();}
typename C::const_reverse_iterator end() const {return c_.rend(); }
_PIReverseWrapper(const C & c): c_(const_cast<C &>(c)) {}
typename C::reverse_iterator begin() { return c_.rbegin(); }
typename C::reverse_iterator end() { return c_.rend(); }
typename C::const_reverse_iterator begin() const { return c_.rbegin(); }
typename C::const_reverse_iterator end() const { return c_.rend(); }
private:
C & c_;
};
@@ -71,15 +72,24 @@ public:
template<typename T>
class _PIContainerConstants {
public:
static size_t minCountPoT() {static size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
static size_t minCountPoT() {
static size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T));
return ret;
}
};
//! \brief
//! \~english Template reverse wrapper over any container
//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
template <typename C> _PIReverseWrapper<C> PIReverseWrap(C & c) {return _PIReverseWrapper<C>(c);}
template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _PIReverseWrapper<C>(c);}
template<typename C>
_PIReverseWrapper<C> PIReverseWrap(C & c) {
return _PIReverseWrapper<C>(c);
}
template<typename C>
_PIReverseWrapper<C> PIReverseWrap(const C & c) {
return _PIReverseWrapper<C>(c);
}
//! \brief
@@ -88,7 +98,7 @@ template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _P
//! \~\param c
//! \~english Iteration times in loop
//! \~russian Количество итераций цикла
#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
#define piForTimes(c) for (int _i##c = 0; _i##c < c; ++_i##c)
//! \brief
@@ -120,7 +130,7 @@ template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _P
//! // 4
//! \endcode
//! \sa \a piForeachC, \a piForeachR, \a piForeachRC
#define piForeach(i, c) for(i : c)
#define piForeach(i, c) for (i: c)
//! \brief
//! \~english Macro for iterate any container
@@ -136,7 +146,7 @@ template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _P
//! \~russian Перебор всех элементов контейнера с доступом только на чтение.
//! Перебор осуществляется в прямом порядке.
//! \~ \sa \a piForeach, \a piForeachR, \a piForeachRC
#define piForeachC(i, c) for(const i : c)
#define piForeachC(i, c) for (const i: c)
//! \brief
//! \~english Macro for iterate any container
@@ -152,7 +162,7 @@ template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _P
//! \~russian Перебор всех элементов контейнера с доступом на чтение и запись.
//! Перебор осуществляется в обратном порядке.
//! \~ \sa \a piForeach, \a piForeachC, \a piForeachRC
#define piForeachR(i, c) for(i : PIReverseWrap(c))
#define piForeachR(i, c) for (i: PIReverseWrap(c))
//! \brief
//! \~english Macro for iterate any container
@@ -168,8 +178,8 @@ template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _P
//! \~russian Перебор всех элементов контейнера с доступом только на чтение.
//! Перебор осуществляется в обратном порядке. Также можно писать **piForeachCR**
//! \~ \sa \a piForeach, \a piForeachC, \a piForeachR
#define piForeachRC(i, c) for(const i : PIReverseWrap(c))
#define piForeachCR piForeachRC
#define piForeachRC(i, c) for (const i: PIReverseWrap(c))
#define piForeachCR piForeachRC
//! \~\brief
@@ -177,8 +187,10 @@ template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _P
//! \~russian Порядок обхода для функции изменения размерности reshape().
//! \~ \sa \a PIVector::reshape(), \a PIDeque::reshape()
enum ReshapeOrder {
ReshapeByRow /*! \~english Traversing elements by line, just as they stay in memory \~russian Обход элементов построчно, так же как они находятся в памяти */,
ReshapeByColumn /*! \~english Traversing elements by column \~russian Обход элементов по столбцам */,
ReshapeByRow /*! \~english Traversing elements by line, just as they stay in memory \~russian Обход элементов построчно, так же как они
находятся в памяти */
,
ReshapeByColumn /*! \~english Traversing elements by column \~russian Обход элементов по столбцам */,
};
#endif // PICONTAINERS_H
+14 -14
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Containers
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Containers
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Containers Containers
//! \~\brief
@@ -180,12 +180,12 @@
#ifndef PICONTAINERSMODULE_H
#define PICONTAINERSMODULE_H
#include "pivector.h"
#include "pideque.h"
#include "pimap.h"
#include "piqueue.h"
#include "piset.h"
#include "pistack.h"
#include "pivector.h"
#include "pivector2d.h"
+291 -353
View File
@@ -13,22 +13,22 @@
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/*
PIP - Platform Independent Primitives
Dynamic array of any type
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Dynamic array of any type
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIDEQUE_H
@@ -114,22 +114,20 @@
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива 𝓞(n)
//!
//! \~\sa \a PIVector, \a PIMap
template <typename T>
template<typename T>
class PIDeque {
public:
typedef bool (*CompareFunc)(const T & , const T & );
typedef bool (*CompareFunc)(const T &, const T &);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T * pointer;
typedef const T * const_pointer;
typedef T & reference;
typedef const T & const_reference;
typedef size_t size_type;
//! \~english Constructs an empty array.
//! \~russian Создает пустой массив.
inline PIDeque() {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
}
inline PIDeque() { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) }
//! \~english Copy constructor.
//! \~russian Копирующий конструктор.
@@ -193,8 +191,8 @@ public:
//! \~russian Перемещающий конструктор.
inline PIDeque(PIDeque<T> && other) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
pid_data = other.pid_data;
pid_size = other.pid_size;
pid_data = other.pid_data;
pid_size = other.pid_size;
pid_rsize = other.pid_rsize;
pid_start = other.pid_start;
other._reset();
@@ -209,7 +207,7 @@ public:
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIDeque<T> & operator =(const PIDeque<T> & other) {
inline PIDeque<T> & operator=(const PIDeque<T> & other) {
if (this == &other) return *this;
clear();
alloc_forward(other.pid_size);
@@ -219,360 +217,330 @@ public:
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIDeque<T> & operator =(PIDeque<T> && other) {
inline PIDeque<T> & operator=(PIDeque<T> && other) {
swap(other);
return *this;
}
class iterator {
friend class PIDeque<T>;
private:
inline iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
PIDeque<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline iterator(): parent(0), pos(0) {}
inline T & operator *() {return (*parent)[pos];}
inline const T & operator *() const {return (*parent)[pos];}
inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline T & operator*() { return (*parent)[pos]; }
inline const T & operator*() const { return (*parent)[pos]; }
inline T & operator->() { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline iterator & operator ++() {
inline iterator & operator++() {
++pos;
return *this;
}
inline iterator operator ++(int) {
inline iterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline iterator & operator --() {
inline iterator & operator--() {
--pos;
return *this;
}
inline iterator operator --(int) {
inline iterator operator--(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline iterator & operator +=(const iterator & it) {
inline iterator & operator+=(const iterator & it) {
pos += it.pos;
return *this;
}
inline iterator & operator +=(size_t p) {
inline iterator & operator+=(size_t p) {
pos += p;
return *this;
}
inline iterator & operator -=(const iterator & it) {
inline iterator & operator-=(const iterator & it) {
pos -= it.pos;
return *this;
}
inline iterator & operator -=(size_t p) {
inline iterator & operator-=(size_t p) {
pos -= p;
return *this;
}
friend inline iterator operator -(size_t p, const iterator & it) {return it - p;}
friend inline iterator operator -(const iterator & it, size_t p) {
friend inline iterator operator-(size_t p, const iterator & it) { return it - p; }
friend inline iterator operator-(const iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
return it1.pos - it2.pos;
}
friend inline std::ptrdiff_t operator-(const iterator & it1, const iterator & it2) { return it1.pos - it2.pos; }
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
friend inline iterator operator +(const iterator & it, size_t p) {
friend inline iterator operator+(size_t p, const iterator & it) { return it + p; }
friend inline iterator operator+(const iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const iterator & it1, const iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const iterator & it1, const iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const iterator & it1, const iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const iterator & it1, const iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const iterator & it1, const iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const iterator & it1, const iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const iterator & it1, const iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const iterator & it1, const iterator & it2) { return it1.pos >= it2.pos; }
};
class const_iterator {
friend class PIDeque<T>;
private:
inline const_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
const PIDeque<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_iterator(): parent(0), pos(0) {}
inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline const T & operator*() const { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline const_iterator & operator ++() {
inline const_iterator & operator++() {
++pos;
return *this;
}
inline const_iterator operator ++(int) {
inline const_iterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_iterator & operator --() {
inline const_iterator & operator--() {
--pos;
return *this;
}
inline const_iterator operator --(int) {
inline const_iterator operator--(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_iterator & operator +=(const const_iterator & it) {
inline const_iterator & operator+=(const const_iterator & it) {
pos += it.pos;
return *this;
}
inline const_iterator & operator +=(size_t p) {
inline const_iterator & operator+=(size_t p) {
pos += p;
return *this;
}
inline const_iterator & operator -=(const const_iterator & it) {
inline const_iterator & operator-=(const const_iterator & it) {
pos -= it.pos;
return *this;
}
inline const_iterator & operator -=(size_t p) {
inline const_iterator & operator-=(size_t p) {
pos -= p;
return *this;
}
friend inline const_iterator operator -(size_t p, const const_iterator & it) {return it - p;}
friend inline const_iterator operator -(const const_iterator & it, size_t p) {
friend inline const_iterator operator-(size_t p, const const_iterator & it) { return it - p; }
friend inline const_iterator operator-(const const_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
return it1.pos - it2.pos;
}
friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; }
friend inline const_iterator operator +(size_t p, const const_iterator & it) {return it + p;}
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
friend inline const_iterator operator+(size_t p, const const_iterator & it) { return it + p; }
friend inline const_iterator operator+(const const_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const const_iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const const_iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; }
};
class reverse_iterator {
friend class PIDeque<T>;
private:
inline reverse_iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
PIDeque<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline reverse_iterator(): parent(0), pos(0) {}
inline T & operator *() {return (*parent)[pos];}
inline const T & operator *() const {return (*parent)[pos];}
inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline T & operator*() { return (*parent)[pos]; }
inline const T & operator*() const { return (*parent)[pos]; }
inline T & operator->() { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline reverse_iterator & operator ++() {
inline reverse_iterator & operator++() {
--pos;
return *this;
}
inline reverse_iterator operator ++(int) {
inline reverse_iterator operator++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline reverse_iterator & operator --() {
inline reverse_iterator & operator--() {
++pos;
return *this;
}
inline reverse_iterator operator --(int) {
inline reverse_iterator operator--(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline reverse_iterator & operator +=(const reverse_iterator & it) {
inline reverse_iterator & operator+=(const reverse_iterator & it) {
pos -= it.pos;
return *this;
}
inline reverse_iterator & operator +=(size_t p) {
inline reverse_iterator & operator+=(size_t p) {
pos -= p;
return *this;
}
inline reverse_iterator & operator -=(const reverse_iterator & it) {
inline reverse_iterator & operator-=(const reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline reverse_iterator & operator -=(size_t p) {
inline reverse_iterator & operator-=(size_t p) {
pos += p;
return *this;
}
friend inline reverse_iterator operator -(size_t p, const reverse_iterator & it) {return it - p;}
friend inline reverse_iterator operator -(const reverse_iterator & it, size_t p) {
friend inline reverse_iterator operator-(size_t p, const reverse_iterator & it) { return it - p; }
friend inline reverse_iterator operator-(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline std::ptrdiff_t operator-(const reverse_iterator & it1, const reverse_iterator & it2) { return it2.pos - it1.pos; }
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
friend inline reverse_iterator operator+(size_t p, const reverse_iterator & it) { return it + p; }
friend inline reverse_iterator operator+(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const reverse_iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const reverse_iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos >= it2.pos; }
};
class const_reverse_iterator {
friend class PIDeque<T>;
private:
inline const_reverse_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
const PIDeque<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_reverse_iterator(): parent(0), pos(0) {}
inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline const T & operator*() const { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline const_reverse_iterator & operator ++() {
inline const_reverse_iterator & operator++() {
--pos;
return *this;
}
inline const_reverse_iterator operator ++(int) {
inline const_reverse_iterator operator++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_reverse_iterator & operator --() {
inline const_reverse_iterator & operator--() {
++pos;
return *this;
}
inline const_reverse_iterator operator --(int) {
inline const_reverse_iterator operator--(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_reverse_iterator & operator +=(const const_reverse_iterator & it) {
inline const_reverse_iterator & operator+=(const const_reverse_iterator & it) {
pos -= it.pos;
return *this;
}
inline const_reverse_iterator & operator +=(size_t p) {
inline const_reverse_iterator & operator+=(size_t p) {
pos -= p;
return *this;
}
inline const_reverse_iterator & operator -=(const const_reverse_iterator & it) {
inline const_reverse_iterator & operator-=(const const_reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline const_reverse_iterator & operator -=(size_t p) {
inline const_reverse_iterator & operator-=(size_t p) {
pos += p;
return *this;
}
friend inline const_reverse_iterator operator -(size_t p, const const_reverse_iterator & it) {return it - p;}
friend inline const_reverse_iterator operator -(const const_reverse_iterator & it, size_t p) {
friend inline const_reverse_iterator operator-(size_t p, const const_reverse_iterator & it) { return it - p; }
friend inline const_reverse_iterator operator-(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
friend inline std::ptrdiff_t operator-(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline const_reverse_iterator operator +(size_t p, const const_reverse_iterator & it) {return it + p;}
friend inline const_reverse_iterator operator +(const const_reverse_iterator & it, size_t p) {
friend inline const_reverse_iterator operator+(size_t p, const const_reverse_iterator & it) { return it + p; }
friend inline const_reverse_iterator operator+(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const const_reverse_iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const const_reverse_iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos >= it2.pos; }
};
@@ -584,7 +552,7 @@ public:
//! \~russian Если массив - пуст, возвращаемый итератор будет равен \a end().
//! \~\return \ref stl_iterators
//! \~\sa \a end(), \a rbegin(), \a rend()
inline iterator begin() {return iterator(this, 0);}
inline iterator begin() { return iterator(this, 0); }
//! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
@@ -596,10 +564,10 @@ public:
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a begin(), \a rbegin(), \a rend()
inline iterator end() {return iterator(this, pid_size);}
inline iterator end() { return iterator(this, pid_size); }
inline const_iterator begin() const {return const_iterator(this, 0); }
inline const_iterator end() const {return const_iterator(this, pid_size);}
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator end() const { return const_iterator(this, pid_size); }
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
@@ -612,7 +580,7 @@ public:
//! Если массив пустой, то совпадает с итератором \a rend().
//! \~\return \ref stl_iterators
//! \~\sa \a rend(), \a begin(), \a end()
inline reverse_iterator rbegin() {return reverse_iterator(this, pid_size - 1);}
inline reverse_iterator rbegin() { return reverse_iterator(this, pid_size - 1); }
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
@@ -628,25 +596,25 @@ public:
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a rbegin(), \a begin(), \a end()
inline reverse_iterator rend() {return reverse_iterator(this, -1);}
inline reverse_iterator rend() { return reverse_iterator(this, -1); }
inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, pid_size - 1);}
inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(this, pid_size - 1); }
inline const_reverse_iterator rend() const { return const_reverse_iterator(this, -1); }
//! \~english Number of elements in the container.
//! \~russian Количество элементов массива.
//! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t size() const {return pid_size;}
inline size_t size() const { return pid_size; }
//! \~english Number of elements in the container as signed value.
//! \~russian Количество элементов массива в виде знакового числа.
//! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline ssize_t size_s() const {return pid_size;}
inline ssize_t size_s() const { return pid_size; }
//! \~english Same as \a size().
//! \~russian Синоним \a size().
//! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t length() const {return pid_size;}
inline size_t length() const { return pid_size; }
//! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
@@ -654,9 +622,9 @@ public:
//! \~english To find out the actual number of items, use the function \a size().
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
//! \~\sa \a reserve(), \a size(), \a size_s()
inline size_t capacity() const {return pid_rsize;}
inline size_t capacity() const { return pid_rsize; }
inline size_t _start() const {return pid_start;}
inline size_t _start() const { return pid_start; }
//! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли массив.
@@ -664,7 +632,7 @@ public:
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если массив пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isEmpty() const {return (pid_size == 0);}
inline bool isEmpty() const { return (pid_size == 0); }
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли массив.
@@ -672,7 +640,7 @@ public:
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если массив не пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isNotEmpty() const {return (pid_size > 0);}
inline bool isNotEmpty() const { return (pid_size > 0); }
//! \~english Tests whether at least one element in the array
//! passes the test implemented by the provided function `test`.
@@ -740,8 +708,8 @@ public:
//! piCout << v; // {1, 2, 5, 9}
//! \endcode
//! \~\sa \a at()
inline T & operator [](size_t index) {return pid_data[pid_start + index];}
inline const T & operator [](size_t index) const {return pid_data[pid_start + index];}
inline T & operator[](size_t index) { return pid_data[pid_start + index]; }
inline const T & operator[](size_t index) const { return pid_data[pid_start + index]; }
//! \~english Read only access to element by `index`.
//! \~russian Доступ исключительно на чтение к элементу по индексу `index`.
@@ -752,7 +720,7 @@ public:
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const T & at(size_t index) const {return pid_data[pid_start + index];}
inline const T & at(size_t index) const { return pid_data[pid_start + index]; }
//! \~english Returns the first element of the array that
//! passes the test implemented by the provided function `test`
@@ -762,8 +730,10 @@ public:
//! \~\sa \a indexWhere()
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
ssize_t i = indexWhere(test, start);
if (i < 0) return def;
else return at(i);
if (i < 0)
return def;
else
return at(i);
}
//! \~english Returns the last element of the array that
@@ -774,8 +744,10 @@ public:
//! \~\sa \a lastIndexWhere()
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
ssize_t i = lastIndexWhere(test, start);
if (i < 0) return def;
else return at(i);
if (i < 0)
return def;
else
return at(i);
}
//! \~english Last element.
@@ -787,8 +759,8 @@ public:
//! \~russian Возвращает ссылку на последний элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline T & back() {return pid_data[pid_start + pid_size - 1];}
inline const T & back() const {return pid_data[pid_start + pid_size - 1];}
inline T & back() { return pid_data[pid_start + pid_size - 1]; }
inline const T & back() const { return pid_data[pid_start + pid_size - 1]; }
//! \~english Last element.
//! \~russian Первый элемент массива.
@@ -799,12 +771,12 @@ public:
//! \~russian Возвращает ссылку на пенрвый элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline T & front() {return pid_data[pid_start];}
inline const T & front() const {return pid_data[pid_start];}
inline T & front() { return pid_data[pid_start]; }
inline const T & front() const { return pid_data[pid_start]; }
//! \~english Compare operator with array `v`.
//! \~russian Оператор сравнения с массивом `v`.
inline bool operator ==(const PIDeque<T> & v) const {
inline bool operator==(const PIDeque<T> & v) const {
if (pid_size != v.pid_size) return false;
for (size_t i = 0; i < pid_size; ++i) {
if (v[i] != (*this)[i]) return false;
@@ -814,7 +786,7 @@ public:
//! \~english Compare operator with array `v`.
//! \~russian Оператор сравнения с массивом `v`.
inline bool operator !=(const PIDeque<T> & v) const {return !(*this == v);}
inline bool operator!=(const PIDeque<T> & v) const { return !(*this == v); }
//! \~english Tests if element `e` exists in the array.
//! \~russian Проверяет наличие элемента `e` в массиве.
@@ -873,7 +845,7 @@ public:
start = pid_size + start;
if (start < 0) start = 0;
}
for (const T & e : v) {
for (const T & e: v) {
bool c = false;
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
if (e == pid_data[i]) {
@@ -1134,7 +1106,7 @@ public:
//! memcpy(vec.data(1), a, 2 * sizeof(int));
//! piCout << v; // {2, 12, 13, 2}
//! \endcode
inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);}
inline T * data(size_t index = 0) { return &(pid_data[pid_start + index]); }
//! \~english Read only pointer to array
//! \~russian Указатель на память массива только для чтения.
@@ -1153,7 +1125,7 @@ public:
//! memcpy(a, v.data(), a.size() * sizeof(int));
//! piCout << a[0] << a[1] << a[2]; // 1 3 5
//! \endcode
inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);}
inline const T * data(size_t index = 0) const { return &(pid_data[pid_start + index]); }
//! \~english Creates sub-array of this array.
//! \~russian Создает подмассив, то есть кусок из текущего массива.
@@ -1184,21 +1156,17 @@ public:
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIDeque<T> & clear() {
deleteT(pid_data + pid_start, pid_size);
pid_size = 0;
pid_size = 0;
pid_start = (pid_rsize - pid_size) / 2;
return *this;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIDeque<T> & clear() {
PIINTROSPECTION_CONTAINER_UNUSED(T, pid_size)
pid_size = 0;
pid_size = 0;
pid_start = (pid_rsize - pid_size) / 2;
return *this;
}
@@ -1242,21 +1210,17 @@ public:
//! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize()
inline PIDeque<T> & assign(const T & e = T()) {return fill(e);}
inline PIDeque<T> & assign(const T & e = T()) { return fill(e); }
//! \~english First does `resize(new_size)` then `fill(e)`.
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
//! \~\sa \a fill(), \a resize()
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIDeque<T> & assign(size_t new_size, const T & e) {
resize(new_size);
return fill(e);
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIDeque<T> & assign(size_t new_size, const T & e) {
_resizeRaw(new_size);
return fill(e);
@@ -1278,7 +1242,7 @@ public:
if (new_size < pid_size) {
deleteT(pid_data + pid_start + new_size, pid_size - new_size);
pid_size = new_size;
}else if (new_size > pid_size) {
} else if (new_size > pid_size) {
expand(new_size, e);
}
return *this;
@@ -1306,25 +1270,21 @@ public:
return *this;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIDeque<T> & _resizeRaw(size_t new_size) {
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
if (new_size > pid_size) {
PIINTROSPECTION_CONTAINER_USED(T, (new_size-pid_size));
PIINTROSPECTION_CONTAINER_USED(T, (new_size - pid_size));
}
if (new_size < pid_size) {
PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size));
PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size - new_size));
}
#endif
alloc_forward(new_size);
return *this;
}
inline void _copyRaw(T * dst, const T * src, size_t size) {
newT(dst, src, size);
}
inline void _copyRaw(T * dst, const T * src, size_t size) { newT(dst, src, size); }
//! \~english Attempts to allocate memory for at least `new_size` elements.
//! \~russian Резервируется память под как минимум `new_size` элементов.
@@ -1367,12 +1327,12 @@ public:
alloc_forward(pid_size + 1);
if (index < pid_size - 1) {
size_t os = pid_size - index - 1;
memmove((void*)(pid_data + pid_start + index + 1), (const void*)(pid_data + pid_start + index), os * sizeof(T));
memmove((void *)(pid_data + pid_start + index + 1), (const void *)(pid_data + pid_start + index), os * sizeof(T));
}
} else {
alloc_backward(pid_size + 1, -1);
if (index > 0) {
memmove((void*)(pid_data + pid_start), (const void*)(pid_data + pid_start + 1), index * sizeof(T));
memmove((void *)(pid_data + pid_start), (const void *)(pid_data + pid_start + 1), index * sizeof(T));
}
}
elementNew(pid_data + pid_start + index, e);
@@ -1393,12 +1353,12 @@ public:
alloc_forward(pid_size + 1);
if (index < pid_size - 1) {
size_t os = pid_size - index - 1;
memmove((void*)(pid_data + pid_start + index + 1), (const void*)(pid_data + pid_start + index), os * sizeof(T));
memmove((void *)(pid_data + pid_start + index + 1), (const void *)(pid_data + pid_start + index), os * sizeof(T));
}
} else {
alloc_backward(pid_size + 1, -1);
if (index > 0) {
memmove((void*)(pid_data + pid_start), (const void*)(pid_data + pid_start + 1), index * sizeof(T));
memmove((void *)(pid_data + pid_start), (const void *)(pid_data + pid_start + 1), index * sizeof(T));
}
}
elementNew(pid_data + pid_start + index, std::move(e));
@@ -1424,12 +1384,12 @@ public:
ssize_t os = pid_size - index;
alloc_forward(pid_size + v.pid_size);
if (os > 0) {
memmove((void*)(pid_data + pid_start + index + v.pid_size), (const void*)(pid_data + pid_start + index), os * sizeof(T));
memmove((void *)(pid_data + pid_start + index + v.pid_size), (const void *)(pid_data + pid_start + index), os * sizeof(T));
}
} else {
alloc_backward(pid_size + v.pid_size, -v.pid_size);
if (index > 0) {
memmove((void*)(pid_data + pid_start), (const void*)(pid_data + pid_start + v.pid_size), index * sizeof(T));
memmove((void *)(pid_data + pid_start), (const void *)(pid_data + pid_start + v.pid_size), index * sizeof(T));
}
}
newT(pid_data + pid_start + index, v.pid_data + v.pid_start, v.pid_size);
@@ -1453,12 +1413,14 @@ public:
ssize_t os = ssize_t(pid_size) - index;
alloc_forward(pid_size + init_list.size());
if (os > 0) {
memmove((void*)(pid_data + pid_start + index + init_list.size()), (const void*)(pid_data + pid_start + index), os * sizeof(T));
memmove((void *)(pid_data + pid_start + index + init_list.size()),
(const void *)(pid_data + pid_start + index),
os * sizeof(T));
}
} else {
alloc_backward(pid_size + init_list.size(), -init_list.size());
if (index > 0) {
memmove((void*)(pid_data + pid_start), (const void*)(pid_data + pid_start + init_list.size()), index * sizeof(T));
memmove((void *)(pid_data + pid_start), (const void *)(pid_data + pid_start + init_list.size()), index * sizeof(T));
}
}
newT(pid_data + pid_start + index, init_list.begin(), init_list.size());
@@ -1485,10 +1447,10 @@ public:
size_t os = pid_size - index - count;
deleteT(pid_data + pid_start + index, count);
if (os <= index) {
memmove((void*)(pid_data + pid_start + index), (const void*)(pid_data + pid_start + index + count), os * sizeof(T));
memmove((void *)(pid_data + pid_start + index), (const void *)(pid_data + pid_start + index + count), os * sizeof(T));
} else {
if (index > 0) {
memmove((void*)(pid_data + pid_start + count), (const void*)(pid_data + pid_start), index * sizeof(T));
memmove((void *)(pid_data + pid_start + count), (const void *)(pid_data + pid_start), index * sizeof(T));
}
pid_start += count;
}
@@ -1503,7 +1465,7 @@ public:
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
inline void swap(PIDeque<T> & other) {
piSwap<T*>(pid_data, other.pid_data);
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);
@@ -1548,23 +1510,18 @@ public:
//! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
//! Для сравнения элементов используется функция сравнения `comp`.
//! Функция сравнения, возвращает ​`true` если первый аргумент меньше второго.
//! Сигнатура функции сравнения должна быть эквивалентна следующей:
//! \code
//! bool comp(const T &a, const T &b);
//! \endcode
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
//! Функция обязана возвращать `false` для одинаковых элементов,
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`.
//! Функция сравнения, возвращает ​`true` если первый аргумент меньше
//! второго. Сигнатура функции сравнения должна быть эквивалентна следующей: \code bool comp(const T &a, const T &b); \endcode Сигнатура
//! не обязана содержать const &, однако, функция не может изменять переданные объекты. Функция обязана возвращать `false` для
//! одинаковых элементов, иначе это приведёт к неопределённому поведению программы и ошибкам памяти. Для сортировки используется функция
//! [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). Сложность сортировки `O(N·log(N))`.
//! \~\code
//! PIDeque<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
//! v.sort([](const int & a, const int & b){return a > b;});
//! piCout << v; // 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
//! \endcode
//! \~\sa \a sort()
inline PIDeque<T> & sort(std::function<bool(const T &a, const T &b)> comp) {
inline PIDeque<T> & sort(std::function<bool(const T & a, const T & b)> comp) {
std::sort(begin(), end(), comp);
return *this;
}
@@ -1587,9 +1544,9 @@ public:
//! \endcode
//! \~\sa \a reversed()
inline PIDeque<T> & reverse() {
size_t s2 = pid_size/2;
size_t s2 = pid_size / 2;
for (size_t i = 0; i < s2; ++i) {
piSwap<T>(pid_data[pid_start+i], pid_data[pid_start+pid_size-i-1]);
piSwap<T>(pid_data[pid_start + i], pid_data[pid_start + pid_size - i - 1]);
}
return *this;
}
@@ -1619,8 +1576,10 @@ public:
//! \~\sa \a resize()
inline PIDeque<T> & enlarge(ssize_t add_size, const T & e = T()) {
ssize_t ns = size_s() + add_size;
if (ns <= 0) clear();
else resize(size_t(ns), e);
if (ns <= 0)
clear();
else
resize(size_t(ns), e);
return *this;
}
@@ -1789,7 +1748,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a prepend(), \a push_front(), \a push_back(), \a insert()
inline PIDeque<T> & append(const T & e) {return push_back(e);}
inline PIDeque<T> & append(const T & e) { return push_back(e); }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
@@ -1797,7 +1756,7 @@ public:
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a append()
inline PIDeque<T> & append(T && e) {return push_back(std::move(e));}
inline PIDeque<T> & append(T && e) { return push_back(std::move(e)); }
//! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива.
@@ -1809,7 +1768,7 @@ public:
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIDeque<T> & append(std::initializer_list<T> init_list) {return push_back(init_list);}
inline PIDeque<T> & append(std::initializer_list<T> init_list) { return push_back(init_list); }
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
@@ -1822,7 +1781,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIDeque<T> & append(const PIDeque<T> & v) {return push_back(v);}
inline PIDeque<T> & append(const PIDeque<T> & v) { return push_back(v); }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
@@ -1833,7 +1792,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIDeque<T> & operator <<(const T & e) {return push_back(e);}
inline PIDeque<T> & operator<<(const T & e) { return push_back(e); }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
@@ -1844,7 +1803,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIDeque<T> & operator <<(T && e) {return push_back(std::move(e));}
inline PIDeque<T> & operator<<(T && e) { return push_back(std::move(e)); }
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
@@ -1855,7 +1814,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append(), \a push_back()
inline PIDeque<T> & operator <<(const PIDeque<T> & v) {return append(v);}
inline PIDeque<T> & operator<<(const PIDeque<T> & v) { return append(v); }
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
@@ -1912,9 +1871,7 @@ public:
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a push_front()
inline PIDeque<T> & push_front(const PIDeque<T> & v) {
return insert(0, v);
}
inline PIDeque<T> & push_front(const PIDeque<T> & v) { return insert(0, v); }
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
@@ -1926,9 +1883,7 @@ public:
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIDeque<T> & push_front(std::initializer_list<T> init_list) {
return insert(0, init_list);
}
inline PIDeque<T> & push_front(std::initializer_list<T> init_list) { return insert(0, init_list); }
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
@@ -1954,7 +1909,7 @@ public:
//! piCout << v; // {5, 4, 1, 2, 3}
//! \endcode
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIDeque<T> & prepend(const T & e) {return push_front(e);}
inline PIDeque<T> & prepend(const T & e) { return push_front(e); }
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
@@ -1962,7 +1917,7 @@ public:
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a prepend()
inline PIDeque<T> & prepend(T && e) {return push_front(std::move(e));}
inline PIDeque<T> & prepend(T && e) { return push_front(std::move(e)); }
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
@@ -1975,7 +1930,7 @@ public:
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a prepend()
inline PIDeque<T> & prepend(const PIDeque<T> & v) {return push_front(v);}
inline PIDeque<T> & prepend(const PIDeque<T> & v) { return push_front(v); }
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
@@ -1987,7 +1942,7 @@ public:
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIDeque<T> & prepend(std::initializer_list<T> init_list) {return push_front(init_list);}
inline PIDeque<T> & prepend(std::initializer_list<T> init_list) { return push_front(init_list); }
//! \~english Remove one element from the end of the array.
//! \~russian Удаляет один элемент с конца массива.
@@ -2071,7 +2026,7 @@ public:
//! piCout << v2; // {1, 2, 3}
//! \endcode
//! \~\sa \a map()
template <typename ST>
template<typename ST>
inline PIDeque<ST> toType() const {
PIDeque<ST> ret(pid_size);
ret.reserve(pid_size);
@@ -2116,7 +2071,7 @@ public:
//! \~\sa \a filter()
inline PIDeque<T> filterReverse(std::function<bool(const T & e)> test) const {
PIDeque<T> ret;
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
if (test(pid_data[i])) ret << pid_data[i];
}
return ret;
@@ -2127,7 +2082,7 @@ public:
//! \~\sa \a filterReverse()
inline PIDeque<T> filterReverseIndexed(std::function<bool(size_t index, const T & e)> test) const {
PIDeque<T> ret;
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
if (test(i - pid_start, pid_data[i])) ret << pid_data[i];
}
return ret;
@@ -2196,7 +2151,7 @@ public:
//! \~russian Аналогично \a forEach() но от конца до начала (справа на лево).
//! \~\sa \a forEach()
inline void forEachReverse(std::function<void(const T & e)> f) const {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(pid_data[i]);
}
}
@@ -2205,7 +2160,7 @@ public:
//! \~russian Аналогично \a forEachReverse(), но позволяет изменять элементы массива.
//! \~\sa \a forEach(), \a forEachReverse()
inline PIDeque<T> & forEachReverse(std::function<void(T & e)> f) {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(pid_data[i]);
}
return *this;
@@ -2215,7 +2170,7 @@ public:
//! \~russian Аналогично \a forEachIndexed() но от конца до начала (справа на лево).
//! \~\sa \a forEachIndexed(), \a forEachReverse(), \a forEach()
inline void forEachReverseIndexed(std::function<void(size_t index, const T & e)> f) const {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(i - pid_start, pid_data[i]);
}
}
@@ -2224,7 +2179,7 @@ public:
//! \~russian Аналогично \a forEachReverseIndexed(), но позволяет изменять элементы массива.
//! \~\sa \a forEachReverseIndexed(), \a forEachIndexed(), \a forEachReverse(), \a forEach()
inline PIDeque<T> & forEachReverseIndexed(std::function<void(size_t index, T & e)> f) {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(i - pid_start, pid_data[i]);
}
return *this;
@@ -2247,9 +2202,10 @@ public:
//! piCout << sl; // {"1", "2", "3"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST>
template<typename ST>
inline PIDeque<ST> map(std::function<ST(const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size);
PIDeque<ST> ret;
ret.reserve(pid_size);
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
ret << f(pid_data[i]);
}
@@ -2264,9 +2220,10 @@ public:
//! piCout << sl; // {"0", "1", "2"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
template<typename ST>
inline PIDeque<ST> mapIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size);
PIDeque<ST> ret;
ret.reserve(pid_size);
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
ret << f(i - pid_start, pid_data[i]);
}
@@ -2281,10 +2238,11 @@ public:
//! piCout << sl; // {"3", "2", "1"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
template<typename ST>
inline PIDeque<ST> mapReverse(std::function<ST(const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
PIDeque<ST> ret;
ret.reserve(pid_size);
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret << f(pid_data[i]);
}
return ret;
@@ -2298,10 +2256,11 @@ public:
//! piCout << sl; // {"2", "1", "0"}
//! \endcode
//! \~\sa \a mapReverse()
template <typename ST>
template<typename ST>
inline PIDeque<ST> mapReverseIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
PIDeque<ST> ret;
ret.reserve(pid_size);
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret << f(size_t(i) - pid_start, pid_data[i]);
}
return ret;
@@ -2348,7 +2307,7 @@ public:
//! piCout << s; // 15
//! \endcode
//! \~\sa \a reduceIndexed(), \a reduceReverse(), \a reduceReverseIndexed(), \a forEach(), \a map()
template <typename ST>
template<typename ST>
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
@@ -2360,7 +2319,7 @@ public:
//! \~english Same as \a reduce() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduce()
template <typename ST>
template<typename ST>
inline ST reduceIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
@@ -2372,10 +2331,10 @@ public:
//! \~english Same as \a reduce() but from end to begin (from right to left).
//! \~russian Аналогично \a reduce() но от конца до начала (справа на лево).
//! \~\sa \a reduce()
template <typename ST>
template<typename ST>
inline ST reduceReverse(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret = f(pid_data[i], ret);
}
return ret;
@@ -2384,10 +2343,10 @@ public:
//! \~english Same as \a reduceReverse() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduceReverse()
template <typename ST>
template<typename ST>
inline ST reduceReverseIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret = f(size_t(i) - pid_start, pid_data[i], ret);
}
return ret;
@@ -2416,22 +2375,22 @@ public:
PIDeque<PIDeque<T>> ret;
if (isEmpty()) return ret;
#ifndef NDEBUG
if (rows*cols != pid_size) {
if (rows * cols != pid_size) {
printf("error with PIDeque<%s>::reshape\n", __PIP_TYPENAME__(T));
}
#endif
assert(rows*cols == pid_size);
assert(rows * cols == pid_size);
ret.expand(rows);
if (order == ReshapeByRow) {
for (size_t r = 0; r < rows; r++) {
ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols);
ret[r] = PIDeque<T>(&(pid_data[r * cols]), cols);
}
}
if (order == ReshapeByColumn) {
for (size_t r = 0; r < rows; r++) {
ret[r].expand(cols);
for (size_t c = 0; c < cols; c++) {
ret[r][c] = pid_data[c*rows + r];
ret[r][c] = pid_data[c * rows + r];
}
}
}
@@ -2452,9 +2411,7 @@ public:
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if<
std::is_same<T, PIDeque<C>>::value
, int>::type = 0>
template<typename C, typename std::enable_if<std::is_same<T, PIDeque<C>>::value, int>::type = 0>
inline PIDeque<C> flatten(ReshapeOrder order = ReshapeByRow) const {
PIDeque<C> ret;
if (isEmpty()) return ret;
@@ -2495,9 +2452,7 @@ public:
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if<
std::is_same<T, PIDeque<C>>::value
, int>::type = 0>
template<typename C, typename std::enable_if<std::is_same<T, PIDeque<C>>::value, int>::type = 0>
inline PIDeque<PIDeque<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
PIDeque<C> fl = flatten<C>();
return fl.reshape(rows, cols, order);
@@ -2514,11 +2469,11 @@ public:
PIDeque<PIDeque<T>> ret;
if (isEmpty()) return ret;
size_t start = 0;
ssize_t ci = indexOf(separator, start);
ssize_t ci = indexOf(separator, start);
while (ci >= 0) {
ret << PIDeque<T>(pid_data + pid_start + start, ci - start);
start = ci + 1;
ci = indexOf(separator, start);
ci = indexOf(separator, start);
}
if (start < pid_size) {
ret << PIDeque<T>(pid_data + pid_start + start, pid_size - start);
@@ -2534,9 +2489,9 @@ public:
if (isEmpty() || sz == 0) return ret;
size_t ch = pid_size / sz;
for (size_t i = 0; i < ch; ++i) {
ret << PIDeque<T>(pid_data + pid_start + sz*i, sz);
ret << PIDeque<T>(pid_data + pid_start + sz * i, sz);
}
size_t t = ch*sz;
size_t t = ch * sz;
if (t < pid_size) {
ret << PIDeque<T>(pid_data + pid_start + t, pid_size - t);
}
@@ -2565,16 +2520,16 @@ public:
if (index >= pid_size || count == 0) return ret;
if (index + count > pid_size) count = pid_size - index;
ret.alloc_forward(count);
memcpy((void*)(ret.pid_data + ret.pid_start), (const void*)(pid_data + pid_start + index), count * sizeof(T));
memcpy((void *)(ret.pid_data + ret.pid_start), (const void *)(pid_data + pid_start + index), count * sizeof(T));
size_t os = pid_size - index - count;
if (os <= index) {
if (os > 0) {
memmove((void*)(pid_data + pid_start + index), (const void*)(pid_data + pid_start + index + count), os * sizeof(T));
memmove((void *)(pid_data + pid_start + index), (const void *)(pid_data + pid_start + index + count), os * sizeof(T));
}
} else {
if (index > 0) {
memmove((void*)(pid_data + pid_start + count), (const void*)(pid_data + pid_start), index * sizeof(T));
memmove((void *)(pid_data + pid_start + count), (const void *)(pid_data + pid_start), index * sizeof(T));
}
pid_start += count;
}
@@ -2584,10 +2539,10 @@ public:
private:
inline void _reset() {
pid_size = 0;
pid_size = 0;
pid_rsize = 0;
pid_start = 0;
pid_data = nullptr;
pid_data = nullptr;
}
inline size_t asize(ssize_t s) {
@@ -2595,15 +2550,14 @@ private:
if (pid_rsize * 2 >= size_t(s) && pid_rsize < size_t(s)) {
return pid_rsize * 2;
}
size_t t = _PIContainerConstants<T>::minCountPoT();
size_t t = _PIContainerConstants<T>::minCountPoT();
size_t s_ = s - 1;
while (s_ >> t) ++t;
while (s_ >> t)
++t;
return (1 << t);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void newT(T * dst, const T * src, size_t s) {
PIINTROSPECTION_CONTAINER_USED(T, s)
for (size_t i = 0; i < s; ++i) {
@@ -2611,17 +2565,13 @@ private:
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void newT(T * dst, const T * src, size_t s) {
PIINTROSPECTION_CONTAINER_USED(T, s)
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
memcpy((void *)(dst), (const void *)(src), s * sizeof(T));
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
if (d != nullptr) {
@@ -2631,56 +2581,42 @@ private:
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T * to, const T & from) {
new(to)T(from);
new (to) T(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T * to, T && from) {
new(to)T(std::move(from));
new (to) T(std::move(from));
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T1 * to, const T & from) {
(*to) = from;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T * to, T && from) {
(*to) = std::move(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementDelete(T & from) {
from.~T();
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementDelete(T & from) {}
inline void dealloc() {
if (pid_data != nullptr) {
free((void*)pid_data);
free((void *)pid_data);
pid_data = nullptr;
}
}
@@ -2691,7 +2627,7 @@ private:
if (pid_start < (pid_size * 2) || ssize_t(pid_start) > (ssize_t(pid_rsize) - (ssize_t(pid_size) * 2))) {
size_t ns = (pid_rsize - pid_size) / 2;
if (pid_start != ns) {
memmove((void*)(pid_data + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
memmove((void *)(pid_data + ns), (const void *)(pid_data + pid_start), pid_size * sizeof(T));
pid_start = ns;
}
}
@@ -2699,7 +2635,7 @@ private:
} else {
size_t ns = (pid_rsize - pid_size) / 2;
if (pid_start != ns) {
memmove((void*)(pid_data + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
memmove((void *)(pid_data + ns), (const void *)(pid_data + pid_start), pid_size * sizeof(T));
pid_start = ns;
}
}
@@ -2711,18 +2647,18 @@ private:
if (pid_start > 0) checkMove();
return;
}
pid_size = new_size;
pid_size = new_size;
size_t as = asize(pid_start + new_size);
if (as != pid_rsize) {
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T)));
PIINTROSPECTION_CONTAINER_ALLOC(T, (as - pid_rsize))
T * p_d = (T *)(realloc((void *)(pid_data), as * sizeof(T)));
#ifndef NDEBUG
if (!p_d) {
printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
}
#endif
assert(p_d);
pid_data = p_d;
pid_data = p_d;
pid_rsize = as;
}
}
@@ -2735,14 +2671,14 @@ private:
as = pid_rsize;
}
if (as > pid_rsize) {
T * td = (T*)(malloc(as * sizeof(T)));
T * td = (T *)(malloc(as * sizeof(T)));
size_t ns = pid_start + as - pid_rsize;
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
PIINTROSPECTION_CONTAINER_ALLOC(T, (as - pid_rsize))
if (pid_rsize > 0 && pid_data != 0) {
memcpy((void*)(td + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
memcpy((void *)(td + ns), (const void *)(pid_data + pid_start), pid_size * sizeof(T));
dealloc();
}
pid_data = td;
pid_data = td;
pid_rsize = as;
pid_start = ns;
}
@@ -2754,7 +2690,7 @@ private:
inline void expand(size_t new_size, const T & e = T()) {
size_t os = pid_size;
alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, e);
}
@@ -2763,14 +2699,14 @@ private:
inline void expand(size_t new_size, std::function<T(size_t i)> f) {
size_t os = pid_size;
alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, f(i));
}
}
T * pid_data = nullptr;
size_t pid_size = 0;
T * pid_data = nullptr;
size_t pid_size = 0;
size_t pid_rsize = 0;
size_t pid_start = 0;
};
@@ -2780,7 +2716,7 @@ private:
//! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream).
//! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream).
template<typename T>
inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {
inline std::ostream & operator<<(std::ostream & s, const PIDeque<T> & v) {
s << "{";
for (size_t i = 0; i < v.size(); ++i) {
s << v[i];
@@ -2796,7 +2732,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename T>
inline PICout operator <<(PICout s, const PIDeque<T> & v) {
inline PICout operator<<(PICout s, const PIDeque<T> & v) {
s.space();
s.saveAndSetControls(0);
s << "{";
@@ -2810,7 +2746,9 @@ inline PICout operator <<(PICout s, const PIDeque<T> & v) {
}
template<typename T>
inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);}
inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {
f.swap(s);
}
#endif // PIDEQUE_H
+181 -188
View File
@@ -13,36 +13,40 @@
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/*
PIP - Platform Independent Primitives
Associative array with custom types of key and value
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Associative array with custom types of key and value
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMAP_H
#define PIMAP_H
#include "pivector.h"
#include "pideque.h"
#include "pipair.h"
#include "pivector.h"
template <typename Key, typename T> class PIMapIteratorConst;
template <typename Key, typename T> class PIMapIteratorConstReverse;
template <typename Key, typename T> class PIMapIterator;
template <typename Key, typename T> class PIMapIteratorReverse;
template<typename Key, typename T>
class PIMapIteratorConst;
template<typename Key, typename T>
class PIMapIteratorConstReverse;
template<typename Key, typename T>
class PIMapIterator;
template<typename Key, typename T>
class PIMapIteratorReverse;
//! \addtogroup Containers
@@ -74,16 +78,21 @@ template <typename Key, typename T> class PIMapIteratorReverse;
//! по которым их можно найти, которыми могут выступать значения любого типа.
//! \a operator [] позволяет получить доступ к элементу по ключу,
//! и если такого эелемента не было, то он будет создан.
template <typename Key, typename T>
template<typename Key, typename T>
class PIMap {
template <typename Key1, typename T1> friend class PIMapIteratorConst;
template <typename Key1, typename T1> friend class PIMapIteratorConstReverse;
template <typename Key1, typename T1> friend class PIMapIterator;
template <typename Key1, typename T1> friend class PIMapIteratorReverse;
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMap<Key1, T1> & v);
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMap<Key1, T1> & v);
template<typename Key1, typename T1>
friend class PIMapIteratorConst;
template<typename Key1, typename T1>
friend class PIMapIteratorConstReverse;
template<typename Key1, typename T1>
friend class PIMapIterator;
template<typename Key1, typename T1>
friend class PIMapIteratorReverse;
template<typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMap<Key1, T1> & v);
template<typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMap<Key1, T1> & v);
public:
typedef T mapped_type;
typedef Key key_type;
@@ -95,11 +104,11 @@ public:
//! \~english Copy constructor.
//! \~russian Копирующий конструктор.
inline PIMap(const PIMap<Key, T> & other) : pim_content(other.pim_content), pim_index(other.pim_index) {}
inline PIMap(const PIMap<Key, T> & other): pim_content(other.pim_content), pim_index(other.pim_index) {}
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
inline PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
inline PIMap(PIMap<Key, T> && other): pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
//! \~english Contructs map from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
@@ -118,150 +127,158 @@ public:
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
inline PIMap<Key, T> & operator=(const PIMap<Key, T> & other) {
if (this == &other) return *this;
clear();
pim_content = other.pim_content;
pim_index = other.pim_index;
pim_index = other.pim_index;
return *this;
}
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
inline PIMap<Key, T> & operator=(PIMap<Key, T> && other) {
swap(other);
return *this;
}
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(nullptr), pos(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
inline PIPair<Key, T> operator *() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));
const Key & key() const { return const_cast<PIMap<Key, T> *>(parent)->_key(pos); }
T & value() { return const_cast<PIMap<Key, T> *>(parent)->_value(pos); }
inline PIPair<Key, T> operator*() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> *>(parent)->_key(pos), 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);}
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(nullptr), pos(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);}
inline PIPair<Key, T> operator *() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));
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); }
inline PIPair<Key, T> operator*() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> *>(parent)->_key(pos), 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);}
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 {
friend class PIMap<Key, T>;
private:
const_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
const PIMap<Key, T> * parent;
ssize_t pos;
public:
const_iterator(): parent(nullptr), pos(0) {}
const value_type operator *() const {return parent->_pair(pos);}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
const 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 const_iterator & it) const {return (pos == it.pos);}
bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
const value_type operator*() const { return parent->_pair(pos); }
const Key & key() const { return const_cast<PIMap<Key, T> *>(parent)->_key(pos); }
const 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 const_iterator & it) const { return (pos == it.pos); }
bool operator!=(const const_iterator & it) const { return (pos != it.pos); }
};
class const_reverse_iterator {
friend class PIMap<Key, T>;
private:
const_reverse_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
const PIMap<Key, T> * parent;
ssize_t pos;
public:
const_reverse_iterator(): parent(nullptr), pos(0) {}
const value_type operator *() const {return parent->_pair(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);}
const value_type operator*() const { return parent->_pair(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); }
};
//! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент.
inline iterator begin() {return iterator(this, 0);}
inline iterator begin() { return iterator(this, 0); }
//! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
inline iterator end() {return iterator(this, size());}
inline iterator end() { return iterator(this, size()); }
inline const_iterator begin() const {return const_iterator(this, 0);}
inline const_iterator end() const {return const_iterator(this, size());}
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator end() const { return const_iterator(this, size()); }
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
inline reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);}
inline reverse_iterator rbegin() { return reverse_iterator(this, size() - 1); }
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент,
//! следующий за последним элементом.
inline reverse_iterator rend() {return reverse_iterator(this, -1);}
inline reverse_iterator rend() { return reverse_iterator(this, -1); }
inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);}
inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(this, size() - 1); }
inline const_reverse_iterator rend() const { return const_reverse_iterator(this, -1); }
//! \relatesalso PIMapIteratorConst
inline PIMapIteratorConst<Key, T> makeIterator() const {return PIMapIteratorConst<Key, T>(*this);}
inline PIMapIteratorConst<Key, T> makeIterator() const { return PIMapIteratorConst<Key, T>(*this); }
//! \relatesalso PIMapIterator
inline PIMapIterator<Key, T> makeIterator() {return PIMapIterator<Key, T>(*this);}
inline PIMapIterator<Key, T> makeIterator() { return PIMapIterator<Key, T>(*this); }
//! \relatesalso PIMapIteratorConstReverse
inline PIMapIteratorConstReverse<Key, T> makeReverseIterator() const {return PIMapIteratorConstReverse<Key, T>(*this);}
inline PIMapIteratorConstReverse<Key, T> makeReverseIterator() const { return PIMapIteratorConstReverse<Key, T>(*this); }
//! \relatesalso PIMapIteratorReverse
inline PIMapIteratorReverse<Key, T> makeReverseIterator() {return PIMapIteratorReverse<Key, T>(*this);}
inline PIMapIteratorReverse<Key, T> makeReverseIterator() { return PIMapIteratorReverse<Key, T>(*this); }
//! \~english Number of elements in the container.
//! \~russian Количество элементов массива.
//! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t size() const {return pim_content.size();}
inline size_t size() const { return pim_content.size(); }
//! \~english Number of elements in the container as signed value.
//! \~russian Количество элементов массива в виде знакового числа.
//! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline int size_s() const {return pim_content.size_s();}
inline int size_s() const { return pim_content.size_s(); }
//! \~english Same as \a size().
//! \~russian Синоним \a size().
//! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t length() const {return pim_content.size();}
inline size_t length() const { return pim_content.size(); }
//! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли массив.
@@ -269,7 +286,7 @@ public:
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если массив пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isEmpty() const {return (pim_content.size() == 0);}
inline bool isEmpty() const { return (pim_content.size() == 0); }
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли массив.
@@ -277,7 +294,7 @@ public:
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если массив не пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isNotEmpty() const {return (pim_content.size() > 0);}
inline bool isNotEmpty() const { return (pim_content.size() > 0); }
//! \~english Full access to element key `key`.
@@ -299,7 +316,7 @@ public:
//! piCout << m; // {огурец: 350, лук: 25}
//! \endcode
//! \~\sa \a insert(), \a value(), \a key()
inline T & operator [](const Key & key) {
inline T & operator[](const Key & key) {
bool f(false);
ssize_t i = _find(key, f);
if (f) return pim_content[pim_index[i].index];
@@ -311,7 +328,7 @@ public:
//! \~english Same as \a value().
//! \~russian Синоним \a value().
//! \~\sa \a operator[](), \a value(), \a key()
inline T at(const Key & key) const {return value(key);}
inline T at(const Key & key) const { return value(key); }
//! \~english Remove element with key `key` from the array and return it.
//! \~russian Удаляет элемент с ключом `key` из массива и возвращает его.
@@ -323,10 +340,10 @@ public:
_remove(i);
return ret;
}
//! \~english Inserts all elements in array `other` to this array with overwrite.
//! \~russian Вставляет все элементы `other` этот массив с перезаписью.
inline PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
inline PIMap<Key, T> & operator<<(const PIMap<Key, T> & other) {
#ifndef NDEBUG
if (&other == this) {
printf("error with PIMap<%s, %s>::<<\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
@@ -351,28 +368,23 @@ public:
//! \~english Compare operator with array `m`.
//! \~russian Оператор сравнения с массивом `m`.
inline bool operator ==(const PIMap<Key, T> & m) const {
return (pim_content == m.pim_content && pim_index == m.pim_index);
}
inline bool operator==(const PIMap<Key, T> & m) const { return (pim_content == m.pim_content && pim_index == m.pim_index); }
//! \~english Compare operator with array `m`.
//! \~russian Оператор сравнения с массивом `m`.
inline bool operator !=(const PIMap<Key, T> & m) const {
return (pim_content != m.pim_content || pim_index != m.pim_index);
}
inline bool operator!=(const PIMap<Key, T> & m) const { return (pim_content != m.pim_content || pim_index != m.pim_index); }
//! \~english Tests if element with key `key` exists in the array.
//! \~russian Проверяет наличие элемента с ключом `key` в массиве.
inline bool contains(const Key & key) const {
bool f(false); _find(key, f);
bool f(false);
_find(key, f);
return f;
}
//! \~english Tests if element with value `value` exists in the array.
//! \~russian Проверяет наличие элемента со значением `value` в массиве.
inline bool containsValue(const T & value) const {
return pim_content.contains(value);
}
inline bool containsValue(const T & value) const { return pim_content.contains(value); }
//! \~english Attempts to allocate memory for at least `new_size` elements.
//! \~russian Резервируется память под как минимум `new_size` элементов.
@@ -407,9 +419,7 @@ public:
//! \~english Same as \a remove().
//! \~russian Синоним функции \a remove().
inline PIMap<Key, T> & erase(const Key & key) {
return remove(key);
}
inline PIMap<Key, T> & erase(const Key & key) { return remove(key); }
//! \~english Clear array, remove all elements.
@@ -424,7 +434,7 @@ public:
pim_index.clear();
return *this;
}
//! \~english Swaps array `v` other with this array.
//! \~russian Меняет местами массив `v` с этим массивом.
//! \~\details
@@ -507,7 +517,7 @@ public:
//! \~english Returns an array of values of all elements
//! \~russian Возвращает массив значений всех эелметнов
inline PIVector<T> values() const {return pim_content;}
inline PIVector<T> values() const { return pim_content; }
//! \~english Returns the key of the first element
//! whose value matches `value` or `default_` if there is no such element.
@@ -545,9 +555,10 @@ public:
//! of calling a provided function `PIPair<Key2, T2> f(const Key & key, const T & value)` on every element in the calling array.
//! \~russian Создаёт новый словарь PIMap<Key2, T2> с результатом вызова указанной функции
//! `PIPair<Key2, T2> f(const Key & key, const T & value)` для каждого элемента массива.
template <typename Key2, typename T2>
template<typename Key2, typename T2>
inline PIMap<Key2, T2> map(std::function<PIPair<Key2, T2>(const Key & key, const T & value)> f) const {
PIMap<Key2, T2> ret; ret.reserve(size());
PIMap<Key2, T2> ret;
ret.reserve(size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret.insert(f(pim_index[i].key, pim_content[pim_index[i].index]));
}
@@ -558,15 +569,16 @@ public:
//! of calling a provided function `ST f(const Key & key, const T & value)` on every element in the calling array.
//! \~russian Создаёт новый массив PIVector<ST> с результатом вызова указанной функции
//! `ST f(const Key & key, const T & value)` для каждого элемента массива.
template <typename ST>
template<typename ST>
inline PIVector<ST> map(std::function<ST(const Key & key, const T & value)> f) const {
PIVector<ST> ret; ret.reserve(size());
PIVector<ST> ret;
ret.reserve(size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret << f(pim_index[i].key, pim_content[pim_index[i].index]);
}
return ret;
}
//! \~english Returns a new array with all elements
//! that pass the test implemented by the provided function `bool test(const Key & key, const T & value)`.
//! \~russian Возвращает новый массив со всеми элементами,
@@ -587,24 +599,29 @@ private:
MapIndex(Key && k, size_t i = 0): key(std::move(k)), index(i) {}
Key key;
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; }
bool operator<(const MapIndex & s) const { return key < s.key; }
bool operator>(const MapIndex & s) const { return key > s.key; }
};
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
template<typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
template<typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
inline ssize_t _binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
ssize_t mid;
while (first <= last) {
mid = (first + last) / 2;
if (key > pim_index[mid].key) first = mid + 1;
else if (key < pim_index[mid].key) last = mid - 1;
else {found = true; return mid;}
if (key > pim_index[mid].key)
first = mid + 1;
else if (key < pim_index[mid].key)
last = mid - 1;
else {
found = true;
return mid;
}
}
found = false;
return first;
@@ -636,14 +653,14 @@ private:
return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
}
inline Key & _key(ssize_t index) {return pim_index[index].key;}
inline Key & _key(ssize_t index) { return pim_index[index].key; }
inline const Key & _key(ssize_t index) const {return pim_index[index].key;}
inline const Key & _key(ssize_t index) const { return pim_index[index].key; }
inline T & _value(ssize_t index) {return pim_content[pim_index[index].index];}
inline T & _value(ssize_t index) { return pim_content[pim_index[index].index]; }
inline const T & _value(ssize_t index) const { return pim_content[pim_index[index].index]; }
inline const T & _value(ssize_t index) const {return pim_content[pim_index[index].index];}
PIVector<T> pim_content;
PIDeque<MapIndex> pim_index;
@@ -678,33 +695,28 @@ private:
//! // 2 two
//! // 4 four
//! \endcode
template <typename Key, typename T>
template<typename Key, typename T>
class PIMapIteratorConst {
typedef PIMap<Key, T> MapType;
public:
inline PIMapIteratorConst(const PIMap<Key, T> & map): m(map), pos(-1) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
inline const Key & key() const { return m._key(pos); }
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline const T & value() const {
return m._value(pos);
}
inline const T & value() const { return m._value(pos); }
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
return pos < (m.size_s() - 1);
}
inline bool hasNext() const { return pos < (m.size_s() - 1); }
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
@@ -717,9 +729,8 @@ public:
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
pos = -1;
}
inline void reset() { pos = -1; }
private:
const MapType & m;
ssize_t pos;
@@ -754,32 +765,27 @@ private:
//! // 2 two
//! // 1 one
//! \endcode
template <typename Key, typename T>
template<typename Key, typename T>
class PIMapIteratorConstReverse {
typedef PIMap<Key, T> MapType;
public:
inline PIMapIteratorConstReverse(const PIMap<Key, T> & map): m(map), pos(m.size_s()) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
inline const Key & key() const { return m._key(pos); }
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline const T & value() const {
return m._value(pos);
}
inline const T & value() const { return m._value(pos); }
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
return pos > 0;
}
inline bool hasNext() const { return pos > 0; }
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
@@ -792,9 +798,8 @@ public:
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
pos = m.size_s();
}
inline void reset() { pos = m.size_s(); }
private:
const MapType & m;
ssize_t pos;
@@ -830,32 +835,27 @@ private:
//! // 2 two_!
//! // 4 four_!
//! \endcode
template <typename Key, typename T>
template<typename Key, typename T>
class PIMapIterator {
typedef PIMap<Key, T> MapType;
public:
inline PIMapIterator(PIMap<Key, T> & map): m(map), pos(-1) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
inline const Key & key() const { return m._key(pos); }
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline T & value() {
return m._value(pos);
}
inline T & value() { return m._value(pos); }
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
return pos < (m.size_s() - 1);
}
inline bool hasNext() const { return pos < (m.size_s() - 1); }
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
@@ -868,9 +868,8 @@ public:
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
pos = -1;
}
inline void reset() { pos = -1; }
private:
MapType & m;
ssize_t pos;
@@ -906,32 +905,27 @@ private:
//! // 2 two_!
//! // 1 one_!
//! \endcode
template <typename Key, typename T>
template<typename Key, typename T>
class PIMapIteratorReverse {
typedef PIMap<Key, T> MapType;
public:
inline PIMapIteratorReverse(PIMap<Key, T> & map): m(map), pos(m.size_s()) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
inline const Key & key() const { return m._key(pos); }
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline T & value() {
return m._value(pos);
}
inline T & value() { return m._value(pos); }
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
return pos > 0;
}
inline bool hasNext() const { return pos > 0; }
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
@@ -944,9 +938,8 @@ public:
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
pos = m.size_s();
}
inline void reset() { pos = m.size_s(); }
private:
MapType & m;
ssize_t pos;
@@ -957,12 +950,11 @@ private:
//! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream).
//! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream).
template<typename Key, typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v) {
inline std::ostream & operator<<(std::ostream & s, const PIMap<Key, Type> & v) {
s << "{";
bool first = true;
for (typename PIMap<Key, Type>::const_iterator i = v.begin(); i != v.end(); ++i) {
if (!first)
s << ", ";
if (!first) s << ", ";
first = false;
s << i.key() << ": " << i.value();
}
@@ -976,14 +968,13 @@ inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v)
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename Key, typename Type>
inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
inline PICout operator<<(PICout s, const PIMap<Key, Type> & v) {
s.space();
s.saveAndSetControls(0);
s << "{";
bool first = true;
for (typename PIMap<Key, Type>::const_iterator i = v.begin(); i != v.end(); ++i) {
if (!first)
s << ", ";
if (!first) s << ", ";
first = false;
s << i.key() << ": " << i.value();
}
@@ -993,7 +984,9 @@ inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
}
template<typename Key, typename Type>
inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {
f.swap(s);
}
#endif // PIMAP_H
+27 -28
View File
@@ -13,22 +13,22 @@
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/*
PIP - Platform Independent Primitives
pair
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
pair
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIPAIR_H
@@ -48,29 +48,28 @@
template<typename Type0, typename Type1>
class PIPair {
public:
//! \~english Constructs an empty PIPair.
//! \~russian Создает пустой PIPair.
PIPair() : first(), second() {}
PIPair(): first(), second() {}
//! \~english Constructs PIPair from [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple).
//! \~russian Создает PIPair из [std::tuple](https://ru.cppreference.com/w/cpp/utility/tuple).
PIPair(std::tuple<Type0, Type1> tuple) {
first = std::get<0>(tuple);
first = std::get<0>(tuple);
second = std::get<1>(tuple);
}
//! \~english Constructs PIPair from values `value0` and `value1`.
//! \~russian Создает PIPair из `value0` и `value1`.
PIPair(const Type0 & value0, const Type1 & value1) {
first = value0;
first = value0;
second = value1;
}
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
PIPair(Type0 && value0, Type1 && value1) {
first = std::move(value0);
first = std::move(value0);
second = std::move(value1);
}
@@ -86,20 +85,20 @@ public:
//! \~english Compare operator with PIPair.
//! \~russian Оператор сравнения с PIPair.
template<typename Type0, typename Type1>
inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {
inline bool operator==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {
return (value0.first == value1.first) && (value0.second == value1.second);
}
//! \~english Compare operator with PIPair.
//! \~russian Оператор сравнения с PIPair.
template<typename Type0, typename Type1>
inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {
inline bool operator!=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {
return (value0.first != value1.first) || (value0.second != value1.second);
}
#ifdef PIP_STD_IOSTREAM
template<typename Type0, typename Type1>
inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {
inline std::ostream & operator<<(std::ostream & s, const PIPair<Type0, Type1> & v) {
s << "(" << v.first << ", " << v.second << ")";
return s;
}
@@ -109,7 +108,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> &
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {
inline PICout operator<<(PICout s, const PIPair<Type0, Type1> & v) {
s.space();
s.saveAndSetControls(0);
s << "(" << v.first << ", " << v.second << ")";
@@ -125,18 +124,18 @@ inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {
//! auto p = createPIPair(1, 'a');
//! piCout << p; // (1, a)
//! \endcode
template< class T1, class T2 >
PIPair<T1,T2> createPIPair(const T1 & f, const T2 & s) {
return PIPair<T1,T2>(f, s);
template<class T1, class T2>
PIPair<T1, T2> createPIPair(const T1 & f, const T2 & s) {
return PIPair<T1, T2>(f, s);
}
//! \~english Creates \a PIPair object, deducing the target type from the types of arguments.
//! \~russian Создает \a PIPair выводя типы из аргументов.
//! \sa \a createPIPair()
template< class T1, class T2 >
PIPair<T1,T2> createPIPair(T1 && f, T2 && s) {
return PIPair<T1,T2>(std::move(f), std::move(s));
template<class T1, class T2>
PIPair<T1, T2> createPIPair(T1 && f, T2 && s) {
return PIPair<T1, T2>(std::move(f), std::move(s));
}
+28 -23
View File
@@ -13,22 +13,22 @@
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/*
PIP - Platform Independent Primitives
Queue container
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Queue container
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIQUEUE_H
@@ -53,18 +53,23 @@
template<typename T>
class PIQueue: public PIDeque<T> {
public:
//! \~english Constructs an empty array.
//! \~russian Создает пустой массив.
PIQueue() {}
//! \~english Puts an element on the queue.
//! \~russian Кладёт элемент в очередь.
PIDeque<T> & enqueue(const T & v) {PIDeque<T>::push_front(v); return *this;}
PIDeque<T> & enqueue(const T & v) {
PIDeque<T>::push_front(v);
return *this;
}
//! \~english Move an element on the queue.
//! \~russian Перемещает элемент в очередь.
PIDeque<T> & enqueue(T && v) {PIDeque<T>::push_front(std::move(v)); return *this;}
PIDeque<T> & enqueue(T && v) {
PIDeque<T>::push_front(std::move(v));
return *this;
}
//! \~english Retrieves and returns an element from the queue.
//! \~russian Забирает и возвращает элемент из очереди.
@@ -74,7 +79,7 @@ public:
//! Otherwise will be undefined behavior.
//! \~russian Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T dequeue() {return PIDeque<T>::take_back();}
T dequeue() { return PIDeque<T>::take_back(); }
//! \~english Head element of the queue.
//! \~russian Головной (верхний) элемент очереди.
@@ -86,8 +91,8 @@ public:
//! \~russian Возвращает ссылку на головной (верхний) элемент очереди.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T & head() {return PIDeque<T>::back();}
const T & head() const {return PIDeque<T>::back();}
T & head() { return PIDeque<T>::back(); }
const T & head() const { return PIDeque<T>::back(); }
//! \~english Tail element of the queue.
//! \~russian Хвостовой (нижний) элемент очереди.
@@ -98,16 +103,16 @@ public:
//! \~russian Возвращает ссылку на хвостовой (нижний) элемент очереди.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T & tail() {return PIDeque<T>::front();}
const T & tail() const {return PIDeque<T>::front();}
T & tail() { return PIDeque<T>::front(); }
const T & tail() const { return PIDeque<T>::front(); }
//! \~english Converts \a PIQueue to \a PIVector.
//! \~russian Преобразует \a PIQueue в \a PIVector.
PIVector<T> toVector() const {return PIVector<T>(PIDeque<T>::data(), PIDeque<T>::size());}
PIVector<T> toVector() const { return PIVector<T>(PIDeque<T>::data(), PIDeque<T>::size()); }
//! \~english Converts \a PIQueue to \a PIDeque.
//! \~russian Преобразует \a PIQueue в \a PIDeque.
PIDeque<T> toDeque() const {return PIDeque<T>(*this);}
PIDeque<T> toDeque() const { return PIDeque<T>(*this); }
};
#endif // PIQUEUE_H
+98 -46
View File
@@ -1,25 +1,25 @@
/*! \file piset.h
* \brief Set container
*
*
* This file declare PISet
*/
*/
/*
PIP - Platform Independent Primitives
Set container
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Set container
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISET_H
@@ -34,25 +34,37 @@
* set with \a operator[] or with function \a find(). These function
* has logarithmic complexity.
*/
template <typename T>
template<typename T>
class PISet: public PIMap<T, uchar> {
typedef PIMap<T, uchar> _CSet;
public:
//! Contructs an empty set
PISet() {}
//! Contructs set with one element "value"
PISet(const T & value) {_CSet::insert(value, 0);}
PISet(const T & value) { _CSet::insert(value, 0); }
//! Contructs set with elements "v0" and "v1"
PISet(const T & v0, const T & v1) {_CSet::insert(v0, 0); _CSet::insert(v1, 0);}
PISet(const T & v0, const T & v1) {
_CSet::insert(v0, 0);
_CSet::insert(v1, 0);
}
//! Contructs set with elements "v0", "v1" and "v2"
PISet(const T & v0, const T & v1, const T & v2) {_CSet::insert(v0, 0); _CSet::insert(v1, 0); _CSet::insert(v2, 0);}
PISet(const T & v0, const T & v1, const T & v2) {
_CSet::insert(v0, 0);
_CSet::insert(v1, 0);
_CSet::insert(v2, 0);
}
//! Contructs set with elements "v0", "v1", "v2" and "v3"
PISet(const T & v0, const T & v1, const T & v2, const T & v3) {_CSet::insert(v0, 0); _CSet::insert(v1, 0); _CSet::insert(v2, 0); _CSet::insert(v3, 0);}
PISet(const T & v0, const T & v1, const T & v2, const T & v3) {
_CSet::insert(v0, 0);
_CSet::insert(v1, 0);
_CSet::insert(v2, 0);
_CSet::insert(v3, 0);
}
//! Contructs set from vector of elements
PISet(const PIVector<T> & values) {
@@ -71,16 +83,28 @@ public:
}
typedef T key_type;
PISet<T> & operator <<(const T & t) {_CSet::insert(t, 0); return *this;}
PISet<T> & operator <<(T && t) {_CSet::insert(std::move(t), 0); return *this;}
PISet<T> & operator <<(const PISet<T> & other) {(*(_CSet*)this) << *((_CSet*)&other); return *this;}
PISet<T> & operator<<(const T & t) {
_CSet::insert(t, 0);
return *this;
}
PISet<T> & operator<<(T && t) {
_CSet::insert(std::move(t), 0);
return *this;
}
PISet<T> & operator<<(const PISet<T> & other) {
(*(_CSet *)this) << *((_CSet *)&other);
return *this;
}
//! Returns if element "t" exists in this set
bool operator [](const T & t) const {return _CSet::contains(t);}
bool operator[](const T & t) const { return _CSet::contains(t); }
//! Returns if element "t" exists in this set
PISet<T> & remove(const T & t) {_CSet::remove(t); return *this;}
PISet<T> & remove(const T & t) {
_CSet::remove(t);
return *this;
}
//! Unite set with "v"
PISet<T> & unite(const PISet<T> & v) {
@@ -107,48 +131,76 @@ public:
}
//! Unite set with "v"
PISet<T> & operator +=(const PISet<T> & v) {return unite(v);}
PISet<T> & operator+=(const PISet<T> & v) { return unite(v); }
//! Unite set with "v"
PISet<T> & operator |=(const PISet<T> & v) {return unite(v);}
PISet<T> & operator|=(const PISet<T> & v) { return unite(v); }
//! Subtract set with "v"
PISet<T> & operator -=(const PISet<T> & v) {return subtract(v);}
PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); }
//! Intersect set with "v"
PISet<T> & operator &=(const PISet<T> & v) {return intersect(v);}
PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); }
//! Returns content of set as PIVector
PIVector<T> toVector() const {PIVector<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << i.key(); return ret;}
PIVector<T> toVector() const {
PIVector<T> ret;
for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i)
ret << i.key();
return ret;
}
//! Returns content of set as PIDeque
PIDeque<T> toDeque() const {PIDeque<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << i.key(); return ret;}
PIDeque<T> toDeque() const {
PIDeque<T> ret;
for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i)
ret << i.key();
return ret;
}
};
//! \relatesalso PISet \brief Returns unite of two sets
template <typename T> PISet<T> operator +(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.unite(v1); return ret;}
template<typename T>
PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0);
ret.unite(v1);
return ret;
}
//! \relatesalso PISet \brief Returns subtraction of two sets
template <typename T> PISet<T> operator -(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.subtract(v1); return ret;}
template<typename T>
PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0);
ret.subtract(v1);
return ret;
}
//! \relatesalso PISet \brief Returns unite of two sets
template <typename T> PISet<T> operator |(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.unite(v1); return ret;}
template<typename T>
PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0);
ret.unite(v1);
return ret;
}
//! \relatesalso PISet \brief Returns intersetion of two sets
template <typename T> PISet<T> operator &(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.intersect(v1); return ret;}
template<typename T>
PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0);
ret.intersect(v1);
return ret;
}
template<typename Type>
inline PICout operator <<(PICout s, const PISet<Type> & v) {
inline PICout operator<<(PICout s, const PISet<Type> & v) {
s.space();
s.saveAndSetControls(0);
s << "{";
bool first = true;
for (typename PIMap<Type, uchar>::const_iterator i = v.begin(); i != v.end(); ++i) {
if (!first)
s << ", ";
if (!first) s << ", ";
first = false;
s << i.key();
}
+27 -22
View File
@@ -13,29 +13,29 @@
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/*
PIP - Platform Independent Primitives
Stack container
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Stack container
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISTACK_H
#define PISTACK_H
#include "pivector.h"
#include "pideque.h"
#include "pivector.h"
//! \addtogroup Containers
//! \{
@@ -53,18 +53,23 @@
template<typename T>
class PIStack: public PIVector<T> {
public:
//! \~english Constructs an empty array.
//! \~russian Создает пустой массив.
PIStack() {}
//! \~english Puts an element on the stack.
//! \~russian Кладёт элемент в стек.
PIVector<T> & push(const T & v) {PIVector<T>::push_back(v); return *this;}
PIVector<T> & push(const T & v) {
PIVector<T>::push_back(v);
return *this;
}
//! \~english Move an element on the stack.
//! \~russian Перемещает элемент в стек.
PIVector<T> & push(T && v) {PIVector<T>::push_back(std::move(v)); return *this;}
PIVector<T> & push(T && v) {
PIVector<T>::push_back(std::move(v));
return *this;
}
//! \~english Retrieves and returns an element from the stack.
//! \~russian Забирает и возвращает элемент из стека.
@@ -74,7 +79,7 @@ public:
//! Otherwise will be undefined behavior.
//! \~russian Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T pop() {return PIVector<T>::take_back();}
T pop() { return PIVector<T>::take_back(); }
//! \~english Top element of the stack
//! \~russian Верхний элемент стека.
@@ -86,16 +91,16 @@ public:
//! \~russian Возвращает ссылку на верхний элемент стека.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T & top() {return PIVector<T>::back();}
const T & top() const {return PIVector<T>::back();}
T & top() { return PIVector<T>::back(); }
const T & top() const { return PIVector<T>::back(); }
//! \~english Converts \a PIStack to \a PIVector.
//! \~russian Преобразует \a PIStack в \a PIVector.
PIVector<T> toVector() const {return PIVector<T>(*this);}
PIVector<T> toVector() const { return PIVector<T>(*this); }
//! \~english Converts \a PIStack to \a PIDeque.
//! \~russian Преобразует \a PIStack в \a PIDeque.
PIDeque<T> toDeque() const {return PIDeque<T>(PIVector<T>::data(), PIVector<T>::size());}
PIDeque<T> toDeque() const { return PIDeque<T>(PIVector<T>::data(), PIVector<T>::size()); }
};
#endif // PISTACK_H
+265 -333
View File
@@ -13,22 +13,22 @@
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/*
PIP - Platform Independent Primitives
Sequence linear container aka dynamic size array of any type
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Sequence linear container aka dynamic size array of any type
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIVECTOR_H
@@ -114,22 +114,20 @@
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива 𝓞(n)
//!
//! \~\sa \a PIDeque, \a PIMap
template <typename T>
template<typename T>
class PIVector {
public:
typedef bool (*CompareFunc)(const T & , const T & );
typedef bool (*CompareFunc)(const T &, const T &);
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T * pointer;
typedef const T * const_pointer;
typedef T & reference;
typedef const T & const_reference;
typedef size_t size_type;
//! \~english Constructs an empty array.
//! \~russian Создает пустой массив.
inline PIVector() {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
}
inline PIVector() { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) }
//! \~english Contructs array from raw `data`.
//! This constructor reserve `size` and copy from `data` pointer.
@@ -193,8 +191,8 @@ public:
//! \~russian Перемещающий конструктор.
inline PIVector(PIVector<T> && v) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
piv_data = v.piv_data;
piv_size = v.piv_size;
piv_data = v.piv_data;
piv_size = v.piv_size;
piv_rsize = v.piv_rsize;
v._reset();
}
@@ -208,7 +206,7 @@ public:
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIVector<T> & operator =(const PIVector<T> & v) {
inline PIVector<T> & operator=(const PIVector<T> & v) {
if (this == &v) return *this;
clear();
alloc(v.piv_size);
@@ -218,360 +216,330 @@ public:
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIVector<T> & operator =(PIVector<T> && v) {
inline PIVector<T> & operator=(PIVector<T> && v) {
swap(v);
return *this;
}
class iterator {
friend class PIVector<T>;
private:
inline iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
PIVector<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline iterator(): parent(0), pos(0) {}
inline T & operator *() {return (*parent)[pos];}
inline const T & operator *() const {return (*parent)[pos];}
inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline T & operator*() { return (*parent)[pos]; }
inline const T & operator*() const { return (*parent)[pos]; }
inline T & operator->() { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline iterator & operator ++() {
inline iterator & operator++() {
++pos;
return *this;
}
inline iterator operator ++(int) {
inline iterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline iterator & operator --() {
inline iterator & operator--() {
--pos;
return *this;
}
inline iterator operator --(int) {
inline iterator operator--(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline iterator & operator +=(const iterator & it) {
inline iterator & operator+=(const iterator & it) {
pos += it.pos;
return *this;
}
inline iterator & operator +=(size_t p) {
inline iterator & operator+=(size_t p) {
pos += p;
return *this;
}
inline iterator & operator -=(const iterator & it) {
inline iterator & operator-=(const iterator & it) {
pos -= it.pos;
return *this;
}
inline iterator & operator -=(size_t p) {
inline iterator & operator-=(size_t p) {
pos -= p;
return *this;
}
friend inline iterator operator -(size_t p, const iterator & it) {return it - p;}
friend inline iterator operator -(const iterator & it, size_t p) {
friend inline iterator operator-(size_t p, const iterator & it) { return it - p; }
friend inline iterator operator-(const iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
return it1.pos - it2.pos;
}
friend inline std::ptrdiff_t operator-(const iterator & it1, const iterator & it2) { return it1.pos - it2.pos; }
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
friend inline iterator operator +(const iterator & it, size_t p) {
friend inline iterator operator+(size_t p, const iterator & it) { return it + p; }
friend inline iterator operator+(const iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const iterator & it1, const iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const iterator & it1, const iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const iterator & it1, const iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const iterator & it1, const iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const iterator & it1, const iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const iterator & it1, const iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const iterator & it1, const iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const iterator & it1, const iterator & it2) { return it1.pos >= it2.pos; }
};
class const_iterator {
friend class PIVector<T>;
private:
inline const_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
const PIVector<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_iterator(): parent(0), pos(0) {}
inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline const T & operator*() const { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline const_iterator & operator ++() {
inline const_iterator & operator++() {
++pos;
return *this;
}
inline const_iterator operator ++(int) {
inline const_iterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_iterator & operator --() {
inline const_iterator & operator--() {
--pos;
return *this;
}
inline const_iterator operator --(int) {
inline const_iterator operator--(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_iterator & operator +=(const const_iterator & it) {
inline const_iterator & operator+=(const const_iterator & it) {
pos += it.pos;
return *this;
}
inline const_iterator & operator +=(size_t p) {
inline const_iterator & operator+=(size_t p) {
pos += p;
return *this;
}
inline const_iterator & operator -=(const const_iterator & it) {
inline const_iterator & operator-=(const const_iterator & it) {
pos -= it.pos;
return *this;
}
inline const_iterator & operator -=(size_t p) {
inline const_iterator & operator-=(size_t p) {
pos -= p;
return *this;
}
friend inline const_iterator operator -(size_t p, const const_iterator & it) {return it - p;}
friend inline const_iterator operator -(const const_iterator & it, size_t p) {
friend inline const_iterator operator-(size_t p, const const_iterator & it) { return it - p; }
friend inline const_iterator operator-(const const_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
return it1.pos - it2.pos;
}
friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; }
friend inline const_iterator operator +(size_t p, const const_iterator & it) {return it + p;}
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
friend inline const_iterator operator+(size_t p, const const_iterator & it) { return it + p; }
friend inline const_iterator operator+(const const_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const const_iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const const_iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; }
};
class reverse_iterator {
friend class PIVector<T>;
private:
inline reverse_iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
PIVector<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline reverse_iterator(): parent(0), pos(0) {}
inline T & operator *() {return (*parent)[pos];}
inline const T & operator *() const {return (*parent)[pos];}
inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline T & operator*() { return (*parent)[pos]; }
inline const T & operator*() const { return (*parent)[pos]; }
inline T & operator->() { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline reverse_iterator & operator ++() {
inline reverse_iterator & operator++() {
--pos;
return *this;
}
inline reverse_iterator operator ++(int) {
inline reverse_iterator operator++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline reverse_iterator & operator --() {
inline reverse_iterator & operator--() {
++pos;
return *this;
}
inline reverse_iterator operator --(int) {
inline reverse_iterator operator--(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline reverse_iterator & operator +=(const reverse_iterator & it) {
inline reverse_iterator & operator+=(const reverse_iterator & it) {
pos -= it.pos;
return *this;
}
inline reverse_iterator & operator +=(size_t p) {
inline reverse_iterator & operator+=(size_t p) {
pos -= p;
return *this;
}
inline reverse_iterator & operator -=(const reverse_iterator & it) {
inline reverse_iterator & operator-=(const reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline reverse_iterator & operator -=(size_t p) {
inline reverse_iterator & operator-=(size_t p) {
pos += p;
return *this;
}
friend inline reverse_iterator operator -(size_t p, const reverse_iterator & it) {return it - p;}
friend inline reverse_iterator operator -(const reverse_iterator & it, size_t p) {
friend inline reverse_iterator operator-(size_t p, const reverse_iterator & it) { return it - p; }
friend inline reverse_iterator operator-(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline std::ptrdiff_t operator-(const reverse_iterator & it1, const reverse_iterator & it2) { return it2.pos - it1.pos; }
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
friend inline reverse_iterator operator+(size_t p, const reverse_iterator & it) { return it + p; }
friend inline reverse_iterator operator+(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const reverse_iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const reverse_iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos >= it2.pos; }
};
class const_reverse_iterator {
friend class PIVector<T>;
private:
inline const_reverse_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
const PIVector<T> * parent;
ssize_t pos;
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef T * pointer;
typedef T & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_reverse_iterator(): parent(0), pos(0) {}
inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];}
inline const T & operator*() const { return (*parent)[pos]; }
inline const T & operator->() const { return (*parent)[pos]; }
inline const_reverse_iterator & operator ++() {
inline const_reverse_iterator & operator++() {
--pos;
return *this;
}
inline const_reverse_iterator operator ++(int) {
inline const_reverse_iterator operator++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_reverse_iterator & operator --() {
inline const_reverse_iterator & operator--() {
++pos;
return *this;
}
inline const_reverse_iterator operator --(int) {
inline const_reverse_iterator operator--(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_reverse_iterator & operator +=(const const_reverse_iterator & it) {
inline const_reverse_iterator & operator+=(const const_reverse_iterator & it) {
pos -= it.pos;
return *this;
}
inline const_reverse_iterator & operator +=(size_t p) {
inline const_reverse_iterator & operator+=(size_t p) {
pos -= p;
return *this;
}
inline const_reverse_iterator & operator -=(const const_reverse_iterator & it) {
inline const_reverse_iterator & operator-=(const const_reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline const_reverse_iterator & operator -=(size_t p) {
inline const_reverse_iterator & operator-=(size_t p) {
pos += p;
return *this;
}
friend inline const_reverse_iterator operator -(size_t p, const const_reverse_iterator & it) {return it - p;}
friend inline const_reverse_iterator operator -(const const_reverse_iterator & it, size_t p) {
friend inline const_reverse_iterator operator-(size_t p, const const_reverse_iterator & it) { return it - p; }
friend inline const_reverse_iterator operator-(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
friend inline std::ptrdiff_t operator-(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline const_reverse_iterator operator +(size_t p, const const_reverse_iterator & it) {return it + p;}
friend inline const_reverse_iterator operator +(const const_reverse_iterator & it, size_t p) {
friend inline const_reverse_iterator operator+(size_t p, const const_reverse_iterator & it) { return it + p; }
friend inline const_reverse_iterator operator+(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos < it2.pos;
}
friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
inline bool operator==(const const_reverse_iterator & it) const { return (pos == it.pos); }
inline bool operator!=(const const_reverse_iterator & it) const { return (pos != it.pos); }
friend inline bool operator<(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos < it2.pos; }
friend inline bool operator<=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos <= it2.pos; }
friend inline bool operator>(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos > it2.pos; }
friend inline bool operator>=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos >= it2.pos; }
};
//! \~english Iterator to the first element.
@@ -582,7 +550,7 @@ public:
//! \~russian Если массив пустой, возвращаемый итератор будет равен \a end().
//! \~\return \ref stl_iterators
//! \~\sa \a end(), \a rbegin(), \a rend()
inline iterator begin() {return iterator(this, 0);}
inline iterator begin() { return iterator(this, 0); }
//! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
@@ -594,10 +562,10 @@ public:
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a begin(), \a rbegin(), \a rend()
inline iterator end() {return iterator(this, piv_size);}
inline iterator end() { return iterator(this, piv_size); }
inline const_iterator begin() const {return const_iterator(this, 0);}
inline const_iterator end() const {return const_iterator(this, piv_size);}
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator end() const { return const_iterator(this, piv_size); }
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
@@ -610,7 +578,7 @@ public:
//! Если массив пустой, то совпадает с итератором \a rend().
//! \~\return \ref stl_iterators
//! \~\sa \a rend(), \a begin(), \a end()
inline reverse_iterator rbegin() {return reverse_iterator(this, piv_size - 1);}
inline reverse_iterator rbegin() { return reverse_iterator(this, piv_size - 1); }
//! \~english Returns a reverse iterator to the element
//! following the last element of the reversed array.
@@ -625,25 +593,25 @@ public:
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a rbegin(), \a begin(), \a end()
inline reverse_iterator rend() {return reverse_iterator(this, -1);}
inline reverse_iterator rend() { return reverse_iterator(this, -1); }
inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, piv_size - 1);}
inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(this, piv_size - 1); }
inline const_reverse_iterator rend() const { return const_reverse_iterator(this, -1); }
//! \~english Number of elements in the container.
//! \~russian Количество элементов массива.
//! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t size() const {return piv_size;}
inline size_t size() const { return piv_size; }
//! \~english Number of elements in the container as signed value.
//! \~russian Количество элементов массива в виде знакового числа.
//! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline ssize_t size_s() const {return piv_size;}
inline ssize_t size_s() const { return piv_size; }
//! \~english Same as \a size().
//! \~russian Синоним \a size().
//! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t length() const {return piv_size;}
inline size_t length() const { return piv_size; }
//! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
@@ -651,7 +619,7 @@ public:
//! \~english To find out the actual number of items, use the function \a size().
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
//! \~\sa \a reserve(), \a size(), \a size_s()
inline size_t capacity() const {return piv_rsize;}
inline size_t capacity() const { return piv_rsize; }
//! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли массив.
@@ -659,7 +627,7 @@ public:
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если массив пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isEmpty() const {return (piv_size == 0);}
inline bool isEmpty() const { return (piv_size == 0); }
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли массив.
@@ -667,7 +635,7 @@ public:
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если массив не пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isNotEmpty() const {return (piv_size > 0);}
inline bool isNotEmpty() const { return (piv_size > 0); }
//! \~english Tests whether at least one element in the array
//! passes the test implemented by the provided function `test`.
@@ -735,8 +703,8 @@ public:
//! piCout << v; // {1, 2, 5, 9}
//! \endcode
//! \~\sa \a at()
inline T & operator [](size_t index) {return piv_data[index];}
inline const T & operator [](size_t index) const {return piv_data[index];}
inline T & operator[](size_t index) { return piv_data[index]; }
inline const T & operator[](size_t index) const { return piv_data[index]; }
//! \~english Read only access to element by `index`.
//! \~russian Доступ исключительно на чтение к элементу по индексу `index`.
@@ -747,7 +715,7 @@ public:
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const T & at(size_t index) const {return piv_data[index];}
inline const T & at(size_t index) const { return piv_data[index]; }
//! \~english Returns the first element of the array that
@@ -758,8 +726,10 @@ public:
//! \~\sa \a indexWhere()
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
ssize_t i = indexWhere(test, start);
if (i < 0) return def;
else return at(i);
if (i < 0)
return def;
else
return at(i);
}
//! \~english Returns the last element of the array that
@@ -770,8 +740,10 @@ public:
//! \~\sa \a lastIndexWhere()
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
ssize_t i = lastIndexWhere(test, start);
if (i < 0) return def;
else return at(i);
if (i < 0)
return def;
else
return at(i);
}
//! \~english Last element.
@@ -783,8 +755,8 @@ public:
//! \~russian Возвращает ссылку на последний элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline T & back() {return piv_data[piv_size - 1];}
inline const T & back() const {return piv_data[piv_size - 1];}
inline T & back() { return piv_data[piv_size - 1]; }
inline const T & back() const { return piv_data[piv_size - 1]; }
//! \~english Last element.
//! \~russian Первый элемент массива.
@@ -795,12 +767,12 @@ public:
//! \~russian Возвращает ссылку на пенрвый элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline T & front() {return piv_data[0];}
inline const T & front() const {return piv_data[0];}
inline T & front() { return piv_data[0]; }
inline const T & front() const { return piv_data[0]; }
//! \~english Compare operator with array `v`.
//! \~russian Оператор сравнения с массивом `v`.
inline bool operator ==(const PIVector<T> & v) const {
inline bool operator==(const PIVector<T> & v) const {
if (piv_size != v.piv_size) return false;
for (size_t i = 0; i < piv_size; ++i) {
if (v[i] != piv_data[i]) return false;
@@ -810,7 +782,7 @@ public:
//! \~english Compare operator with array `v`.
//! \~russian Оператор сравнения с массивом `v`.
inline bool operator !=(const PIVector<T> & v) const {return !(*this == v);}
inline bool operator!=(const PIVector<T> & v) const { return !(*this == v); }
//! \~english Tests if element `e` exists in the array.
//! \~russian Проверяет наличие элемента `e` в массиве.
@@ -869,7 +841,7 @@ public:
start = piv_size + start;
if (start < 0) start = 0;
}
for (const T & e : v) {
for (const T & e: v) {
bool c = false;
for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) {
@@ -1122,7 +1094,7 @@ public:
//! memcpy(vec.data(1), a, 2 * sizeof(int));
//! piCout << v; // {2, 12, 13, 2}
//! \endcode
inline T * data(size_t index = 0) {return &(piv_data[index]);}
inline T * data(size_t index = 0) { return &(piv_data[index]); }
//! \~english Read only pointer to array
//! \~russian Указатель на память массива только для чтения.
@@ -1141,7 +1113,7 @@ public:
//! memcpy(a, v.data(), a.size() * sizeof(int));
//! piCout << a[0] << a[1] << a[2]; // 1 3 5
//! \endcode
inline const T * data(size_t index = 0) const {return &(piv_data[index]);}
inline const T * data(size_t index = 0) const { return &(piv_data[index]); }
//! \~english Creates sub-array of this array.
//! \~russian Создает подмассив, то есть кусок из текущего массива.
@@ -1172,17 +1144,13 @@ public:
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector<T> & clear() {
deleteT(piv_data, piv_size);
piv_size = 0;
return *this;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector<T> & clear() {
PIINTROSPECTION_CONTAINER_UNUSED(T, piv_size)
piv_size = 0;
@@ -1228,21 +1196,17 @@ public:
//! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize()
inline PIVector<T> & assign(const T & e = T()) {return fill(e);}
inline PIVector<T> & assign(const T & e = T()) { return fill(e); }
//! \~english First does `resize(new_size)` then `fill(e)`.
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
//! \~\sa \a fill(), \a resize()
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector<T> & assign(size_t new_size, const T & f) {
resize(new_size);
return fill(f);
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector<T> & assign(size_t new_size, const T & f) {
_resizeRaw(new_size);
return fill(f);
@@ -1290,25 +1254,21 @@ public:
return *this;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector<T> & _resizeRaw(size_t new_size) {
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
if (new_size > piv_size) {
PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size));
PIINTROSPECTION_CONTAINER_USED(T, (new_size - piv_size));
}
if (new_size < piv_size) {
PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size));
PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size - new_size));
}
#endif
alloc(new_size);
return *this;
}
inline void _copyRaw(T * dst, const T * src, size_t size) {
newT(dst, src, size);
}
inline void _copyRaw(T * dst, const T * src, size_t size) { newT(dst, src, size); }
//! \~english Attempts to allocate memory for at least `new_size` elements.
//! \~russian Резервируется память под как минимум `new_size` элементов.
@@ -1347,7 +1307,7 @@ public:
alloc(piv_size + 1);
if (index < piv_size - 1) {
size_t os = piv_size - index - 1;
memmove((void*)(piv_data + index + 1), (const void*)(piv_data + index), os * sizeof(T));
memmove((void *)(piv_data + index + 1), (const void *)(piv_data + index), os * sizeof(T));
}
PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(piv_data + index, e);
@@ -1364,7 +1324,7 @@ public:
alloc(piv_size + 1);
if (index < piv_size - 1) {
size_t os = piv_size - index - 1;
memmove((void*)(piv_data + index + 1), (const void*)(piv_data + index), os * sizeof(T));
memmove((void *)(piv_data + index + 1), (const void *)(piv_data + index), os * sizeof(T));
}
PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(piv_data + index, std::move(e));
@@ -1388,7 +1348,7 @@ public:
ssize_t os = piv_size - index;
alloc(piv_size + v.piv_size);
if (os > 0) {
memmove((void*)(piv_data + index + v.piv_size), (const void*)(piv_data + index), os * sizeof(T));
memmove((void *)(piv_data + index + v.piv_size), (const void *)(piv_data + index), os * sizeof(T));
}
newT(piv_data + index, v.piv_data, v.piv_size);
return *this;
@@ -1409,7 +1369,7 @@ public:
ssize_t os = piv_size - index;
alloc(piv_size + init_list.size());
if (os > 0) {
memmove((void*)(piv_data + index + init_list.size()), (const void*)(piv_data + index), os * sizeof(T));
memmove((void *)(piv_data + index + init_list.size()), (const void *)(piv_data + index), os * sizeof(T));
}
newT(piv_data + index, init_list.begin(), init_list.size());
return *this;
@@ -1434,7 +1394,7 @@ public:
} else {
size_t os = piv_size - index - count;
deleteT(piv_data + index, count);
memmove((void*)(piv_data + index), (const void*)(piv_data + index + count), os * sizeof(T));
memmove((void *)(piv_data + index), (const void *)(piv_data + index + count), os * sizeof(T));
piv_size -= count;
}
return *this;
@@ -1446,7 +1406,7 @@ public:
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
inline void swap(PIVector<T> & v) {
piSwap<T*>(piv_data, v.piv_data);
piSwap<T *>(piv_data, v.piv_data);
piSwap<size_t>(piv_size, v.piv_size);
piSwap<size_t>(piv_rsize, v.piv_rsize);
}
@@ -1490,23 +1450,18 @@ public:
//! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
//! Для сравнения элементов используется функция сравнения `comp`.
//! Функция сравнения, возвращает ​`true` если первый аргумент меньше второго.
//! Сигнатура функции сравнения должна быть эквивалентна следующей:
//! \code
//! bool comp(const T &a, const T &b);
//! \endcode
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
//! Функция обязана возвращать `false` для одинаковых элементов,
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`.
//! Функция сравнения, возвращает ​`true` если первый аргумент меньше
//! второго. Сигнатура функции сравнения должна быть эквивалентна следующей: \code bool comp(const T &a, const T &b); \endcode Сигнатура
//! не обязана содержать const &, однако, функция не может изменять переданные объекты. Функция обязана возвращать `false` для
//! одинаковых элементов, иначе это приведёт к неопределённому поведению программы и ошибкам памяти. Для сортировки используется функция
//! [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). Сложность сортировки `O(N·log(N))`.
//! \~\code
//! PIVector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
//! v.sort([](const int & a, const int & b){return a > b;});
//! piCout << v; // {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
//! \endcode
//! \~\sa \a sort()
inline PIVector<T> & sort(std::function<bool(const T &a, const T &b)> comp) {
inline PIVector<T> & sort(std::function<bool(const T & a, const T & b)> comp) {
std::sort(begin(), end(), comp);
return *this;
}
@@ -1528,9 +1483,9 @@ public:
//! \endcode
//! \~\sa \a reversed()
inline PIVector<T> & reverse() {
size_t s2 = piv_size/2;
size_t s2 = piv_size / 2;
for (size_t i = 0; i < s2; ++i) {
piSwap<T>(piv_data[i], piv_data[piv_size-i-1]);
piSwap<T>(piv_data[i], piv_data[piv_size - i - 1]);
}
return *this;
}
@@ -1560,8 +1515,10 @@ public:
//! \~\sa \a resize()
inline PIVector<T> & enlarge(ssize_t add_size, const T & e = T()) {
ssize_t ns = size_s() + add_size;
if (ns <= 0) clear();
else resize(size_t(ns), e);
if (ns <= 0)
clear();
else
resize(size_t(ns), e);
return *this;
}
@@ -1731,7 +1688,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a prepend(), \a push_front(), \a push_back(), \a insert()
inline PIVector<T> & append(const T & e) {return push_back(e);}
inline PIVector<T> & append(const T & e) { return push_back(e); }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
@@ -1739,7 +1696,7 @@ public:
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a append()
inline PIVector<T> & append(T && e) {return push_back(std::move(e));}
inline PIVector<T> & append(T && e) { return push_back(std::move(e)); }
//! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива.
@@ -1751,7 +1708,7 @@ public:
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIVector<T> & append(std::initializer_list<T> init_list) {return push_back(init_list);}
inline PIVector<T> & append(std::initializer_list<T> init_list) { return push_back(init_list); }
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
@@ -1764,7 +1721,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIVector<T> & append(const PIVector<T> & v) {return push_back(v);}
inline PIVector<T> & append(const PIVector<T> & v) { return push_back(v); }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
@@ -1775,7 +1732,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIVector<T> & operator <<(const T & e) {return push_back(e);}
inline PIVector<T> & operator<<(const T & e) { return push_back(e); }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
@@ -1786,7 +1743,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIVector<T> & operator <<(T && e) {return push_back(std::move(e));}
inline PIVector<T> & operator<<(T && e) { return push_back(std::move(e)); }
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
@@ -1797,7 +1754,7 @@ public:
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIVector<T> & operator <<(const PIVector<T> & v) {return push_back(v);}
inline PIVector<T> & operator<<(const PIVector<T> & v) { return push_back(v); }
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
@@ -1815,9 +1772,7 @@ public:
//! piCout << v; // {5, 4, 1, 2, 3}
//! \endcode
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIVector<T> & push_front(const T & e) {
return insert(0, e);
}
inline PIVector<T> & push_front(const T & e) { return insert(0, e); }
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
@@ -1825,9 +1780,7 @@ public:
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_front()
inline PIVector<T> & push_front(T && e) {
return insert(0, std::move(e));
}
inline PIVector<T> & push_front(T && e) { return insert(0, std::move(e)); }
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
@@ -1840,9 +1793,7 @@ public:
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a push_front()
inline PIVector<T> & push_front(const PIVector<T> & v) {
return insert(0, v);
}
inline PIVector<T> & push_front(const PIVector<T> & v) { return insert(0, v); }
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
@@ -1854,9 +1805,7 @@ public:
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIVector<T> & push_front(std::initializer_list<T> init_list) {
return insert(0, init_list);
}
inline PIVector<T> & push_front(std::initializer_list<T> init_list) { return insert(0, init_list); }
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
@@ -1874,7 +1823,7 @@ public:
//! piCout << v; // {5, 4, 1, 2, 3}
//! \endcode
//! \~\sa \a append(), \a push_back(), \a push_front(), \a insert()
inline PIVector<T> & prepend(const T & e) {return push_front(e);}
inline PIVector<T> & prepend(const T & e) { return push_front(e); }
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
@@ -1882,7 +1831,7 @@ public:
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a prepend()
inline PIVector<T> & prepend(T && e) {return push_front(std::move(e));}
inline PIVector<T> & prepend(T && e) { return push_front(std::move(e)); }
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
@@ -1895,7 +1844,7 @@ public:
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a prepend()
inline PIVector<T> & prepend(const PIVector<T> & v) {return push_front(v);}
inline PIVector<T> & prepend(const PIVector<T> & v) { return push_front(v); }
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
@@ -1907,7 +1856,7 @@ public:
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIVector<T> & prepend(std::initializer_list<T> init_list) {return prepend(init_list);}
inline PIVector<T> & prepend(std::initializer_list<T> init_list) { return prepend(init_list); }
//! \~english Remove one element from the end of the array.
//! \~russian Удаляет один элемент с конца массива.
@@ -1989,7 +1938,7 @@ public:
//! piCout << v2; // {1, 2, 3}
//! \endcode
//! \~\sa \a map()
template <typename ST>
template<typename ST>
inline PIVector<ST> toType() const {
PIVector<ST> ret;
ret.reserve(piv_size);
@@ -2104,7 +2053,7 @@ public:
//! \~russian Аналогично \a forEachIndexed(), но позволяет изменять элементы массива.
//! \~\sa \a forEach(), \a forEachIndexed()
inline PIVector<T> & forEachIndexed(std::function<void(size_t index, T & e)> f) {
for (size_t i = 0; i < piv_size; ++i) {
for (size_t i = 0; i < piv_size; ++i) {
f(i, piv_data[i]);
}
return *this;
@@ -2165,9 +2114,10 @@ public:
//! piCout << sl; // {"1", "2", "3"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST>
template<typename ST>
inline PIVector<ST> map(std::function<ST(const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size);
PIVector<ST> ret;
ret.reserve(piv_size);
for (size_t i = 0; i < piv_size; ++i) {
ret << f(piv_data[i]);
}
@@ -2182,9 +2132,10 @@ public:
//! piCout << sl; // {"0", "1", "2"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
template<typename ST>
inline PIVector<ST> mapIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size);
PIVector<ST> ret;
ret.reserve(piv_size);
for (size_t i = 0; i < piv_size; ++i) {
ret << f(i, piv_data[i]);
}
@@ -2199,9 +2150,10 @@ public:
//! piCout << sl; // {"3", "2", "1"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
template<typename ST>
inline PIVector<ST> mapReverse(std::function<ST(const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size);
PIVector<ST> ret;
ret.reserve(piv_size);
for (ssize_t i = piv_size; i >= 0; --i) {
ret << f(piv_data[i]);
}
@@ -2216,9 +2168,10 @@ public:
//! piCout << sl; // {"2", "1", "0"}
//! \endcode
//! \~\sa \a mapReverse()
template <typename ST>
template<typename ST>
inline PIVector<ST> mapReverseIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size);
PIVector<ST> ret;
ret.reserve(piv_size);
for (ssize_t i = piv_size; i >= 0; --i) {
ret << f(i, piv_data[i]);
}
@@ -2266,7 +2219,7 @@ public:
//! piCout << s; // 15
//! \endcode
//! \~\sa \a forEach(), \a map()
template <typename ST>
template<typename ST>
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = 0; i < piv_size; ++i) {
@@ -2278,7 +2231,7 @@ public:
//! \~english Same as \a reduce() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduce()
template <typename ST>
template<typename ST>
inline ST reduceIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = 0; i < piv_size; ++i) {
@@ -2290,7 +2243,7 @@ public:
//! \~english Same as \a reduce() but from end to begin (from right to left).
//! \~russian Аналогично \a reduce() но от конца до начала (справа на лево).
//! \~\sa \a reduce()
template <typename ST>
template<typename ST>
inline ST reduceReverse(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = piv_size; i >= 0; --i) {
@@ -2302,7 +2255,7 @@ public:
//! \~english Same as \a reduceReverse() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduceReverse()
template <typename ST>
template<typename ST>
inline ST reduceReverseIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = piv_size; i >= 0; --i) {
@@ -2332,24 +2285,24 @@ public:
//! \~\sa \a map(), \a reduce(), \a flatten()
inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
#ifndef NDEBUG
if (rows*cols != piv_size) {
if (rows * cols != piv_size) {
printf("error with PIVector<%s>::reshape\n", __PIP_TYPENAME__(T));
}
#endif
assert(rows*cols == piv_size);
assert(rows * cols == piv_size);
PIVector<PIVector<T>> ret;
if (isEmpty()) return ret;
ret.expand(rows);
if (order == ReshapeByRow) {
for (size_t r = 0; r < rows; r++) {
ret[r] = PIVector<T>(&(piv_data[r*cols]), cols);
ret[r] = PIVector<T>(&(piv_data[r * cols]), cols);
}
}
if (order == ReshapeByColumn) {
for (size_t r = 0; r < rows; r++) {
ret[r].resize(cols);
for (size_t c = 0; c < cols; c++) {
ret[r][c] = piv_data[c*rows + r];
ret[r][c] = piv_data[c * rows + r];
}
}
}
@@ -2370,9 +2323,7 @@ public:
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if<
std::is_same<T, PIVector<C>>::value
, int>::type = 0>
template<typename C, typename std::enable_if<std::is_same<T, PIVector<C>>::value, int>::type = 0>
inline PIVector<C> flatten(ReshapeOrder order = ReshapeByRow) const {
PIVector<C> ret;
if (isEmpty()) return ret;
@@ -2413,9 +2364,7 @@ public:
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if<
std::is_same<T, PIVector<C>>::value
, int>::type = 0>
template<typename C, typename std::enable_if<std::is_same<T, PIVector<C>>::value, int>::type = 0>
inline PIVector<PIVector<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
PIVector<C> fl = flatten<C>();
return fl.reshape(rows, cols, order);
@@ -2432,11 +2381,11 @@ public:
PIVector<PIVector<T>> ret;
if (isEmpty()) return ret;
size_t start = 0;
ssize_t ci = indexOf(separator, start);
ssize_t ci = indexOf(separator, start);
while (ci >= 0) {
ret << PIVector<T>(piv_data + start, ci - start);
start = ci + 1;
ci = indexOf(separator, start);
ci = indexOf(separator, start);
}
if (start < piv_size) {
ret << PIVector<T>(piv_data + start, piv_size - start);
@@ -2452,9 +2401,9 @@ public:
if (isEmpty() || sz == 0) return ret;
size_t ch = piv_size / sz;
for (size_t i = 0; i < ch; ++i) {
ret << PIVector<T>(piv_data + sz*i, sz);
ret << PIVector<T>(piv_data + sz * i, sz);
}
size_t t = ch*sz;
size_t t = ch * sz;
if (t < piv_size) {
ret << PIVector<T>(piv_data + t, piv_size - t);
}
@@ -2482,10 +2431,10 @@ public:
if (index >= piv_size || count == 0) return ret;
if (index + count > piv_size) count = piv_size - index;
ret.alloc(count);
memcpy((void*)ret.piv_data, (const void*)(piv_data + index), count * sizeof(T));
memcpy((void *)ret.piv_data, (const void *)(piv_data + index), count * sizeof(T));
size_t os = piv_size - index - count;
if (os > 0) {
memmove((void*)(piv_data + index), (const void*)(piv_data + index + count), os * sizeof(T));
memmove((void *)(piv_data + index), (const void *)(piv_data + index + count), os * sizeof(T));
piv_size -= count;
} else {
piv_size = index;
@@ -2495,9 +2444,9 @@ public:
private:
inline void _reset() {
piv_size = 0;
piv_size = 0;
piv_rsize = 0;
piv_data = nullptr;
piv_data = nullptr;
}
inline size_t asize(size_t s) {
@@ -2506,13 +2455,12 @@ private:
return piv_rsize * 2;
}
ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
while (s_ >> t) ++t;
while (s_ >> t)
++t;
return (1 << t);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void newT(T * dst, const T * src, size_t s) {
PIINTROSPECTION_CONTAINER_USED(T, s)
for (size_t i = 0; i < s; ++i) {
@@ -2520,17 +2468,13 @@ private:
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void newT(T * dst, const T * src, size_t s) {
PIINTROSPECTION_CONTAINER_USED(T, s)
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
memcpy((void *)(dst), (const void *)(src), s * sizeof(T));
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
if (d != nullptr) {
@@ -2540,56 +2484,42 @@ private:
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T * to, const T & from) {
new(to)T(from);
new (to) T(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T * to, T && from) {
new(to)T(std::move(from));
new (to) T(std::move(from));
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T1 * to, const T & from) {
(*to) = from;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementNew(T * to, T && from) {
(*to) = std::move(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementDelete(T & from) {
from.~T();
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline void elementDelete(T & from) {}
inline void dealloc() {
if (piv_data != nullptr) {
free((void*)piv_data);
free((void *)piv_data);
piv_data = nullptr;
}
}
@@ -2597,7 +2527,7 @@ private:
inline void expand(size_t new_size, const T & e = T()) {
size_t os = piv_size;
alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, e);
}
@@ -2606,7 +2536,7 @@ private:
inline void expand(size_t new_size, std::function<T(size_t i)> f) {
size_t os = piv_size;
alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, f(i));
}
@@ -2617,23 +2547,23 @@ private:
piv_size = new_size;
return;
}
piv_size = new_size;
piv_size = new_size;
size_t as = asize(new_size);
if (as == piv_rsize) return;
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-piv_rsize))
T * p_d = (T*)(realloc((void*)(piv_data), as*sizeof(T)));
PIINTROSPECTION_CONTAINER_ALLOC(T, (as - piv_rsize))
T * p_d = (T *)(realloc((void *)(piv_data), as * sizeof(T)));
#ifndef NDEBUG
if (!p_d) {
printf("error with PIVector<%s>::alloc\n", __PIP_TYPENAME__(T));
}
#endif
assert(p_d);
piv_data = p_d;
piv_data = p_d;
piv_rsize = as;
}
T * piv_data = nullptr;
size_t piv_size = 0;
T * piv_data = nullptr;
size_t piv_size = 0;
size_t piv_rsize = 0;
};
@@ -2642,7 +2572,7 @@ private:
//! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream).
//! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream).
template<typename T>
inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {
inline std::ostream & operator<<(std::ostream & s, const PIVector<T> & v) {
s << "{";
for (size_t i = 0; i < v.size(); ++i) {
s << v[i];
@@ -2657,7 +2587,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename T>
inline PICout operator <<(PICout s, const PIVector<T> & v) {
inline PICout operator<<(PICout s, const PIVector<T> & v) {
s.space();
s.saveAndSetControls(0);
s << "{";
@@ -2673,6 +2603,8 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
}
template<typename T>
inline void piSwap(PIVector<T> & f, PIVector<T> & s) {f.swap(s);}
inline void piSwap(PIVector<T> & f, PIVector<T> & s) {
f.swap(s);
}
#endif // PIVECTOR_H
+120 -103
View File
@@ -2,24 +2,24 @@
* \brief 2D wrapper around PIVector
*
* This file declares PIVector
*/
*/
/*
PIP - Platform Independent Primitives
2D wrapper around PIVector
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
2D wrapper around PIVector
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIVECTOR2D_H
@@ -35,154 +35,176 @@
* PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> >
*/
template <typename T>
template<typename T>
class PIVector2D {
public:
inline PIVector2D() {rows_ = cols_ = 0;}
inline PIVector2D() { rows_ = cols_ = 0; }
inline PIVector2D(size_t rows, size_t cols, const T & f = T()) {
rows_ = rows;
cols_ = cols;
mat.resize(rows*cols, f);
mat.resize(rows * cols, f);
}
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) : rows_(rows), cols_(cols), mat(v) {
mat.resize(rows*cols);
}
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v): rows_(rows), cols_(cols), mat(v) { mat.resize(rows * cols); }
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v) : rows_(rows), cols_(cols), mat(std::move(v)) {
mat.resize(rows*cols);
}
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v): rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows * cols); }
inline PIVector2D(const PIVector<PIVector<T>> & v) {
rows_ = v.size();
if (rows_) {
cols_ = v[0].size();
mat.reserve(rows_*cols_);
mat.reserve(rows_ * cols_);
for (size_t i = 0; i < rows_; i++) {
mat.append(v[i]);
}
mat.resize(rows_*cols_);
mat.resize(rows_ * cols_);
}
if (mat.isEmpty()) rows_ = cols_ = 0;
}
inline size_t rows() const {return rows_;}
inline size_t rows() const { return rows_; }
inline size_t cols() const {return cols_;}
inline size_t cols() const { return cols_; }
inline size_t size() const {return mat.size();}
inline size_t size() const { return mat.size(); }
inline ssize_t size_s() const {return mat.size_s();}
inline ssize_t size_s() const { return mat.size_s(); }
inline size_t length() const {return mat.length();}
inline size_t length() const { return mat.length(); }
inline size_t capacity() const {return mat.capacity();}
inline size_t capacity() const { return mat.capacity(); }
inline bool isEmpty() const {return mat.isEmpty();}
inline bool isEmpty() const { return mat.isEmpty(); }
inline bool isNotEmpty() const {return mat.isNotEmpty();}
inline bool isNotEmpty() const { return mat.isNotEmpty(); }
class Row {
friend class PIVector2D<T>;
private:
inline Row(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;}
inline Row(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
st_ = p->cols_ * row;
sz_ = p->cols_;
}
PIVector<T> * p_;
size_t st_, sz_;
public:
inline size_t size() const {return sz_;}
inline T & operator [](size_t index) {return (*p_)[st_ + index];}
inline const T & operator [](size_t index) const {return (*p_)[st_ + index];}
inline T * data(size_t index = 0) {return p_->data(st_ + index);}
inline const T * data(size_t index = 0) const {return p_->data(st_ + index);}
inline Row & operator =(const Row & other) {
inline size_t size() const { return sz_; }
inline T & operator[](size_t index) { return (*p_)[st_ + index]; }
inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; }
inline T * data(size_t index = 0) { return p_->data(st_ + index); }
inline const T * data(size_t index = 0) const { return p_->data(st_ + index); }
inline Row & operator=(const Row & other) {
if (p_ == other.p_ && st_ == other.st_) return *this;
size_t sz = piMin<size_t>(sz_, other.sz_);
p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this;
}
inline Row & operator =(const PIVector<T> & other) {
inline Row & operator=(const PIVector<T> & other) {
size_t sz = piMin<size_t>(sz, other.size());
p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this;
}
inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);}
inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); }
};
class Col {
friend class PIVector2D<T>;
private:
inline Col(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;}
inline Col(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
step_ = p->cols_;
row_ = row;
sz_ = p->rows_;
}
PIVector<T> * p_;
size_t step_, row_, sz_;
public:
inline size_t size() const {return sz_;}
inline T & operator [](size_t index) {return (*p_)[index * step_ + row_];}
inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];}
inline T * data(size_t index = 0) {return p_->data(index * step_ + row_);}
inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);}
inline Col & operator =(const Col & other) {
inline size_t size() const { return sz_; }
inline T & operator[](size_t index) { return (*p_)[index * step_ + row_]; }
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; }
inline T * data(size_t index = 0) { return p_->data(index * step_ + row_); }
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); }
inline Col & operator=(const Col & other) {
if (p_ == other.p_ && row_ == other.row_) return *this;
size_t sz = piMin<size_t>(sz_, other.sz_);
for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i];
for (int i = 0; i < sz; ++i)
(*p_)[i * step_ + row_] = other[i];
return *this;
}
inline Row & operator =(const PIVector<T> & other) {
inline Row & operator=(const PIVector<T> & other) {
size_t sz = piMin<size_t>(sz_, other.size());
for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i];
for (int i = 0; i < sz; ++i)
(*p_)[i * step_ + row_] = other[i];
return *this;
}
inline PIVector<T> toVector() const {
PIVector<T> ret;
ret.reserve(sz_);
for (size_t i=0; i<sz_; i++) ret << (*p_)[i * step_ + row_];
for (size_t i = 0; i < sz_; i++)
ret << (*p_)[i * step_ + row_];
return ret;
}
};
class RowConst {
friend class PIVector2D<T>;
private:
inline RowConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;}
inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
st_ = p->cols_ * row;
sz_ = p->cols_;
}
const PIVector<T> * p_;
size_t st_, sz_;
public:
inline size_t size() const {return sz_;}
inline const T & operator [](size_t index) const {return (*p_)[st_ + index];}
inline const T * data(size_t index = 0) const {return p_->data(st_ + index);}
inline PIVector<T> toVector() const {return PIVector<T>(p_->data(st_), sz_);}
inline size_t size() const { return sz_; }
inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; }
inline const T * data(size_t index = 0) const { return p_->data(st_ + index); }
inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); }
};
class ColConst {
friend class PIVector2D<T>;
private:
inline ColConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;}
inline ColConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
step_ = p->cols_;
row_ = row;
sz_ = p->rows_;
}
const PIVector<T> * p_;
size_t step_, row_, sz_;
public:
inline size_t size() const {return p_->rows_;}
inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];}
inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);}
inline size_t size() const { return p_->rows_; }
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; }
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); }
inline PIVector<T> toVector() const {
PIVector<T> ret;
ret.reserve(sz_);
for (int i=0; i<size(); i++) ret << (*p_)[i * step_ + row_];
for (int i = 0; i < size(); i++)
ret << (*p_)[i * step_ + row_];
return ret;
}
};
inline T & element(size_t row, size_t col) {return mat[row * cols_ + col];}
inline const T & element(size_t row, size_t col) const {return mat[row * cols_ + col];}
inline const T & at(size_t row, size_t col) const {return mat[row * cols_ + col];}
inline Row operator[](size_t index) {return Row(this, index);}
inline RowConst operator[](size_t index) const {return RowConst(this, index);}
inline T * data(size_t index = 0) {return mat.data(index);}
inline const T * data(size_t index = 0) const {return mat.data(index);}
inline T & element(size_t row, size_t col) { return mat[row * cols_ + col]; }
inline const T & element(size_t row, size_t col) const { return mat[row * cols_ + col]; }
inline const T & at(size_t row, size_t col) const { return mat[row * cols_ + col]; }
inline Row operator[](size_t index) { return Row(this, index); }
inline RowConst operator[](size_t index) const { return RowConst(this, index); }
inline T * data(size_t index = 0) { return mat.data(index); }
inline const T * data(size_t index = 0) const { return mat.data(index); }
inline Row row(size_t index) {return Row(this, index);}
inline RowConst row(size_t index) const {return RowConst(this, index);}
inline Col col(size_t index) {return Col(this, index);}
inline ColConst col(size_t index) const {return ColConst(this, index);}
inline Row row(size_t index) { return Row(this, index); }
inline RowConst row(size_t index) const { return RowConst(this, index); }
inline Col col(size_t index) { return Col(this, index); }
inline ColConst col(size_t index) const { return ColConst(this, index); }
inline PIVector2D<T> & setRow(size_t row, const Row & other) {
size_t sz = piMin<size_t>(cols_, other.sz_);
mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
@@ -227,20 +249,20 @@ public:
}
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) {
mat.resize(rows*cols_, f);
rows_ = rows;
mat.resize(rows * cols_, f);
rows_ = rows;
int cs = (cols - cols_);
if (cs < 0) {
for (size_t r=0; r<rows; ++r) {
mat.remove(r*cols + cols, -cs);
for (size_t r = 0; r < rows; ++r) {
mat.remove(r * cols + cols, -cs);
}
}
mat.resize(rows*cols, f);
mat.resize(rows * cols, f);
if (!mat.isEmpty()) {
if (cs > 0) {
for (size_t r=0; r<rows_; ++r) {
for (int i=0; i<cs; ++i)
mat.insert(r*cols + cols_, mat.take_back());
for (size_t r = 0; r < rows_; ++r) {
for (int i = 0; i < cs; ++i)
mat.insert(r * cols + cols_, mat.take_back());
}
}
}
@@ -248,26 +270,25 @@ public:
return *this;
}
inline bool operator ==(const PIVector2D<T> & t) const {
if (cols_ != t.cols_ || rows_ != t.rows_)
return false;
inline bool operator==(const PIVector2D<T> & t) const {
if (cols_ != t.cols_ || rows_ != t.rows_) return false;
return mat == t.mat;
}
inline bool operator !=(const PIVector2D<T> & t) const {return !(*this == t);}
inline bool operator!=(const PIVector2D<T> & t) const { return !(*this == t); }
inline PIVector<PIVector<T> > toVectors() const {
PIVector<PIVector<T> > ret;
inline PIVector<PIVector<T>> toVectors() const {
PIVector<PIVector<T>> ret;
ret.reserve(rows_);
for(size_t i = 0; i < rows_; ++i)
ret << PIVector<T>(mat.data(i*cols_), cols_);
for (size_t i = 0; i < rows_; ++i)
ret << PIVector<T>(mat.data(i * cols_), cols_);
return ret;
}
inline PIVector<T> toPlainVector() const {return mat;}
inline PIVector<T> toPlainVector() const { return mat; }
inline PIVector<T> & plainVector() {return mat;}
inline PIVector<T> & plainVector() { return mat; }
inline const PIVector<T> & plainVector() const {return mat;}
inline const PIVector<T> & plainVector() const { return mat; }
inline void swap(PIVector2D<T> & other) {
mat.swap(other.mat);
@@ -275,13 +296,11 @@ public:
piSwap<size_t>(cols_, other.cols_);
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
rows_ = r;
cols_ = c;
mat._resizeRaw(r*c);
mat._resizeRaw(r * c);
return *this;
}
@@ -290,14 +309,12 @@ public:
mat.clear();
}
template <typename ST>
template<typename ST>
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const {
return PIVector2D<ST>(rows_, cols_, mat.map(f));
}
inline void forEach(std::function<void(const T &)> f) const {
mat.forEach(f);
}
inline void forEach(std::function<void(const T &)> f) const { mat.forEach(f); }
inline PIVector2D<T> & forEach(std::function<void(T &)> f) {
mat.forEach(f);
@@ -311,7 +328,7 @@ protected:
template<typename T>
inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
inline PICout operator<<(PICout s, const PIVector2D<T> & v) {
s.saveAndSetControls(0);
s << "{";
for (size_t i = 0; i < v.rows(); ++i) {
@@ -321,7 +338,7 @@ inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
if (j < v.cols() - 1) s << ", ";
}
s << " }";
if (i < v.rows() - 1) s << PICoutManipulators::NewLine ;
if (i < v.rows() - 1) s << PICoutManipulators::NewLine;
}
if (v.isEmpty()) s << "{ }";
s << "}";
+340 -244
View File
@@ -11,33 +11,34 @@
* \~russian
* Этот файл реализует первый слой после системы и объявляет
* несколько базовых полезных методов
*/
*/
/*
PIP - Platform Independent Primitives
Base types and functions
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Base types and functions
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIBASE_H
#define PIBASE_H
#include "pip_defs.h"
#include "pip_export.h"
#include "pip_version.h"
#include "piplatform.h"
#include "pip_export.h"
#include "pip_defs.h"
#include <string.h>
//! \~english
@@ -204,184 +205,195 @@
//! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной
# define NO_UNUSED(x)
#undef MICRO_PIP
#undef FREERTOS
#endif //DOXYGEN
# undef MICRO_PIP
# undef FREERTOS
#endif // DOXYGEN
#ifdef CC_AVR_GCC
# include <ArduinoSTL.h>
#endif
#include <functional>
#include <cstddef>
#include <cassert>
#include <limits>
#include <atomic>
#include <cassert>
#include <cstddef>
#include <functional>
#include <limits>
#ifdef WINDOWS
# ifdef CC_VC
# define SHUT_RDWR 2
# pragma comment(lib, "Ws2_32.lib")
# pragma comment(lib, "Iphlpapi.lib")
# pragma comment(lib, "Psapi.lib")
# ifdef ARCH_BITS_32
# define _X86_
# else
# define _IA64_
# endif
# define SHUT_RDWR 2
# pragma comment(lib, "Ws2_32.lib")
# pragma comment(lib, "Iphlpapi.lib")
# pragma comment(lib, "Psapi.lib")
# ifdef ARCH_BITS_32
# define _X86_
# else
# define _IA64_
# endif
# else
# define SHUT_RDWR SD_BOTH
# define SHUT_RDWR SD_BOTH
# endif
typedef int socklen_t;
extern long long __pi_perf_freq;
typedef int socklen_t;
extern long long __pi_perf_freq;
#endif
#ifndef DOXYGEN
#ifdef ANDROID
///# define tcdrain(fd) ioctl(fd, TCSBRK, 1)
//inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
//inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
#endif
#ifdef MAC_OS
# define environ (*_NSGetEnviron())
typedef long time_t;
#endif
#ifdef LINUX
# define environ __environ
#endif
#ifdef FREE_BSD
extern char ** environ;
#endif
#ifndef NO_UNUSED
# define NO_UNUSED(x) (void)x
#endif
#ifndef assert
# define assert(x)
# define assertm(exp, msg)
#else
# define assertm(exp, msg) assert(((void)msg, exp))
#endif
#ifdef MICRO_PIP
# define __PIP_TYPENAME__(T) "?"
#else
# define __PIP_TYPENAME__(T) typeid(T).name()
#endif
#ifdef CC_GCC
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED __attribute__((deprecated))
# define DEPRECATEDM(msg) __attribute__((deprecated(msg)))
# if CC_GCC_VERSION > 0x025F // > 2.95
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
# ifdef LINUX
# define HAS_LOCALE
# endif
# ifdef MAC_OS
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
# pragma GCC diagnostic ignored "-Wc++11-extensions"
# endif
# endif
# ifdef ANDROID
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wextra"
# pragma GCC diagnostic ignored "-Wc++11-extensions"
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
//# pragma GCC diagnostic ignored "-Wliteral-suffix"
/// # define tcdrain(fd) ioctl(fd, TCSBRK, 1)
// inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
// inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
# endif
#endif
#ifdef CC_VC
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED __declspec(deprecated)
# define DEPRECATEDM(msg) __declspec(deprecated(msg))
# pragma warning(disable: 4018)
# pragma warning(disable: 4061)
# pragma warning(disable: 4100)
# pragma warning(disable: 4239)
# pragma warning(disable: 4242)
# pragma warning(disable: 4244)
# pragma warning(disable: 4251)
# pragma warning(disable: 4365)
# pragma warning(disable: 4512)
# pragma warning(disable: 4668)
# pragma warning(disable: 4710)
# pragma warning(disable: 4800)
# pragma warning(disable: 4820)
# pragma warning(disable: 4986)
# pragma warning(disable: 4996)
# ifdef ARCH_BITS_32
typedef long ssize_t;
# ifdef MAC_OS
# define environ (*_NSGetEnviron())
typedef long time_t;
# endif
# ifdef LINUX
# define environ __environ
# endif
# ifdef FREE_BSD
extern char ** environ;
# endif
# ifndef NO_UNUSED
# define NO_UNUSED(x) (void)x
# endif
# ifndef assert
# define assert(x)
# define assertm(exp, msg)
# else
typedef long long ssize_t;
# define assertm(exp, msg) assert(((void)msg, exp))
# endif
#endif
#ifdef CC_OTHER
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED
# define DEPRECATEDM(msg)
#endif
# ifdef MICRO_PIP
# define __PIP_TYPENAME__(T) "?"
# else
# define __PIP_TYPENAME__(T) typeid(T).name()
# endif
#endif //DOXYGEN
# ifdef CC_GCC
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED __attribute__((deprecated))
# define DEPRECATEDM(msg) __attribute__((deprecated(msg)))
# if CC_GCC_VERSION > 0x025F // > 2.95
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
# ifdef LINUX
# define HAS_LOCALE
# endif
# ifdef MAC_OS
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
# pragma GCC diagnostic ignored "-Wc++11-extensions"
# endif
# endif
# ifdef ANDROID
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wextra"
# pragma GCC diagnostic ignored "-Wc++11-extensions"
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
// # pragma GCC diagnostic ignored "-Wliteral-suffix"
# endif
# endif
# ifdef CC_VC
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED __declspec(deprecated)
# define DEPRECATEDM(msg) __declspec(deprecated(msg))
# pragma warning(disable: 4018)
# pragma warning(disable: 4061)
# pragma warning(disable: 4100)
# pragma warning(disable: 4239)
# pragma warning(disable: 4242)
# pragma warning(disable: 4244)
# pragma warning(disable: 4251)
# pragma warning(disable: 4365)
# pragma warning(disable: 4512)
# pragma warning(disable: 4668)
# pragma warning(disable: 4710)
# pragma warning(disable: 4800)
# pragma warning(disable: 4820)
# pragma warning(disable: 4986)
# pragma warning(disable: 4996)
# ifdef ARCH_BITS_32
typedef long ssize_t;
# else
typedef long long ssize_t;
# endif
# endif
# ifdef CC_OTHER
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED
# define DEPRECATEDM(msg)
# endif
#endif // DOXYGEN
// Private data macros
#ifndef DOXYGEN
#define PRIVATE_DECLARATION(e) \
struct __Private__; \
friend struct __Private__; \
struct e __PrivateInitializer__ { \
__PrivateInitializer__(); \
__PrivateInitializer__(const __PrivateInitializer__ & o); \
~__PrivateInitializer__(); \
__PrivateInitializer__ & operator =(const __PrivateInitializer__ & o); \
__Private__ * p; \
}; \
__PrivateInitializer__ __privateinitializer__;
# define PRIVATE_DECLARATION(e) \
struct __Private__; \
friend struct __Private__; \
struct e __PrivateInitializer__ { \
__PrivateInitializer__(); \
__PrivateInitializer__(const __PrivateInitializer__ & o); \
~__PrivateInitializer__(); \
__PrivateInitializer__ & operator=(const __PrivateInitializer__ & o); \
__Private__ * p; \
}; \
__PrivateInitializer__ __privateinitializer__;
#define PRIVATE_DEFINITION_START(c) \
struct c::__Private__ {
# define PRIVATE_DEFINITION_START(c) struct c::__Private__ {
# define PRIVATE_DEFINITION_END(c) \
} \
; \
c::__PrivateInitializer__::__PrivateInitializer__() { \
p = new c::__Private__(); \
} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ &) { /*if (p) delete p;*/ \
p = new c::__Private__(); \
} \
c::__PrivateInitializer__::~__PrivateInitializer__() { \
delete p; \
p = 0; \
} \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator=(const c::__PrivateInitializer__ &) { \
if (p) delete p; \
p = new c::__Private__(); \
return *this; \
}
#define PRIVATE_DEFINITION_END(c) \
}; \
c::__PrivateInitializer__::__PrivateInitializer__() {p = new c::__Private__();} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \
c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & ) {if (p) delete p; p = new c::__Private__(); return *this;}
# define PRIVATE (__privateinitializer__.p)
# define PRIVATEWB __privateinitializer__.p
#define PRIVATE (__privateinitializer__.p)
#define PRIVATEWB __privateinitializer__.p
#endif // DOXYGEN
#endif //DOXYGEN
#define NO_COPY_CLASS(name) \
name(const name&) = delete; \
name& operator=(const name&) = delete;
#define NO_COPY_CLASS(name) \
name(const name &) = delete; \
name & operator=(const name &) = delete;
#define _PIP_ADD_COUNTER_WS(a, cnt, line) a##cnt##_##line
#define _PIP_ADD_COUNTER_WF(a, cnt, line) _PIP_ADD_COUNTER_WS(a, cnt, line)
#define _PIP_ADD_COUNTER(a) _PIP_ADD_COUNTER_WF(a, __COUNTER__, __LINE__)
#define _PIP_ADD_COUNTER(a) _PIP_ADD_COUNTER_WF(a, __COUNTER__, __LINE__)
#define STATIC_INITIALIZER_BEGIN \
class { \
class _Initializer_ { \
public: \
class { \
class _Initializer_ { \
public: \
_Initializer_() {
#define STATIC_INITIALIZER_END \
} \
} _initializer_; \
} _PIP_ADD_COUNTER(_pip_initializer_);
} \
} \
_initializer_; \
} \
_PIP_ADD_COUNTER(_pip_initializer_);
//! \~\brief
@@ -392,9 +404,9 @@
//! \~russian Используется в \a piMinSleep(), \a PIThread, \a PITimer::Pool. По умолчанию равна 1мс.
#ifndef PIP_MIN_MSLEEP
# ifndef MICRO_PIP
# define PIP_MIN_MSLEEP 1.
# define PIP_MIN_MSLEEP 1.
# else
# define PIP_MIN_MSLEEP 10.
# define PIP_MIN_MSLEEP 10.
# endif
#endif
@@ -402,7 +414,7 @@
//! \~\brief
//! \~english Macro used for infinite loop
//! \~russian Макрос для бесконечного цикла
#define FOREVER for (;;)
#define FOREVER for (;;)
//! \~\brief
//! \~english Macro used for infinite wait
@@ -441,7 +453,12 @@ typedef long double ldouble;
//! \~\details
//! \~english Example:\n \snippet piincludes.cpp swap
//! \~russian Пример:\n \snippet piincludes.cpp swap
template<typename T> inline void piSwap(T & f, T & s) {T t(std::move(f)); f = std::move(s); s = std::move(t);}
template<typename T>
inline void piSwap(T & f, T & s) {
T t(std::move(f));
f = std::move(s);
s = std::move(t);
}
//! \~\brief
//! \~english Templated function for swap two values without "="
@@ -449,36 +466,38 @@ template<typename T> inline void piSwap(T & f, T & s) {T t(std::move(f)); f = st
//! \~\details
//! \~english Example:\n \snippet piincludes.cpp swapBinary
//! \~russian Пример:\n \snippet piincludes.cpp swapBinary
template<typename T> inline void piSwapBinary(T & f, T & s) {
if ((size_t*)&f == (size_t*)&s) return;
template<typename T>
inline void piSwapBinary(T & f, T & s) {
if ((size_t *)&f == (size_t *)&s) return;
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
size_t i = 0;
for (i = 0; i < j; ++i) {
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
((size_t*)(&s))[i] ^= ((size_t*)(&f))[i];
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
((size_t *)(&f))[i] ^= ((size_t *)(&s))[i];
((size_t *)(&s))[i] ^= ((size_t *)(&f))[i];
((size_t *)(&f))[i] ^= ((size_t *)(&s))[i];
}
for (i = bs; i < bf; ++i) {
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
((uchar*)(&s))[i] ^= ((uchar*)(&f))[i];
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
((uchar *)(&f))[i] ^= ((uchar *)(&s))[i];
((uchar *)(&s))[i] ^= ((uchar *)(&f))[i];
((uchar *)(&f))[i] ^= ((uchar *)(&s))[i];
}
}
template<> inline void piSwapBinary(const void *& f, const void *& s) {
if ((size_t*)f == (size_t*)s) return;
template<>
inline void piSwapBinary(const void *& f, const void *& s) {
if ((size_t *)f == (size_t *)s) return;
size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *);
size_t i = 0;
void * pf = const_cast<void*>(f), * ps = const_cast<void*>(s);
void *pf = const_cast<void *>(f), *ps = const_cast<void *>(s);
for (i = 0; i < j; ++i) {
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
((size_t*)(&ps))[i] ^= ((size_t*)(&pf))[i];
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
((size_t *)(&pf))[i] ^= ((size_t *)(&ps))[i];
((size_t *)(&ps))[i] ^= ((size_t *)(&pf))[i];
((size_t *)(&pf))[i] ^= ((size_t *)(&ps))[i];
}
for (i = bs; i < bf; ++i) {
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
((uchar*)(&ps))[i] ^= ((uchar*)(&pf))[i];
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
((uchar *)(&pf))[i] ^= ((uchar *)(&ps))[i];
((uchar *)(&ps))[i] ^= ((uchar *)(&pf))[i];
((uchar *)(&pf))[i] ^= ((uchar *)(&ps))[i];
}
}
@@ -491,8 +510,7 @@ template<> inline void piSwapBinary(const void *& f, const void *& s) {
//! \~russian Пример:\n \snippet piincludes.cpp compareBinary
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
for (size_t i = 0; i < size; ++i)
if (((const uchar*)f)[i] != ((const uchar*)s)[i])
return false;
if (((const uchar *)f)[i] != ((const uchar *)s)[i]) return false;
return true;
}
@@ -516,7 +534,10 @@ inline bool piCompareBinary(const void * f, const void * s, size_t size) {
//!
//! Пример:
//! \snippet piincludes.cpp round
template<typename T> inline constexpr int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
template<typename T>
inline constexpr int piRound(const T & v) {
return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));
}
//! \~\brief
//! \~english Templated function return floor of float falue
@@ -538,7 +559,10 @@ template<typename T> inline constexpr int piRound(const T & v) {return int(v >=
//!
//! Пример:
//! \snippet piincludes.cpp floor
template<typename T> inline constexpr int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
template<typename T>
inline constexpr int piFloor(const T & v) {
return v < T(0) ? int(v) - 1 : int(v);
}
//! \~\brief
//! \~english Templated function return ceil of float falue
@@ -560,7 +584,10 @@ template<typename T> inline constexpr int piFloor(const T & v) {return v < T(0)
//!
//! Пример:
//! \snippet piincludes.cpp ceil
template<typename T> inline constexpr int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
template<typename T>
inline constexpr int piCeil(const T & v) {
return v < T(0) ? int(v) : int(v) + 1;
}
//! \~\brief
//! \~english Templated function return absolute of numeric falue
@@ -590,7 +617,10 @@ template<typename T> inline constexpr int piCeil(const T & v) {return v < T(0) ?
//!
//! Пример:
//! \snippet piincludes.cpp abs
template<typename T> inline constexpr T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
template<typename T>
inline constexpr T piAbs(const T & v) {
return (v >= T(0) ? v : -v);
}
//! \~\brief
//! \~english Templated function return minimum of two values
@@ -618,7 +648,10 @@ template<typename T> inline constexpr T piAbs(const T & v) {return (v >= T(0) ?
//!
//! Пример:
//! \snippet piincludes.cpp min2
template<typename T> inline constexpr T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
template<typename T>
inline constexpr T piMin(const T & f, const T & s) {
return ((f > s) ? s : f);
}
//! \~\brief
//! \~english Templated function return minimum of tree values
@@ -646,7 +679,10 @@ template<typename T> inline constexpr T piMin(const T & f, const T & s) {return
//!
//! Пример:
//! \snippet piincludes.cpp min3
template<typename T> inline constexpr T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
template<typename T>
inline constexpr T piMin(const T & f, const T & s, const T & t) {
return ((f < s && f < t) ? f : ((s < t) ? s : t));
}
//! \~\brief
//! \~english Templated function return maximum of two values
@@ -674,7 +710,10 @@ template<typename T> inline constexpr T piMin(const T & f, const T & s, const T
//!
//! Пример:
//! \snippet piincludes.cpp max2
template<typename T> inline constexpr T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
template<typename T>
inline constexpr T piMax(const T & f, const T & s) {
return ((f < s) ? s : f);
}
//! \~\brief
//! \~english Templated function return maximum of tree values
@@ -702,7 +741,10 @@ template<typename T> inline constexpr T piMax(const T & f, const T & s) {return
//!
//! Пример:
//! \snippet piincludes.cpp max3
template<typename T> inline constexpr T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
template<typename T>
inline constexpr T piMax(const T & f, const T & s, const T & t) {
return ((f > s && f > t) ? f : ((s > t) ? s : t));
}
//! \~\brief
//! \~english Templated function return clamped value
@@ -732,14 +774,17 @@ template<typename T> inline constexpr T piMax(const T & f, const T & s, const T
//!
//! Пример:
//! \snippet piincludes.cpp clamp
template<typename T> inline constexpr T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
template<typename T>
inline constexpr T piClamp(const T & v, const T & min, const T & max) {
return (v > max ? max : (v < min ? min : v));
}
//! \~\brief
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1])
inline void piLetobe(void * data, int size) {
for (int i = 0; i < size / 2; i++)
piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]);
piSwap<uchar>(((uchar *)data)[size - i - 1], ((uchar *)data)[i]);
}
//! \~\brief
@@ -768,7 +813,10 @@ inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric
//! \~\brief
//! \~english Templated function that inverse byte order of value "v"
//! \~russian Шаблонный метод, меняющий порядок байт в переменной "v"
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
template<typename T>
inline void piLetobe(T * v) {
piLetobe(v, sizeof(T));
}
//! \~\brief
//! \~english Templated function that returns "v" with inversed byte order
@@ -794,14 +842,26 @@ template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
//!
//! Пример:
//! \snippet piincludes.cpp letobe
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
template<typename T>
inline T piLetobe(const T & v) {
T tv(v);
piLetobe(&tv, sizeof(T));
return tv;
}
// specialization
template<> inline uint16_t piLetobe(const uint16_t & v) {return (v << 8) | (v >> 8);}
template<> inline uint32_t piLetobe(const uint32_t & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
template<> inline float piLetobe(const float & v) {
template<>
inline uint16_t piLetobe(const uint16_t & v) {
return (v << 8) | (v >> 8);
}
template<>
inline uint32_t piLetobe(const uint32_t & v) {
return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);
}
template<>
inline float piLetobe(const float & v) {
union _pletobe_f {
_pletobe_f(const float &f_) {f = f_;}
_pletobe_f(const float & f_) { f = f_; }
float f;
uint32_t v;
};
@@ -852,68 +912,104 @@ inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
}
template<typename T> inline uint piHash(const T & v) {
template<typename T>
inline uint piHash(const T & v) {
return 0;
}
template<> inline uint piHash(const char & v) {return (uint)v;}
template<> inline uint piHash(const uchar & v) {return (uint)v;}
template<> inline uint piHash(const short & v) {return (uint)v;}
template<> inline uint piHash(const ushort & v) {return (uint)v;}
template<> inline uint piHash(const int & v) {return (uint)v;}
template<> inline uint piHash(const uint & v) {return (uint)v;}
template<> inline uint piHash(const llong & v) {return piHashData((const uchar *)&v, sizeof(v));}
template<> inline uint piHash(const ullong & v) {return piHashData((const uchar *)&v, sizeof(v));}
template<> inline uint piHash(const float & v) {return (uint)v;}
template<> inline uint piHash(const double & v) {return piHashData((const uchar *)&v, sizeof(v));}
template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar *)&v, sizeof(v));}
template<>
inline uint piHash(const char & v) {
return (uint)v;
}
template<>
inline uint piHash(const uchar & v) {
return (uint)v;
}
template<>
inline uint piHash(const short & v) {
return (uint)v;
}
template<>
inline uint piHash(const ushort & v) {
return (uint)v;
}
template<>
inline uint piHash(const int & v) {
return (uint)v;
}
template<>
inline uint piHash(const uint & v) {
return (uint)v;
}
template<>
inline uint piHash(const llong & v) {
return piHashData((const uchar *)&v, sizeof(v));
}
template<>
inline uint piHash(const ullong & v) {
return piHashData((const uchar *)&v, sizeof(v));
}
template<>
inline uint piHash(const float & v) {
return (uint)v;
}
template<>
inline uint piHash(const double & v) {
return piHashData((const uchar *)&v, sizeof(v));
}
template<>
inline uint piHash(const ldouble & v) {
return piHashData((const uchar *)&v, sizeof(v));
}
template<typename T> inline void piDeleteAll(T & container) {
template<typename T>
inline void piDeleteAll(T & container) {
for (auto i: container)
delete i;
}
template<typename T> inline void piDeleteAllAndClear(T & container) {
template<typename T>
inline void piDeleteAllAndClear(T & container) {
piDeleteAll(container);
container.clear();
}
#define piRoundf piRound<float>
#define piRoundd piRound<double>
#define piRoundf piRound<float>
#define piRoundd piRound<double>
#define piComparef piCompare<float>
#define piCompared piCompare<double>
#define piFloorf piFloor<float>
#define piFloord piFloor<double>
#define piCeilf piCeil<float>
#define piCeild piCeil<double>
#define piAbss piAbs<short>
#define piAbsi piAbs<int>
#define piAbsl piAbs<long>
#define piAbsll piAbs<llong>
#define piAbsf piAbs<float>
#define piAbsd piAbs<double>
#define piMins piMin<short>
#define piMini piMin<int>
#define piMinl piMin<long>
#define piMinll piMin<llong>
#define piMinf piMin<float>
#define piMind piMin<double>
#define piMaxs piMax<short>
#define piMaxi piMax<int>
#define piMaxl piMax<long>
#define piMaxll piMax<llong>
#define piMaxf piMax<float>
#define piMaxd piMax<double>
#define piClamps piClamp<short>
#define piClampi piClamp<int>
#define piClampl piClamp<long>
#define piClampll piClamp<llong>
#define piClampf piClamp<float>
#define piClampd piClamp<double>
#define piLetobes piLetobe<ushort>
#define piLetobei piLetobe<uint>
#define piLetobel piLetobe<ulong>
#define piFloorf piFloor<float>
#define piFloord piFloor<double>
#define piCeilf piCeil<float>
#define piCeild piCeil<double>
#define piAbss piAbs<short>
#define piAbsi piAbs<int>
#define piAbsl piAbs<long>
#define piAbsll piAbs<llong>
#define piAbsf piAbs<float>
#define piAbsd piAbs<double>
#define piMins piMin<short>
#define piMini piMin<int>
#define piMinl piMin<long>
#define piMinll piMin<llong>
#define piMinf piMin<float>
#define piMind piMin<double>
#define piMaxs piMax<short>
#define piMaxi piMax<int>
#define piMaxl piMax<long>
#define piMaxll piMax<llong>
#define piMaxf piMax<float>
#define piMaxd piMax<double>
#define piClamps piClamp<short>
#define piClampi piClamp<int>
#define piClampl piClamp<long>
#define piClampll piClamp<llong>
#define piClampf piClamp<float>
#define piClampd piClamp<double>
#define piLetobes piLetobe<ushort>
#define piLetobei piLetobe<uint>
#define piLetobel piLetobe<ulong>
#define piLetobell piLetobe<ullong>
#define piLetobef piLetobe<float>
#define piLetobef piLetobe<float>
#endif // PIBASE_H
+25 -25
View File
@@ -1,23 +1,24 @@
/*
PIP - Platform Independent Primitives
Command-Line Parser
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Command-Line Parser
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picli.h"
#include "pisysteminfo.h"
@@ -69,14 +70,13 @@
PICLI::PICLI(int argc, char * argv[]) {
needParse = debug_ = true;
_prefix_short = "-";
_prefix_full = "--";
_count_opt = 0;
_count_mand = 0;
_prefix_short = "-";
_prefix_full = "--";
_count_opt = 0;
_count_mand = 0;
for (int i = 0; i < argc; ++i)
_args_raw << argv[i];
if (argc > 0)
PISystemInfo::instance()->execCommand = argv[0];
if (argc > 0) PISystemInfo::instance()->execCommand = argv[0];
}
@@ -89,10 +89,10 @@ void PICLI::parse() {
if (cra.left(2) == _prefix_full) {
last = 0;
full = cra.right(cra.length() - 2);
piForeach (Argument & a, _args) {
piForeach(Argument & a, _args) {
if (a.full_key == full) {
a.found = true;
last = &a;
last = &a;
break;
}
}
@@ -101,11 +101,11 @@ void PICLI::parse() {
last = 0;
for (int j = 1; j < cra.length(); ++j) {
bool found = false;
piForeach (Argument & a, _args) {
piForeach(Argument & a, _args) {
if ((a.short_key != '\0') && (a.short_key == cra[j])) {
a.found = true;
last = &a;
found = true;
last = &a;
found = true;
break;
}
}
@@ -125,7 +125,7 @@ void PICLI::parse() {
}
if (last == 0 ? false : last->has_value) {
last->value = cra;
last = 0;
last = 0;
}
}
}
+132 -63
View File
@@ -3,132 +3,201 @@
* \~\brief
* \~english Command-Line parser
* \~russian Парсер командной строки
*/
*/
/*
PIP - Platform Independent Primitives
Command-Line Parser
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Command-Line Parser
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICLI_H
#define PICLI_H
#include "pistringlist.h"
#include "piset.h"
#include "pistringlist.h"
//! \ingroup Core
//! \~\brief
//! \~english Command-Line parser.
//! \~russian Парсер командной строки.
class PIP_EXPORT PICLI
{
class PIP_EXPORT PICLI {
public:
//! \~english Constructs %PICLI from "argc" and "argv" from "int main()" method.
//! \~russian Создает %PICLI из "argc" и "argv" из метода "int main()".
PICLI(int argc, char * argv[]);
//! \~english Add argument with name "name", short key = name first letter and full key = name.
//! \~russian Добавляет аргумент с именем "name", коротким ключом = первой букве имени и полным ключом = имени.
void addArgument(const PIString & name, bool value = false) {_args << Argument(name, name[0], name, value); needParse = true;}
void addArgument(const PIString & name, bool value = false) {
_args << Argument(name, name[0], name, value);
needParse = true;
}
//! \~english Add argument with name "name", short key = "shortKey" and full key = name.
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени.
void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {_args << Argument(name, shortKey, name, value); needParse = true;}
void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {
_args << Argument(name, shortKey, name, value);
needParse = true;
}
//! \~english Add argument with name "name", short key = "shortKey" and full key = name.
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени.
void addArgument(const PIString & name, const char * shortKey, bool value = false) {_args << Argument(name, PIChar(shortKey), name, value); needParse = true;}
void addArgument(const PIString & name, const char * shortKey, bool value = false) {
_args << Argument(name, PIChar(shortKey), name, value);
needParse = true;
}
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey".
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey".
void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, shortKey, fullKey, value); needParse = true;}
void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {
_args << Argument(name, shortKey, fullKey, value);
needParse = true;
}
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey".
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey".
void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, PIChar(shortKey), fullKey, value); needParse = true;}
void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {
_args << Argument(name, PIChar(shortKey), fullKey, value);
needParse = true;
}
//! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command.
//! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы.
PIString rawArgument(int index) {parse(); return _args_raw[index];}
PIString mandatoryArgument(int index) {parse(); return _args_mand[index];}
PIString optionalArgument(int index) {parse(); return _args_opt[index];}
PIString rawArgument(int index) {
parse();
return _args_raw[index];
}
PIString mandatoryArgument(int index) {
parse();
return _args_mand[index];
}
PIString optionalArgument(int index) {
parse();
return _args_opt[index];
}
//! \~english Returns unparsed command-line arguments.
//! \~russian Возвращает исходные аргументы командной строки.
const PIStringList & rawArguments() {parse(); return _args_raw;}
const PIStringList & mandatoryArguments() {parse(); return _args_mand;}
const PIStringList & optionalArguments() {parse(); return _args_opt;}
const PIStringList & rawArguments() {
parse();
return _args_raw;
}
const PIStringList & mandatoryArguments() {
parse();
return _args_mand;
}
const PIStringList & optionalArguments() {
parse();
return _args_opt;
}
//! \~english Returns program execute command without arguments.
//! \~russian Возвращает команду вызова программы без аргументов.
PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();}
PIString programCommand() {
parse();
return _args_raw.size() > 0 ? _args_raw.front() : PIString();
}
//! \~english Returns if argument "name" found.
//! \~russian Возвращает найден ли аргумент "name".
bool hasArgument(const PIString & name) {parse(); piForeach (Argument & i, _args) if (i.name == name && i.found) return true; return false;}
bool hasArgument(const PIString & name) {
parse();
piForeach(Argument & i, _args)
if (i.name == name && i.found) return true;
return false;
}
//! \~english Returns argument "name" value, or empty string if this is no value.
//! \~russian Возвращает значение аргумента "name" или пустую строку, если значения нет.
PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();}
PIString argumentValue(const PIString & name) {
parse();
piForeach(Argument & i, _args)
if (i.name == name && i.found) return i.value;
return PIString();
}
//! \~english Returns short key of argument "name", or empty string if this is no argument.
//! \~russian Возвращает короткий ключ аргумента "name" или пустую строку, если аргумента нет.
PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();}
PIString argumentShortKey(const PIString & name) {
piForeach(Argument & i, _args)
if (i.name == name) return i.short_key;
return PIString();
}
//! \~english Returns full key of argument "name", or empty string if this is no argument.
//! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет.
PIString argumentFullKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.full_key; return PIString();}
const PIString & shortKeyPrefix() const {return _prefix_short;}
const PIString & fullKeyPrefix() const {return _prefix_full;}
int mandatoryArgumentsCount() const {return _count_mand;}
int optionalArgumentsCount() const {return _count_opt;}
void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix; needParse = true;}
void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix; needParse = true;}
void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;}
void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;}
bool debug() const {return debug_;}
void setDebug(bool debug) {debug_ = debug;}
PIConstChars className() const {return "PICLI";}
PIString name() const {return PIStringAscii("CLI");}
PIString argumentFullKey(const PIString & name) {
piForeach(Argument & i, _args)
if (i.name == name) return i.full_key;
return PIString();
}
const PIString & shortKeyPrefix() const { return _prefix_short; }
const PIString & fullKeyPrefix() const { return _prefix_full; }
int mandatoryArgumentsCount() const { return _count_mand; }
int optionalArgumentsCount() const { return _count_opt; }
void setShortKeyPrefix(const PIString & prefix) {
_prefix_short = prefix;
needParse = true;
}
void setFullKeyPrefix(const PIString & prefix) {
_prefix_full = prefix;
needParse = true;
}
void setMandatoryArgumentsCount(const int count) {
_count_mand = count;
needParse = true;
}
void setOptionalArgumentsCount(const int count) {
_count_opt = count;
needParse = true;
}
bool debug() const { return debug_; }
void setDebug(bool debug) { debug_ = debug; }
PIConstChars className() const { return "PICLI"; }
PIString name() const { return PIStringAscii("CLI"); }
private:
struct Argument {
Argument() {has_value = found = false;}
Argument(const PIString & n, const PIChar & s, const PIString & f, bool v) {name = n; short_key = s; full_key = f; has_value = v; found = false;}
Argument() { has_value = found = false; }
Argument(const PIString & n, const PIChar & s, const PIString & f, bool v) {
name = n;
short_key = s;
full_key = f;
has_value = v;
found = false;
}
PIString name;
PIChar short_key;
PIString full_key;
PIString value;
bool has_value, found;
};
void parse();
PIString _prefix_short, _prefix_full;
PIStringList _args_raw, _args_mand, _args_opt;
PISet<PIString> keys_full, keys_short;
PIVector<Argument> _args;
int _count_mand, _count_opt;
bool needParse, debug_;
};
#endif // PICLI_H
+25 -29
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picollection.h"
@@ -40,37 +40,35 @@
PIStringList PICollection::groups() {
PIStringList sl;
PIVector<PICollection::Group> & cg(_groups());
piForeachC (Group & g, cg)
piForeachC(Group & g, cg)
sl << g.name;
return sl;
}
PIVector<const PIObject * > PICollection::groupElements(const PIString & group) {
PIVector<const PIObject *> PICollection::groupElements(const PIString & group) {
PIVector<PICollection::Group> & cg(_groups());
piForeachC (Group & g, cg)
if (g.name == group)
return g.elements;
return PIVector<const PIObject * >();
piForeachC(Group & g, cg)
if (g.name == group) return g.elements;
return PIVector<const PIObject *>();
}
bool PICollection::addToGroup(const PIString & group, const PIObject * element) {
//piCout << "add to" << group << element;
// piCout << "add to" << group << element;
PIString n = PIStringAscii(element->className());
PIVector<PICollection::Group> & cg(_groups());
piForeach (Group & g, cg)
piForeach(Group & g, cg)
if (g.name == group) {
for (int i = 0; i < g.elements.size_s(); ++i)
if (PIString(g.elements[i]->className()) == n)
return false;
if (PIString(g.elements[i]->className()) == n) return false;
g.elements << element;
//piCout << "new group" << group << ", ok";
// piCout << "new group" << group << ", ok";
return true;
}
_groups() << Group(group);
_groups().back().elements << element;
//piCout << "new group" << group << ", ok";
// piCout << "new group" << group << ", ok";
return true;
}
@@ -83,9 +81,7 @@ PIVector<PICollection::Group> & PICollection::_groups() {
PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name, bool own) {
if (!element) return;
if (name.isNotEmpty())
const_cast<PIObject * >(element)->setName(name);
if (name.isNotEmpty()) const_cast<PIObject *>(element)->setName(name);
bool added = PICollection::addToGroup(group, element);
if (!added && own)
delete element;
if (!added && own) delete element;
}
+29 -30
View File
@@ -3,24 +3,24 @@
* \~\brief
* \~english Unique classes collection
* \~russian Коллекция уникальных классов
*/
*/
/*
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICOLLECTION_H
@@ -87,16 +87,16 @@
#else
# define ADD_TO_COLLECTION(group, object) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, "", false);
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, "", false);
# define ADD_TO_COLLECTION_WITH_NAME(group, object, name) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, #name, false);
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, #name, false);
# define ADD_NEW_TO_COLLECTION(group, class) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), "", true);
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), "", true);
# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), #name, true);
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), #name, true);
#endif
@@ -104,36 +104,35 @@
//! \~\brief
//! \~english Helper to collect and retrieve classes to groups.
//! \~russian Помощник для создания и получения классов в группы.
class PIP_EXPORT PICollection
{
class PIP_EXPORT PICollection {
friend class __PICollectionInitializer;
public:
PICollection() {;}
PICollection() { ; }
//! \~english Returns all existing groups by their names
//! \~russian Возвращает имена всех групп
static PIStringList groups();
//! \~english Returns all elements of group "group"
//! \~russian Возвращает все элементы группы "group"
static PIVector<const PIObject * > groupElements(const PIString & group);
static PIVector<const PIObject *> groupElements(const PIString & group);
static bool addToGroup(const PIString & group, const PIObject * element);
class PIP_EXPORT CollectionAdder {
public:
CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false);
};
protected:
struct PIP_EXPORT Group {
Group(const PIString & name_ = PIString()) {name = name_;}
Group(const PIString & name_ = PIString()) { name = name_; }
PIString name;
PIVector<const PIObject * > elements;
PIVector<const PIObject *> elements;
};
static PIVector<Group> & _groups();
};
#endif // PICOLLECTION_H
+18 -18
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Core Core
//! \~\brief
@@ -51,12 +51,12 @@
#ifndef PICOREMODULE_H
#define PICOREMODULE_H
#include "picollection.h"
#include "piobject.h"
#include "pitime.h"
#include "picli.h"
#include "pichunkstream.h"
#include "pipropertystorage.h"
#include "picli.h"
#include "picollection.h"
#include "pijson.h"
#include "piobject.h"
#include "pipropertystorage.h"
#include "pitime.h"
#endif // PICOREMODULE_H
+119 -82
View File
@@ -1,35 +1,36 @@
/*
PIP - Platform Independent Primitives
Universal output to console class
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Universal output to console class
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "picout.h"
#include "pibytearray.h"
#include "pistack.h"
#include "piincludes_p.h"
#include "piobject.h"
#include "pistack.h"
#include "pistring_std.h"
#ifdef HAS_LOCALE
# include <locale>
# include <codecvt>
# include <locale>
#endif
#ifdef WINDOWS
# include <wincon.h>
# include <windows.h>
# include <wingdi.h>
# include <wincon.h>
# define COMMON_LVB_UNDERSCORE 0x8000
#endif
@@ -106,13 +107,13 @@
class NotifierObject: public PIObject {
PIOBJECT(NotifierObject)
public:
NotifierObject() {}
EVENT2(finished, int, id, PIString*, buffer);
EVENT2(finished, int, id, PIString *, buffer);
};
PICout::Notifier::Notifier() {
o = new NotifierObject();
}
@@ -129,12 +130,16 @@ PIObject * PICout::Notifier::object() {
}
using namespace PICoutManipulators;
PIMutex & PICout::__mutex__() {static PIMutex * ret = new PIMutex(); return *ret;}
PIString & PICout::__string__() {static PIString * ret = new PIString(); return *ret;}
PIMutex & PICout::__mutex__() {
static PIMutex * ret = new PIMutex();
return *ret;
}
PIString & PICout::__string__() {
static PIString * ret = new PIString();
return *ret;
}
PICout::OutputDevices PICout::devs = PICout::StdOut;
@@ -149,7 +154,7 @@ PRIVATE_DEFINITION_END(PICout)
#ifdef WINDOWS
void * PICout::__Private__::hOut = 0;
WORD PICout::__Private__::dattr = 0;
WORD PICout::__Private__::dattr = 0;
DWORD PICout::__Private__::smode = 0;
#endif
@@ -164,9 +169,16 @@ PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cn
}
PICout::PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), act_(other.act_), cnb_(other.cnb_), attr_(other.attr_),
id_(other.id_), buffer_(other.buffer_), co_(other.co_) {
}
PICout::PICout(const PICout & other)
: fo_(other.fo_)
, cc_(true)
, fc_(false)
, act_(other.act_)
, cnb_(other.cnb_)
, attr_(other.attr_)
, id_(other.id_)
, buffer_(other.buffer_)
, co_(other.co_) {}
PICout::~PICout() {
@@ -178,12 +190,12 @@ PICout::~PICout() {
PICout::__mutex__().unlock();
}
if (buffer_) {
((NotifierObject*)Notifier::object())->finished(id_, buffer_);
((NotifierObject *)Notifier::object())->finished(id_, buffer_);
}
}
PICout & PICout::operator <<(PICoutAction v) {
PICout & PICout::operator<<(PICoutAction v) {
if (!act_) return *this;
#ifdef WINDOWS
CONSOLE_SCREEN_BUFFER_INFO sbi;
@@ -200,7 +212,7 @@ PICout & PICout::operator <<(PICoutAction v) {
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
coord = sbi.dwCursorPosition;
coord = sbi.dwCursorPosition;
coord.X = piMax<int>(0, int(coord.X) - 1);
SetConsoleCursorPosition(__Private__::hOut, coord);
printf(" ");
@@ -236,8 +248,8 @@ PICout & PICout::operator <<(PICoutAction v) {
if (isOutputDeviceActive(StdOut)) {
#ifdef WINDOWS
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
coord = sbi.dwCursorPosition;
int dx = coord.X;
coord = sbi.dwCursorPosition;
int dx = coord.X;
coord.X = 0;
SetConsoleCursorPosition(__Private__::hOut, coord);
if (dx > 0) {
@@ -270,7 +282,7 @@ PICout & PICout::operator <<(PICoutAction v) {
}
PICout & PICout::operator <<(PICoutManipulators::PICoutFormat v) {
PICout & PICout::operator<<(PICoutManipulators::PICoutFormat v) {
switch (v) {
case PICoutManipulators::Bin: cnb_ = 2; break;
case PICoutManipulators::Oct: cnb_ = 8; break;
@@ -282,7 +294,7 @@ PICout & PICout::operator <<(PICoutManipulators::PICoutFormat v) {
}
PICout & PICout::operator <<(PIFlags<PICoutManipulators::PICoutFormat> v) {
PICout & PICout::operator<<(PIFlags<PICoutManipulators::PICoutFormat> v) {
if (v[PICoutManipulators::Bin]) cnb_ = 2;
if (v[PICoutManipulators::Oct]) cnb_ = 8;
if (v[PICoutManipulators::Dec]) cnb_ = 10;
@@ -312,32 +324,35 @@ PICout & PICout::operator <<(PIFlags<PICoutManipulators::PICoutFormat> v) {
return *this;
}
#define PIINTCOUT(v) { \
if (!act_) return *this; \
space(); \
if (cnb_ == 10) {\
if (buffer_) {\
(*buffer_) += PIString::fromNumber(v);\
} else {\
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v);\
}\
} else write(PIString::fromNumber(v, cnb_)); \
return *this; \
#define PIINTCOUT(v) \
{ \
if (!act_) return *this; \
space(); \
if (cnb_ == 10) { \
if (buffer_) { \
(*buffer_) += PIString::fromNumber(v); \
} else { \
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v); \
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v); \
} \
} else \
write(PIString::fromNumber(v, cnb_)); \
return *this; \
}
#define PIFLOATCOUT(v) { \
if (buffer_) {\
(*buffer_) += PIString::fromNumber(v, 'g');\
} else {\
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g');\
}\
}\
#define PIFLOATCOUT(v) \
{ \
if (buffer_) { \
(*buffer_) += PIString::fromNumber(v, 'g'); \
} else { \
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v); \
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g'); \
} \
} \
return *this;
PICout & PICout::operator <<(const PIString & v) {
PICout & PICout::operator<<(const PIString & v) {
space();
quote();
write(v);
@@ -345,7 +360,7 @@ PICout & PICout::operator <<(const PIString & v) {
return *this;
}
PICout & PICout::operator <<(const char * v) {
PICout & PICout::operator<<(const char * v) {
if (!act_ || !v) return *this;
if (v[0] == '\0') return *this;
space();
@@ -355,56 +370,71 @@ PICout & PICout::operator <<(const char * v) {
return *this;
}
PICout & PICout::operator <<(bool v) {
PICout & PICout::operator<<(bool v) {
if (!act_) return *this;
space();
if (v) write("true");
else write("false");
if (v)
write("true");
else
write("false");
return *this;
}
PICout & PICout::operator <<(char v) {
PICout & PICout::operator<<(char v) {
if (!act_) return *this;
space();
write(v);
return *this;
}
PICout & PICout::operator <<(uchar v) {PIINTCOUT(ushort(v))}
PICout & PICout::operator<<(uchar v){PIINTCOUT(ushort(v))}
PICout & PICout::operator <<(short int v) {PIINTCOUT(v)}
PICout & PICout::operator<<(short int v){PIINTCOUT(v)}
PICout & PICout::operator <<(ushort v) {PIINTCOUT(v)}
PICout & PICout::operator<<(ushort v){PIINTCOUT(v)}
PICout & PICout::operator <<(int v) {PIINTCOUT(v)}
PICout & PICout::operator<<(int v){PIINTCOUT(v)}
PICout & PICout::operator <<(uint v) {PIINTCOUT(v)}
PICout & PICout::operator<<(uint v){PIINTCOUT(v)}
PICout & PICout::operator <<(long v) {PIINTCOUT(v)}
PICout & PICout::operator<<(long v){PIINTCOUT(v)}
PICout & PICout::operator <<(ulong v) {PIINTCOUT(v)}
PICout & PICout::operator<<(ulong v){PIINTCOUT(v)}
PICout & PICout::operator <<(llong v) {PIINTCOUT(v)}
PICout & PICout::operator<<(llong v){PIINTCOUT(v)}
PICout & PICout::operator <<(ullong v) {PIINTCOUT(v)}
PICout & PICout::operator<<(ullong v){PIINTCOUT(v)}
PICout & PICout::operator <<(float v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
PICout & PICout::operator<<(float v) {
if (!act_) return *this;
space();
PIFLOATCOUT(v)
}
PICout & PICout::operator <<(double v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
PICout & PICout::operator<<(double v) {
if (!act_) return *this;
space();
PIFLOATCOUT(v)
}
PICout & PICout::operator <<(ldouble v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
PICout & PICout::operator<<(ldouble v) {
if (!act_) return *this;
space();
PIFLOATCOUT(v)
}
PICout & PICout::operator <<(const void * v) {
PICout & PICout::operator<<(const void * v) {
if (!act_) return *this;
space();
write("0x" + PIString::fromNumber(ullong(v), 16));
return *this;
}
PICout & PICout::operator <<(const PIObject * v) {
PICout & PICout::operator<<(const PIObject * v) {
if (!act_) return *this;
space();
if (v == 0) write("PIObject*(0x0)");
if (v == 0)
write("PIObject*(0x0)");
else {
write(v->className());
write("*(0x" + PIString::fromNumber(ullong(v), 16) + ", \"" + v->name() + "\")");
@@ -412,7 +442,7 @@ PICout & PICout::operator <<(const PIObject * v) {
return *this;
}
PICout & PICout::operator <<(PICoutSpecialChar v) {
PICout & PICout::operator<<(PICoutSpecialChar v) {
if (!act_) return *this;
switch (v) {
case Null:
@@ -487,7 +517,6 @@ PICout & PICout::restoreControls() {
}
//! \details
//! \~english
//! If it is not a first output and control \a AddSpaces is set space character is put
@@ -594,9 +623,11 @@ PICout & PICout::write(const PIString & s) {
void PICout::stdoutPIString(const PIString & s) {
#ifdef HAS_LOCALE
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> utf8conv;
std::cout << utf8conv.to_bytes((char16_t*)&(const_cast<PIString&>(s).front()), (char16_t*)&(const_cast<PIString&>(s).front()) + s.size());
std::cout << utf8conv.to_bytes((char16_t *)&(const_cast<PIString &>(s).front()),
(char16_t *)&(const_cast<PIString &>(s).front()) + s.size());
#else
for (PIChar c: s) std::wcout.put(c.toWChar());
for (PIChar c: s)
std::wcout.put(c.toWChar());
#endif
}
@@ -626,7 +657,10 @@ void PICout::applyFormat(PICoutFormat f) {
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
switch (f) {
case Bin: case Oct: case Dec: case Hex: break;
case Bin:
case Oct:
case Dec:
case Hex: break;
case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break;
case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break;
case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break;
@@ -651,7 +685,10 @@ void PICout::applyFormat(PICoutFormat f) {
SetConsoleTextAttribute(__Private__::hOut, attr_);
#else
switch (f) {
case Bin: case Oct: case Dec: case Hex: break;
case Bin:
case Oct:
case Dec:
case Hex: break;
case PICoutManipulators::Bold: printf("\e[1m"); break;
case PICoutManipulators::Faint: printf("\e[2m"); break;
case PICoutManipulators::Italic: printf("\e[3m"); break;
@@ -721,6 +758,6 @@ bool PICout::isOutputDeviceActive(PICout::OutputDevice d) {
PICout PICout::withExternalBuffer(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls) {
PICout c(controls);
c.buffer_ = buffer;
c.id_ = id;
c.id_ = id;
return c;
}
+129 -115
View File
@@ -3,24 +3,24 @@
* \~\brief
* \~english Universal output to console class
* \~russian Универсальный вывод в консоль
*/
*/
/*
PIP - Platform Independent Primitives
Universal output to console class
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Universal output to console class
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICOUT_H
@@ -41,7 +41,9 @@
#else
# define piCout PICout(piDebug)
# define piCoutObj PICout(piDebug && debug()) << (PIStringAscii("[") + className() + (name().isEmpty() ? "]" : PIStringAscii(" \"") + name() + PIStringAscii("\"]")))
# define piCoutObj \
PICout(piDebug && debug()) << (PIStringAscii("[") + className() + \
(name().isEmpty() ? "]" : PIStringAscii(" \"") + name() + PIStringAscii("\"]")))
#endif
@@ -53,76 +55,75 @@ class PIObject;
//! \~russian Пространство имен содержит перечисления для контроля PICout
namespace PICoutManipulators {
//! \~english Enum contains special characters
//! \~russian Перечисление со спецсимволами
enum PICoutSpecialChar {
Null /*! \~english Null-character, '\\0' \~russian Нулевой символ, '\\0' */,
NewLine /*! \~english New line character, '\\n' \~russian Новая строка, '\\n' */,
Tab /*! \~english Tab character, '\\t' \~russian Табуляция, '\\t' */,
Esc /*! \~english Escape character, '\\e' \~russian Esc-символ, '\\e' */,
Quote /*! \~english Quote character, '\"' \~russian Кавычки, '\"' */
};
//! \~english Enum contains special characters
//! \~russian Перечисление со спецсимволами
enum PICoutSpecialChar {
Null /*! \~english Null-character, '\\0' \~russian Нулевой символ, '\\0' */,
NewLine /*! \~english New line character, '\\n' \~russian Новая строка, '\\n' */,
Tab /*! \~english Tab character, '\\t' \~russian Табуляция, '\\t' */,
Esc /*! \~english Escape character, '\\e' \~russian Esc-символ, '\\e' */,
Quote /*! \~english Quote character, '\"' \~russian Кавычки, '\"' */
};
//! \~english Enum contains immediate action
//! \~russian Перечисление с немедленными действиями
enum PICoutAction {
Flush /*! \~english Flush the output \~russian Обновить вывод */,
Backspace /*! \~english Remove last symbol \~russian Удалить последний символ */,
ShowCursor /*! \~english Show cursor \~russian Показать курсор */,
HideCursor /*! \~english Hide cursor \~russian Скрыть курсор */,
ClearLine /*! \~english Clear current line \~russian Очистить текущую строку */,
ClearScreen /*! \~english Clear the screen \~russian Очистить экран */,
SaveContol /*! \~english Save control flags, equivalent to \a saveControl() \~russian Сохранить флаги, аналогично \a saveControl() */,
RestoreControl /*! \~english Restore control flags, equivalent to \a restoreControl() \~russian Восстановить флаги, аналогично \a restoreControl() */
};
//! \~english Enum contains immediate action
//! \~russian Перечисление с немедленными действиями
enum PICoutAction {
Flush /*! \~english Flush the output \~russian Обновить вывод */,
Backspace /*! \~english Remove last symbol \~russian Удалить последний символ */,
ShowCursor /*! \~english Show cursor \~russian Показать курсор */,
HideCursor /*! \~english Hide cursor \~russian Скрыть курсор */,
ClearLine /*! \~english Clear current line \~russian Очистить текущую строку */,
ClearScreen /*! \~english Clear the screen \~russian Очистить экран */,
SaveContol /*! \~english Save control flags, equivalent to \a saveControl() \~russian Сохранить флаги, аналогично \a saveControl() */,
RestoreControl /*! \~english Restore control flags, equivalent to \a restoreControl() \~russian Восстановить флаги, аналогично \a
restoreControl() */
};
//! \~english Enum contains control of PICout
//! \~russian Перечисление с управлением PICout
enum PICoutControl {
AddNone /*! \~english No controls \~russian Без управления */ = 0x0,
AddSpaces /*! \~english Spaces will be appear after each output \~russian Пробел после каждого вывода */ = 0x1,
AddNewLine /*! \~english New line will be appear after all output \~russian Новая строка после завершения вывода */ = 0x2,
AddQuotes /*! \~english Each string will be quoted \~russian Каждая строка в кавычках */ = 0x4,
DefaultControls /*! \~english Default controls \~russian Управление по умолчанию */ = AddSpaces | AddNewLine,
AddAll /*! \~english All controls \~russian Всё управление */ = 0xFF,
NoLock /*! \~english Don`t use mutex for output \~russian Не использовать мьютекс при выводе */ = 0x100,
};
//! \~english Enum contains output format
//! \~russian Перечисление с форматом вывода
enum PICoutFormat {
Bin /*! \~english Binary representation of integers \~russian Двоичное представление для целых чисел */ = 0x01,
Oct /*! \~english Octal representation of integers \~russian Восьмеричное представление для целых чисел */ = 0x02,
Dec /*! \~english Decimal representation of integers \~russian Десятичное представление для целых чисел */ = 0x04,
Hex /*! \~english Hexadecimal representation of integers \~russian Шестнадцатеричное представление для целых чисел */ = 0x08,
Bold /*! \~english Bold \~russian Жирный */ = 0x10,
Faint /*! \~english \~russian */ = 0x20,
Italic /*! \~english \~russian */ = 0x40,
Underline /*! \~english Underline \~russian Подчеркнутый */ = 0x80,
Blink /*! \~english Blink \~russian Мигающий */ = 0x100,
Black /*! \~english Black font \~russian Чёрный */ = 0x400,
Red /*! \~english Red font \~russian Красный */ = 0x800,
Green /*! \~english Green font \~russian Зелёный */ = 0x1000,
Blue /*! \~english Blue font \~russian Синий */ = 0x2000,
Yellow /*! \~english Yellow font \~russian Жёлтый */ = 0x4000,
Magenta /*! \~english Magenta font \~russian Пурпурный */ = 0x8000,
Cyan /*! \~english Cyan font \~russian Голубой */ = 0x10000,
White /*! \~english White font \~russian Белый */ = 0x20000,
BackBlack /*! \~english Black background \~russian Чёрный фон */ = 0x40000,
BackRed /*! \~english Red background \~russian Красный фон */ = 0x80000,
BackGreen /*! \~english Green background \~russian Зелёный фон */ = 0x100000,
BackBlue /*! \~english Blue background \~russian Синий фон */ = 0x200000,
BackYellow /*! \~english Yellow background \~russian Жёлтый фон */ = 0x400000,
BackMagenta /*! \~english Magenta background \~russian Пурпурный фон */ = 0x800000,
BackCyan /*! \~english Cyan background \~russian Голубой фон */ = 0x1000000,
BackWhite /*! \~english White background \~russian Белый фон */ = 0x2000000,
Default /*! \~english Default format \~russian Формат по умолчанию */ = 0x4000000
};
typedef PIFlags<PICoutControl> PICoutControls;
}
//! \~english Enum contains control of PICout
//! \~russian Перечисление с управлением PICout
enum PICoutControl {
AddNone /*! \~english No controls \~russian Без управления */ = 0x0,
AddSpaces /*! \~english Spaces will be appear after each output \~russian Пробел после каждого вывода */ = 0x1,
AddNewLine /*! \~english New line will be appear after all output \~russian Новая строка после завершения вывода */ = 0x2,
AddQuotes /*! \~english Each string will be quoted \~russian Каждая строка в кавычках */ = 0x4,
DefaultControls /*! \~english Default controls \~russian Управление по умолчанию */ = AddSpaces | AddNewLine,
AddAll /*! \~english All controls \~russian Всё управление */ = 0xFF,
NoLock /*! \~english Don`t use mutex for output \~russian Не использовать мьютекс при выводе */ = 0x100,
};
//! \~english Enum contains output format
//! \~russian Перечисление с форматом вывода
enum PICoutFormat {
Bin /*! \~english Binary representation of integers \~russian Двоичное представление для целых чисел */ = 0x01,
Oct /*! \~english Octal representation of integers \~russian Восьмеричное представление для целых чисел */ = 0x02,
Dec /*! \~english Decimal representation of integers \~russian Десятичное представление для целых чисел */ = 0x04,
Hex /*! \~english Hexadecimal representation of integers \~russian Шестнадцатеричное представление для целых чисел */ = 0x08,
Bold /*! \~english Bold \~russian Жирный */ = 0x10,
Faint /*! \~english \~russian */ = 0x20,
Italic /*! \~english \~russian */ = 0x40,
Underline /*! \~english Underline \~russian Подчеркнутый */ = 0x80,
Blink /*! \~english Blink \~russian Мигающий */ = 0x100,
Black /*! \~english Black font \~russian Чёрный */ = 0x400,
Red /*! \~english Red font \~russian Красный */ = 0x800,
Green /*! \~english Green font \~russian Зелёный */ = 0x1000,
Blue /*! \~english Blue font \~russian Синий */ = 0x2000,
Yellow /*! \~english Yellow font \~russian Жёлтый */ = 0x4000,
Magenta /*! \~english Magenta font \~russian Пурпурный */ = 0x8000,
Cyan /*! \~english Cyan font \~russian Голубой */ = 0x10000,
White /*! \~english White font \~russian Белый */ = 0x20000,
BackBlack /*! \~english Black background \~russian Чёрный фон */ = 0x40000,
BackRed /*! \~english Red background \~russian Красный фон */ = 0x80000,
BackGreen /*! \~english Green background \~russian Зелёный фон */ = 0x100000,
BackBlue /*! \~english Blue background \~russian Синий фон */ = 0x200000,
BackYellow /*! \~english Yellow background \~russian Жёлтый фон */ = 0x400000,
BackMagenta /*! \~english Magenta background \~russian Пурпурный фон */ = 0x800000,
BackCyan /*! \~english Cyan background \~russian Голубой фон */ = 0x1000000,
BackWhite /*! \~english White background \~russian Белый фон */ = 0x2000000,
Default /*! \~english Default format \~russian Формат по умолчанию */ = 0x4000000
};
typedef PIFlags<PICoutControl> PICoutControls;
} // namespace PICoutManipulators
//! \ingroup Core
@@ -131,7 +132,6 @@ namespace PICoutManipulators {
//! \~russian Универсальный вывод в консоль.
class PIP_EXPORT PICout {
public:
//! \~english Default constructor with default features (AddSpaces and AddNewLine)
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine)
PICout(int controls = PICoutManipulators::DefaultControls);
@@ -154,6 +154,7 @@ public:
//! \~english Object that emit events from %PICout
//! \~russian Объект, который посылает события от %PICout
static PIObject * object();
private:
Notifier();
PIObject * o;
@@ -162,113 +163,123 @@ public:
//! \~english Enum contains output devices of %PICout
//! \~russian Перечисление с устройствами вывода для %PICout
enum OutputDevice {
NoDevices /** \~english %PICout is disabled \~russian %PICout неактивен */ = 0x0,
StdOut /** \~english Standard console output \~russian Стандартный вывод в консоль */ = 0x1,
Buffer /** \~english Internal buffer \~russian Внутренний буфер */ = 0x2,
AllDevices /** \~english All \~russian Все */ = 0xFFFF,
NoDevices /** \~english %PICout is disabled \~russian %PICout неактивен */ = 0x0,
StdOut /** \~english Standard console output \~russian Стандартный вывод в консоль */ = 0x1,
Buffer /** \~english Internal buffer \~russian Внутренний буфер */ = 0x2,
AllDevices /** \~english All \~russian Все */ = 0xFFFF,
};
typedef PIFlags<OutputDevice> OutputDevices;
//! \~english Output operator for strings with <tt>"const char * "</tt> type
//! \~russian Оператор вывода для строк <tt>"const char * "</tt>
PICout & operator <<(const char * v);
PICout & operator<<(const char * v);
//! \~english Output operator for \a PIString
//! \~russian Оператор вывода для \a PIString
PICout & operator <<(const PIString & v);
PICout & operator<<(const PIString & v);
//! \~english Output operator for boolean values
//! \~russian Оператор вывода для логических значений
PICout & operator <<(bool v);
PICout & operator<<(bool v);
//! \~english Output operator for <tt>"char"</tt> values
//! \~russian Оператор вывода для <tt>"char"</tt> значений
PICout & operator <<(char v);
PICout & operator<<(char v);
//! \~english Output operator for <tt>"unsigned char"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned char"</tt> значений
PICout & operator <<(uchar v);
PICout & operator<<(uchar v);
//! \~english Output operator for <tt>"short"</tt> values
//! \~russian Оператор вывода для <tt>"short"</tt> значений
PICout & operator <<(short v);
PICout & operator<<(short v);
//! \~english Output operator for <tt>"unsigned short"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned short"</tt> значений
PICout & operator <<(ushort v);
PICout & operator<<(ushort v);
//! \~english Output operator for <tt>"int"</tt> values
//! \~russian Оператор вывода для <tt>"int"</tt> значений
PICout & operator <<(int v);
PICout & operator<<(int v);
//! \~english Output operator for <tt>"unsigned int"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned int"</tt> значений
PICout & operator <<(uint v);
PICout & operator<<(uint v);
//! \~english Output operator for <tt>"long"</tt> values
//! \~russian Оператор вывода для <tt>"long"</tt> значений
PICout & operator <<(long v);
PICout & operator<<(long v);
//! \~english Output operator for <tt>"unsigned long"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned long"</tt> значений
PICout & operator <<(ulong v);
PICout & operator<<(ulong v);
//! \~english Output operator for <tt>"long long"</tt> values
//! \~russian Оператор вывода для <tt>"long long"</tt> значений
PICout & operator <<(llong v);
PICout & operator<<(llong v);
//! \~english Output operator for <tt>"unsigned long long"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned long long"</tt> значений
PICout & operator <<(ullong v);
PICout & operator<<(ullong v);
//! \~english Output operator for <tt>"float"</tt> values
//! \~russian Оператор вывода для <tt>"float"</tt> значений
PICout & operator <<(float v);
PICout & operator<<(float v);
//! \~english Output operator for <tt>"double"</tt> values
//! \~russian Оператор вывода для <tt>"double"</tt> значений
PICout & operator <<(double v);
PICout & operator<<(double v);
//! \~english Output operator for <tt>"ldouble"</tt> values
//! \~russian Оператор вывода для <tt>"ldouble"</tt> значений
PICout & operator <<(ldouble v);
PICout & operator<<(ldouble v);
//! \~english Output operator for pointers
//! \~russian Оператор вывода для указателей
PICout & operator <<(const void * v);
PICout & operator<<(const void * v);
//! \~english Output operator for PIObject and ancestors
//! \~russian Оператор вывода для PIObject и наследников
PICout & operator <<(const PIObject * v);
PICout & operator<<(const PIObject * v);
//! \~english Output operator for \a PICoutSpecialChar values
//! \~russian Оператор вывода для \a PICoutSpecialChar
PICout & operator <<(PICoutManipulators::PICoutSpecialChar v);
PICout & operator<<(PICoutManipulators::PICoutSpecialChar v);
//! \~english Output operator for \a PIFlags<PICoutFormat> values
//! \~russian Оператор вывода для \a PIFlags<PICoutFormat>
PICout & operator <<(PIFlags<PICoutManipulators::PICoutFormat> v);
PICout & operator<<(PIFlags<PICoutManipulators::PICoutFormat> v);
//! \~english Output operator for \a PICoutFormat values
//! \~russian Оператор вывода для \a PICoutFormat
PICout & operator <<(PICoutManipulators::PICoutFormat v);
PICout & operator<<(PICoutManipulators::PICoutFormat v);
//! \~english Do some action
//! \~russian Делает действие
PICout & operator <<(PICoutManipulators::PICoutAction v);
PICout & operator<<(PICoutManipulators::PICoutAction v);
//! \~english Set control flag "c" is "on" state
//! \~russian Установить флаг "c" в "on" состояние
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {
co_.setFlag(c, on);
return *this;
}
//! \~english Set control flags "c"
//! \~russian Установить флаги "c"
PICout & setControls(PICoutManipulators::PICoutControls c) {co_ = c; return *this;}
PICout & setControls(PICoutManipulators::PICoutControls c) {
co_ = c;
return *this;
}
//! \~english Exec \a saveControls() and set control flags to "c"
//! \~russian Иыполнить \a saveControls() и Установить флаги "c"
PICout & saveAndSetControls(PICoutManipulators::PICoutControls c) {saveControls(); co_ = c; return *this;}
PICout & saveAndSetControls(PICoutManipulators::PICoutControls c) {
saveControls();
co_ = c;
return *this;
}
//! \~english Save control flags to internal stack
//! \~russian Сохраняет состояние флагов во внутренний стек
@@ -331,11 +342,11 @@ public:
//! \~english Turn on output device "d". Returns if it was enabled
//! \~russian Включает устройство вывода "d". Возвращает было ли устройство активно
static bool enableOutputDevice(OutputDevice d) {return setOutputDevice(d, true);}
static bool enableOutputDevice(OutputDevice d) { return setOutputDevice(d, true); }
//! \~english Turn off output device "d". Returns if it was enabled
//! \~russian Выключает устройство вывода "d". Возвращает было ли устройство активно
static bool disableOutputDevice(OutputDevice d) {return setOutputDevice(d, false);}
static bool disableOutputDevice(OutputDevice d) { return setOutputDevice(d, false); }
//! \~english Set output to devices to "d"
//! \~russian Устанавливает устройства вывода "d"
@@ -343,7 +354,7 @@ public:
//! \~english Returns current output devices
//! \~russian Возвращает текущие устройства вывода
static OutputDevices currentOutputDevices() {return devs;}
static OutputDevices currentOutputDevices() { return devs; }
//! \~english Returns if output device "d" is active
//! \~russian Возвращает активно ли устройство вывода "d"
@@ -352,7 +363,10 @@ public:
//! \~english Construct with external buffer and ID "id". See \a Notifier for details
//! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier
static PICout withExternalBuffer(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
static PICout withExternalBuffer(PIString * buffer,
int id = 0,
PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces |
PICoutManipulators::AddNewLine);
static PIMutex & __mutex__();
static PIString & __string__();
+30 -23
View File
@@ -1,23 +1,24 @@
/*
PIP - Platform Independent Primitives
Global includes
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Global includes
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes.h"
#include "piincludes_p.h"
#include "pitime.h"
#ifndef QNX
@@ -26,21 +27,21 @@
# include <locale.h>
#endif
#ifdef MAC_OS
//# include <mach/mach_traps.h>
//# include <mach/mach.h>
// # include <mach/mach_traps.h>
// # include <mach/mach.h>
# include <mach/clock.h>
//# include <crt_externs.h>
// # include <crt_externs.h>
#endif
#include <errno.h>
bool piDebug = true;
bool piDebug = true;
double piMountInfoRefreshIntervalMs = 10000.;
lconv * currentLocale =
#ifdef ANDROID
0;
0;
#else
std::localeconv();
std::localeconv();
#endif
#ifdef MAC_OS
@@ -49,9 +50,9 @@ clock_serv_t __pi_mac_clock;
#ifdef WINDOWS
FILETIME __pi_ftjan1970;
long long __pi_perf_freq = -1;
long long __pi_perf_freq = -1;
PINtQueryTimerResolution getTimerResolutionAddr = 0;
PINtSetTimerResolution setTimerResolutionAddr = 0;
PINtSetTimerResolution setTimerResolutionAddr = 0;
#endif
void errorClear() {
@@ -65,8 +66,14 @@ void errorClear() {
PIString errorString() {
#ifdef WINDOWS
char * msg = nullptr;
int err = GetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
int err = GetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&msg,
0,
NULL);
PIString ret = PIStringAscii("code ") + PIString::fromNumber(err) + PIStringAscii(" - ");
if (msg) {
ret += PIString::fromSystem(msg).trim();
+17 -15
View File
@@ -3,24 +3,24 @@
* \~\brief
* \~english Minimal PIP includes
* \~russian Минимально-необходимые инклюды PIP
*/
*/
/*
PIP - Platform Independent Primitives
Minimal PIP includes
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Minimal PIP includes
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINCLUDES_H
@@ -28,6 +28,7 @@
#include "pibase.h"
#include "piflags.h"
#include <sys/types.h>
#ifdef PIP_STD_IOSTREAM
# include <iostream>
@@ -38,7 +39,8 @@ class PIMutexLocker;
class PIObject;
class PIString;
class PIByteArray;
template <typename P> class PIBinaryStream;
template<typename P>
class PIBinaryStream;
#ifndef MICRO_PIP
class PIInit;
#endif
+28 -26
View File
@@ -1,58 +1,60 @@
/*
PIP - Platform Independent Primitives
Private PIP includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Private PIP includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINCLUDES_P_H
#define PIINCLUDES_P_H
// clang-format off
#include "picout.h"
#ifdef WINDOWS
# ifdef _WIN32_WINNT
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0600
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0600
# endif
# include <stdarg.h>
# include <windef.h>
# include <winbase.h>
typedef LONG(NTAPI*PINtQueryTimerResolution)(PULONG, PULONG, PULONG);
typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
typedef LONG(NTAPI * PINtQueryTimerResolution)(PULONG, PULONG, PULONG);
typedef LONG(NTAPI * PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
#endif
#ifdef CC_GCC
# include <unistd.h>
#endif
#include <string.h>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <cstdlib>
#include <stdio.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#ifdef FREERTOS
# ifdef ESP_PLATFORM
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# endif
# ifdef ARDUINO_ARCH_STM32
# include <STM32FreeRTOS.h>
# include <STM32FreeRTOS.h>
# endif
#endif
// clang-format on
#endif // PIINCLUDES_P_H
+198 -198
View File
@@ -1,106 +1,105 @@
/*
PIP - Platform Independent Primitives
Initialization
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Initialization
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "piinit.h"
#include "piincludes_p.h"
#ifndef MICRO_PIP
#include "pitime.h"
#include "pisignals.h"
#include "piobject.h"
#include "pisysteminfo.h"
#include "piresourcesstorage.h"
#include "pidir.h"
#include "piprocess.h"
#ifdef ESP_PLATFORM
# include "esp_system.h"
#endif
#include <codecvt>
#ifdef WINDOWS
# include <winsock2.h>
# include "pidir.h"
# include "piobject.h"
# include "piprocess.h"
# include "piresourcesstorage.h"
# include "pisignals.h"
# include "pisysteminfo.h"
# include "pitime.h"
# ifdef ESP_PLATFORM
# include "esp_system.h"
# endif
# include <codecvt>
# ifdef WINDOWS
# include <winsock2.h>
extern FILETIME __pi_ftjan1970;
extern PINtQueryTimerResolution getTimerResolutionAddr;
extern PINtSetTimerResolution setTimerResolutionAddr;
void __PISetTimerResolution() {
if (setTimerResolutionAddr == NULL || getTimerResolutionAddr == NULL)
return;
if (setTimerResolutionAddr == NULL || getTimerResolutionAddr == NULL) return;
ULONG _max(0), _min(0), _cur(0);
//printf("getTimerResolution ...\n");
// printf("getTimerResolution ...\n");
LONG q = getTimerResolutionAddr(&_max, &_min, &_cur);
//printf("getTimerResolution %d %lu %lu %lu\n", q, _min, _max, _cur);
if (q == 0)
setTimerResolutionAddr(_min, TRUE, &_cur);
//printf("setTimerResolution %lu\n", cur);
// printf("getTimerResolution %d %lu %lu %lu\n", q, _min, _max, _cur);
if (q == 0) setTimerResolutionAddr(_min, TRUE, &_cur);
// printf("setTimerResolution %lu\n", cur);
}
#else
# include <pwd.h>
# include <sys/utsname.h>
# include <pthread.h>
# ifdef BLACKBERRY
# include <signal.h>
# else
# include <csignal>
# include <pthread.h>
# include <pwd.h>
# include <sys/utsname.h>
# ifdef BLACKBERRY
# include <signal.h>
# else
# include <csignal>
# endif
# endif
#endif
#ifdef MAC_OS
# include <mach/mach_traps.h>
# include <mach/mach.h>
# include <mach/clock.h>
# ifdef MAC_OS
# include <mach/clock.h>
# include <mach/mach.h>
# include <mach/mach_traps.h>
extern clock_serv_t __pi_mac_clock;
#endif
#ifdef PIP_ICU
# define U_NOEXCEPT
# include <unicode/uclean.h>
# include <unicode/ucnv.h>
#endif
# endif
# ifdef PIP_ICU
# define U_NOEXCEPT
# include <unicode/uclean.h>
# include <unicode/ucnv.h>
# endif
#ifdef HAS_LOCALE
# ifdef HAS_LOCALE
static locale_t currentLocale_t = 0;
#endif
# endif
PRIVATE_DEFINITION_START(PIInit)
#ifdef WINDOWS
HMODULE ntlib;
ULONG prev_res;
#endif
bool delete_locs;
# ifdef WINDOWS
HMODULE ntlib;
ULONG prev_res;
# endif
bool delete_locs;
PRIVATE_DEFINITION_END(PIInit)
void __sighandler__(PISignals::Signal s) {
//piCout << Hex << int(s);
if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput)
piMSleep(10);
// piCout << Hex << int(s);
if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput) piMSleep(10);
if (s == PISignals::UserDefined1)
dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID()));
dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") +
PIString::fromNumber(PIProcess::currentPID()));
}
PIInit::PIInit() {
file_charset = 0;
file_charset = 0;
PISystemInfo * sinfo = PISystemInfo::instance();
sinfo->execDateTime = PIDateTime::current();
sinfo->execDateTime = PIDateTime::current();
setFileCharset("UTF-8");
#ifndef ANDROID
# ifndef ANDROID
PISignals::setSlot(__sighandler__);
PISignals::grabSignals(PISignals::UserDefined1);
# ifndef WINDOWS
# ifndef WINDOWS
PISignals::grabSignals(PISignals::StopTTYInput | PISignals::StopTTYOutput);
sigset_t ss;
sigemptyset(&ss);
@@ -109,25 +108,25 @@ PIInit::PIInit() {
pthread_sigmask(SIG_BLOCK, &ss, 0);
signal(SIGPIPE, SIG_IGN);
PIStringList ifpathes;
ifpathes << PIStringAscii("/bin/ifconfig") << PIStringAscii("/sbin/ifconfig")
<< PIStringAscii("/usr/bin/ifconfig") << PIStringAscii("/usr/sbin/ifconfig");
piForeachC (PIString & i, ifpathes) {
ifpathes << PIStringAscii("/bin/ifconfig") << PIStringAscii("/sbin/ifconfig") << PIStringAscii("/usr/bin/ifconfig")
<< PIStringAscii("/usr/sbin/ifconfig");
piForeachC(PIString & i, ifpathes) {
if (fileExists(i)) {
sinfo->ifconfigPath = i;
break;
}
}
# else //WINDOWS
# else // WINDOWS
// OS version
DWORD dwVersion = GetVersion();
DWORD dwVersion = GetVersion();
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
sinfo->OS_version = PIString::fromNumber(dwMajorVersion) + "." + PIString::fromNumber(dwMinorVersion);
sinfo->OS_version = PIString::fromNumber(dwMajorVersion) + "." + PIString::fromNumber(dwMinorVersion);
// WinSock inint
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// Timers init
SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 0, 0, 0};
SystemTimeToFileTime(&jan1970, &__pi_ftjan1970);
@@ -135,7 +134,7 @@ PIInit::PIInit() {
pf.QuadPart = -1;
if (QueryPerformanceFrequency(&pf) != 0) __pi_perf_freq = pf.QuadPart;
if (__pi_perf_freq == 0) __pi_perf_freq = -1;
// Sleep precision init
PRIVATE->ntlib = LoadLibraryA("ntdll.dll");
if (PRIVATE->ntlib) {
@@ -143,66 +142,65 @@ PIInit::PIInit() {
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
__PISetTimerResolution();
}
# endif //WINDOWS
# ifdef HAS_LOCALE
//std::cout << "has locale" << std::endl;
# endif // WINDOWS
# ifdef HAS_LOCALE
// std::cout << "has locale" << std::endl;
if (currentLocale_t != 0) {
freelocale(currentLocale_t);
currentLocale_t = 0;
}
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, "C"), 0);
setlocale(LC_CTYPE, "en_US.UTF-8");
//std::ios_base::sync_with_stdio(false);
//std::locale utf8( std::locale(), new std::codecvt_utf8<wchar_t> );
//std::wcout.imbue(utf8);
# else //HAS_LOCALE
// std::ios_base::sync_with_stdio(false);
// std::locale utf8( std::locale(), new std::codecvt_utf8<wchar_t> );
// std::wcout.imbue(utf8);
# else // HAS_LOCALE
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
# endif //HAS_LOCALE
#endif //ANDROID
# endif // HAS_LOCALE
# endif // ANDROID
PRIVATE->delete_locs = false;
__syslocname__ = __sysoemname__ = 0;
__utf8name__ = const_cast<char*>("UTF-8");
#ifdef PIP_ICU
__utf8name__ = const_cast<char *>("UTF-8");
# ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
u_init(&e);
# ifdef WINDOWS
# ifdef WINDOWS
PRIVATE->delete_locs = true;
CPINFOEX cpinfo;
int l = 0;
GetCPInfoEx(CP_OEMCP, 0, &cpinfo);
for (l = 0; l < MAX_PATH; ++l)
if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ')
break;
if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ') break;
__sysoemname__ = new char[256];
memset(__sysoemname__, 0, 256);
memcpy(__sysoemname__, "ibm-", 4);
memcpy(&(__sysoemname__[4]), cpinfo.CodePageName, l);
# else
# else
/*PIString en(getenv("LANG"));
if (!en.isEmpty())
en = en.mid(en.find(".") + 1);
en = en.mid(en.find(".") + 1);
PIByteArray enba = en.toByteArray();
memcpy(__syslocname__, enba.data(), enba.size_s());*/
# endif
//piCout << __syslocname__;
//piCout << __sysoemname__;
#else //PIP_ICU
# ifdef WINDOWS
__syslocname__ = (char *)CP_ACP;
__sysoemname__ = (char *)CP_OEMCP;
__utf8name__ = (char *)CP_UTF8;
# endif
#endif //PIP_ICU
#ifdef MAC_OS
# endif
// piCout << __syslocname__;
// piCout << __sysoemname__;
# else // PIP_ICU
# ifdef WINDOWS
__syslocname__ = (char *)CP_ACP;
__sysoemname__ = (char *)CP_OEMCP;
__utf8name__ = (char *)CP_UTF8;
# endif
# endif // PIP_ICU
# ifdef MAC_OS
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
#endif
# endif
char cbuff[1024];
memset(cbuff, 0, 1024);
if (gethostname(cbuff, 1023) == 0) {
sinfo->hostname = cbuff;
}
#ifdef WINDOWS
# ifdef WINDOWS
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
sinfo->processorsCount = sysinfo.dwNumberOfProcessors;
@@ -216,57 +214,54 @@ PIInit::PIInit() {
}
int argc_(0);
wchar_t ** argv_ = CommandLineToArgvW(GetCommandLineW(), &argc_);
if (argc_ > 0 && argv_ != 0)
sinfo->execCommand = argv_[0];
if (argc_ > 0 && argv_ != 0) sinfo->execCommand = argv_[0];
LocalFree(argv_);
memset(cbuff, 0, 1024);
ulong unlen = 1023;
if (GetUserNameA(cbuff, &unlen) != 0)
sinfo->user = cbuff;
#else //WINDOWS
if (GetUserNameA(cbuff, &unlen) != 0) sinfo->user = cbuff;
# else // WINDOWS
sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN)));
passwd * ps = getpwuid(getuid());
passwd * ps = getpwuid(getuid());
if (ps)
sinfo->user = ps->pw_name;
else {
memset(cbuff, 0, 1024);
char * l = getlogin();
if (l)
sinfo->user = l;
if (l) sinfo->user = l;
}
struct utsname uns;
if (uname(&uns) == 0) {
sinfo->OS_version = uns.release;
sinfo->OS_version = uns.release;
sinfo->architecture = uns.machine;
}
#endif //WINDOWS
# endif // WINDOWS
#ifdef ESP_PLATFORM
# ifdef ESP_PLATFORM
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
sinfo->processorsCount = chip_info.cores;
sinfo->architecture = "Xtensa LX6";
//printf("silicon revision %d, ", chip_info.revision);
sinfo->OS_version = esp_get_idf_version();
#endif
sinfo->architecture = "Xtensa LX6";
// printf("silicon revision %d, ", chip_info.revision);
sinfo->OS_version = esp_get_idf_version();
# endif
sinfo->OS_name =
#ifdef WINDOWS
PIStringAscii("Windows");
#elif defined(QNX)
PIStringAscii("QNX");
#elif defined(MAC_OS)
PIStringAscii("MacOS");
#elif defined(ANDROID)
PIStringAscii("Android");
#elif defined(FREE_BSD)
PIStringAscii("FreeBSD");
#elif defined(FREERTOS)
PIStringAscii("FreeRTOS");
#elif defined(MICRO_PIP)
PIStringAscii("MicroPIP");
#else
uns.sysname;
#endif
# ifdef WINDOWS
PIStringAscii("Windows");
# elif defined(QNX)
PIStringAscii("QNX");
# elif defined(MAC_OS)
PIStringAscii("MacOS");
# elif defined(ANDROID)
PIStringAscii("Android");
# elif defined(FREE_BSD)
PIStringAscii("FreeBSD");
# elif defined(FREERTOS)
PIStringAscii("FreeRTOS");
# elif defined(MICRO_PIP)
PIStringAscii("MicroPIP");
# else
uns.sysname;
# endif
}
@@ -274,74 +269,82 @@ PIInit::~PIInit() {
if (file_charset) delete[] file_charset;
file_charset = 0;
PIResourcesStorage::instance()->clear();
#ifdef WINDOWS
# ifdef WINDOWS
WSACleanup();
if (PRIVATE->ntlib) FreeLibrary(PRIVATE->ntlib);
PRIVATE->ntlib = 0;
#endif
#ifdef MAC_OS
# endif
# ifdef MAC_OS
mach_port_deallocate(mach_task_self(), __pi_mac_clock);
#endif
# endif
if (PRIVATE->delete_locs) {
if (__syslocname__) delete __syslocname__;
if (__sysoemname__) delete __sysoemname__;
}
#ifdef PIP_ICU
# ifdef PIP_ICU
u_cleanup();
#endif
# endif
}
bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
switch (o) {
case boICU: return
#ifdef PIP_ICU
true;
#else
false;
#endif
case boUSB: return
#ifdef PIP_USB
true;
#else
false;
#endif
case boCrypt: return
#ifdef PIP_CRYPT
true;
#else
false;
#endif
case boIntrospection: return
#ifdef PIP_INTROSPECTION
true;
#else
false;
#endif
case boFFTW: return
#ifdef PIP_FFTW
true;
#else
false;
#endif
case boCompress: return
#ifdef PIP_COMPRESS
true;
#else
false;
#endif
case boOpenCL: return
#ifdef PIP_OPENCL
true;
#else
false;
#endif
case boCloud: return
#ifdef PIP_CLOUD
true;
#else
false;
#endif
case boICU:
return
# ifdef PIP_ICU
true;
# else
false;
# endif
case boUSB:
return
# ifdef PIP_USB
true;
# else
false;
# endif
case boCrypt:
return
# ifdef PIP_CRYPT
true;
# else
false;
# endif
case boIntrospection:
return
# ifdef PIP_INTROSPECTION
true;
# else
false;
# endif
case boFFTW:
return
# ifdef PIP_FFTW
true;
# else
false;
# endif
case boCompress:
return
# ifdef PIP_COMPRESS
true;
# else
false;
# endif
case boOpenCL:
return
# ifdef PIP_OPENCL
true;
# else
false;
# endif
case boCloud:
return
# ifdef PIP_CLOUD
true;
# else
false;
# endif
default: return false;
}
return false;
@@ -362,7 +365,7 @@ PIStringList PIInit::buildOptions() {
}
void PIInit::setFileCharset(const char *charset) {
void PIInit::setFileCharset(const char * charset) {
if (file_charset) delete file_charset;
file_charset = 0;
if (charset) {
@@ -375,14 +378,12 @@ void PIInit::setFileCharset(const char *charset) {
bool PIInit::fileExists(const PIString & p) {
FILE * f = fopen(p.data(), "r");
if (f == 0)
return false;
if (f == 0) return false;
fclose(f);
return true;
}
int __PIInit_Initializer__::count_(0);
PIInit * __PIInit_Initializer__::__instance__(0);
@@ -390,7 +391,7 @@ PIInit * __PIInit_Initializer__::__instance__(0);
__PIInit_Initializer__::__PIInit_Initializer__() {
count_++;
if (count_ > 1) return;
//piCout << "create PIInit";
// piCout << "create PIInit";
__instance__ = new PIInit();
}
@@ -398,7 +399,7 @@ __PIInit_Initializer__::__PIInit_Initializer__() {
__PIInit_Initializer__::~__PIInit_Initializer__() {
count_--;
if (count_ > 0) return;
//piCout << "delete PIInit";
// piCout << "delete PIInit";
if (__instance__ != 0) {
delete __instance__;
__instance__ = 0;
@@ -406,4 +407,3 @@ __PIInit_Initializer__::~__PIInit_Initializer__() {
}
#endif // MICRO_PIP
+26 -24
View File
@@ -3,24 +3,24 @@
* \~\brief
* \~english Library initialization
* \~russian Инициализация библиотеки
*/
*/
/*
PIP - Platform Independent Primitives
Initialization
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Initialization
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINIT_H
@@ -30,7 +30,7 @@
#ifndef MICRO_PIP
#include "piincludes.h"
# include "piincludes.h"
class PIFile;
@@ -51,6 +51,7 @@ static __PIInit_Initializer__ __piinit_initializer__;
class PIP_EXPORT PIInit {
friend class __PIInit_Initializer__;
friend class PIFile;
public:
~PIInit();
@@ -58,16 +59,16 @@ public:
//! \~english Build options which PIP library was built
//! \~russian Опции, с которыми был собран PIP
enum BuildOption {
boICU /*! \~english Unicode support by ICU \~russian Поддержка юникода через ICU */ = 0x01,
boUSB /*! \~english USB support \~russian Поддержка USB */ = 0x02,
boCrypt /*! \~english Crypt support \~russian Поддержка шифрования */ = 0x08,
boIntrospection /*! \~english Introspection \~russian Интроспекция */ = 0x010,
boFFTW /*! \~english FFTW3 support \~russian Поддержка FFTW3 */ = 0x40,
boCompress /*! \~english Zlib compression support \~russian Поддержка сжатия Zlib */ = 0x80,
boOpenCL /*! \~english OpenCL support \~russian Поддержка OpenCL */ = 0x100,
boICU /*! \~english Unicode support by ICU \~russian Поддержка юникода через ICU */ = 0x01,
boUSB /*! \~english USB support \~russian Поддержка USB */ = 0x02,
boCrypt /*! \~english Crypt support \~russian Поддержка шифрования */ = 0x08,
boIntrospection /*! \~english Introspection \~russian Интроспекция */ = 0x010,
boFFTW /*! \~english FFTW3 support \~russian Поддержка FFTW3 */ = 0x40,
boCompress /*! \~english Zlib compression support \~russian Поддержка сжатия Zlib */ = 0x80,
boOpenCL /*! \~english OpenCL support \~russian Поддержка OpenCL */ = 0x100,
boCloud /*! \~english PICloud transport support \~russian Поддержка облачного транспорта PICloud */ = 0x200,
};
static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
static PIInit * instance() { return __PIInit_Initializer__::__instance__; }
//! \ingroup Core
//! \~english Returns if build option was enabled
@@ -78,9 +79,10 @@ public:
//! \~english Returns build options as stringlist
//! \~russian Возвращает опции сборки как список строк
static PIStringList buildOptions();
private:
explicit PIInit();
void setFileCharset(const char *charset);
void setFileCharset(const char * charset);
bool fileExists(const PIString & p);
PRIVATE_DECLARATION(PIP_EXPORT)
char * file_charset;
+39 -26
View File
@@ -3,24 +3,24 @@
* \~\brief
* \~english Base types and functions
* \~russian Базовые типы и методы
*/
*/
/*
PIP - Platform Independent Primitives
Base types and functions
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Base types and functions
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMEMORYBLOCK_H
@@ -34,40 +34,53 @@
//! \~russian Вспомогательная структура для сохранения/извлечения произвольного блока данных в/из PIBinaryStream
struct PIMemoryBlock {
public:
//! \~english Constructs data block
//! \~russian Создает блок данных
PIMemoryBlock(void * data_ = 0, int size_ = 0) {
d = data_;
s = size_;
}
//! \~english Constructs data block
//! \~russian Создает блок данных
PIMemoryBlock(void * data_ = 0, int size_ = 0) {d = data_; s = size_;}
PIMemoryBlock(const void * data_, const int size_) {
d = const_cast<void *>(data_);
s = size_;
}
//! \~english Constructs data block
//! \~russian Создает блок данных
PIMemoryBlock(const void * data_, const int size_) {d = const_cast<void * >(data_); s = size_;}
PIMemoryBlock(const PIMemoryBlock & o) {
d = o.d;
s = o.s;
}
PIMemoryBlock(const PIMemoryBlock & o) {d = o.d; s = o.s;}
PIMemoryBlock & operator =(const PIMemoryBlock & o) {d = o.d; s = o.s; return *this;}
PIMemoryBlock & operator=(const PIMemoryBlock & o) {
d = o.d;
s = o.s;
return *this;
}
//! \~english Pointer to data
//! \~russian Указатель на данные
void * data() {return d;}
void * data() { return d; }
//! \~english Pointer to data
//! \~russian Указатель на данные
const void * data() const {return d;}
const void * data() const { return d; }
//! \~english Size of data in bytes
//! \~russian Размер данных в байтах
int size() const {return s;}
int size() const { return s; }
private:
void * d;
int s;
};
//! \~english Returns PIMemoryBlock from pointer to variable "ptr" with type "T"
//! \~russian Возвращает PIMemoryBlock из указателя "ptr" типа "T"
template<typename T>
PIMemoryBlock createMemoryBlock(const T * ptr) {return PIMemoryBlock(ptr, sizeof(T));}
PIMemoryBlock createMemoryBlock(const T * ptr) {
return PIMemoryBlock(ptr, sizeof(T));
}
#endif // PIMEMORYBLOCK_H
+153 -148
View File
@@ -1,29 +1,30 @@
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piobject.h"
#include "pithread.h"
#include "piconditionvar.h"
#include "pithread.h"
#ifndef MICRO_PIP
# include "pisysteminfo.h"
# include "pifile.h"
# include "piiostream.h"
# include "pisysteminfo.h"
#endif
@@ -104,15 +105,14 @@
PIObject::__MetaFunc::__MetaFunc() {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
types[i] = names[i] = nullptr;
types_id[i] = 0;
types_id[i] = 0;
}
}
int PIObject::__MetaFunc::argumentsCount() const {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i)
if (!types[i])
return i;
if (!types[i]) return i;
return __PIOBJECT_MAX_ARGS__;
}
@@ -129,9 +129,7 @@ PIString PIObject::__MetaFunc::arguments() const {
PIString PIObject::__MetaFunc::fullFormat() const {
PIString ret = PIStringAscii(type_ret) + " " +
PIStringAscii(scope) + "::" +
PIStringAscii(func_name) +"(";
PIString ret = PIStringAscii(type_ret) + " " + PIStringAscii(scope) + "::" + PIStringAscii(func_name) + "(";
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (!types[i]) break;
if (i > 0) ret += ", ";
@@ -143,7 +141,7 @@ PIString PIObject::__MetaFunc::fullFormat() const {
void PIObject::__MetaFunc::__setFuncName(const char * n) {
func_name = n;
func_name = n;
func_name_id = PIStringAscii(n).hash();
}
@@ -151,27 +149,25 @@ void PIObject::__MetaFunc::__setFuncName(const char * n) {
void PIObject::__MetaFunc::__addArgument(const char * t, const char * n) {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (types[i]) continue;
types[i] = t;
names[i] = n;
types[i] = t;
names[i] = n;
types_id[i] = PIObject::simplifyType(t, false).hash();
break;
}
//PICout(PICoutManipulators::DefaultControls | PICoutManipulators::AddQuotes)
// PICout(PICoutManipulators::DefaultControls | PICoutManipulators::AddQuotes)
// << "__addArgument" << t << n << PIObject::simplifyType(t) << types_id.back();
}
bool PIObject::__MetaFunc::canConnectTo(const __MetaFunc & dst, int & args_count) const {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
//piCout << "canConnectTo" << i << types[i] << dst.types[i];
// piCout << "canConnectTo" << i << types[i] << dst.types[i];
args_count = i;
if (!dst.types[i]) break;
if (!types[i]) return false;
if (types_id[i] != dst.types_id[i])
return false;
if (types_id[i] != dst.types_id[i]) return false;
}
return true;
}
@@ -182,13 +178,13 @@ PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__),
mutexObjects().lock();
objects() << this;
mutexObjects().unlock();
//piCout << "new" << this;
// piCout << "new" << this;
}
PIObject::~PIObject() {
in_event_cnt = 0;
//piCout << "delete" << this;
// piCout << "delete" << this;
mutexObjects().lock();
objects().removeAll(this);
mutexObjects().unlock();
@@ -198,19 +194,16 @@ PIObject::~PIObject() {
}
bool PIObject::execute(const PIString & method, const PIVector<PIVariantSimple> & vl) {
if (method.isEmpty()) return false;
if (!isPIObject()) {
piCout << "Error: \"execute(" << method << ")\":" << (void*)this << "is not PIObject!";
piCout << "Error: \"execute(" << method << ")\":" << (void *)this << "is not PIObject!";
return false;
}
int ac = 0;
__MetaFunc func;
bool ok = findSuitableMethodV(method, vl.size_s(), ac, func);
if (!ok)
return false;
if (!ok) return false;
callAddrV(func.addrV, toThis(), ac, vl);
return true;
}
@@ -218,18 +211,17 @@ bool PIObject::execute(const PIString & method, const PIVector<PIVariantSimple>
bool PIObject::executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) {
if (!isPIObject()) {
piCout << "Error: \"executeQueued(" << method << ")\": this(" << (void*)this << ") is not PIObject!";
piCout << "Error: \"executeQueued(" << method << ")\": this(" << (void *)this << ") is not PIObject!";
return false;
}
if (!performer->isPIObject()) {
piCout << "Error: \"executeQueued(" << method << ")\": performer(" << (void*)performer << ") is not PIObject!";
piCout << "Error: \"executeQueued(" << method << ")\": performer(" << (void *)performer << ") is not PIObject!";
return false;
}
int ac = 0;
__MetaFunc func;
bool ok = findSuitableMethodV(method, vl.size_s(), ac, func);
if (!ok)
return false;
if (!ok) return false;
performer->postQueuedEvent(__QueuedEvent(func.addrV, toThis(), this, performer, vl));
performer->proc_event_queue = true;
return true;
@@ -262,8 +254,7 @@ bool PIObject::isMethodEHContains(const PIString & name) const {
PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
return true;
if (eh.value().func_name_id == search_id) return true;
}
return false;
}
@@ -274,8 +265,7 @@ PIString PIObject::methodEHArguments(const PIString & name) const {
PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
return eh.value().arguments();
if (eh.value().func_name_id == search_id) return eh.value().arguments();
}
return PIString();
}
@@ -286,8 +276,7 @@ PIString PIObject::methodEHFullFormat(const PIString & name) const {
PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
return eh.value().fullFormat();
if (eh.value().func_name_id == search_id) return eh.value().fullFormat();
}
return PIString();
}
@@ -303,8 +292,7 @@ PIVector<PIObject::__MetaFunc> PIObject::findEH(const PIString & name) const {
PIVector<__MetaFunc> ret;
const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
ret << eh.value();
if (eh.value().func_name_id == search_id) ret << eh.value();
}
return ret;
}
@@ -316,25 +304,38 @@ PIObject::__MetaFunc PIObject::methodEH(const void * addr) const {
}
PIObject::Connection PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc) {
//piCout << "piConnect ...";
//piCout << "piConnect" << src << (void*)(dest) << sig;
//piCout << "piConnect" << src->className() << "->" << ((PIObject*)dest)->className();
PIObject::Connection PIObject::piConnect(PIObject * src,
const PIString & sig,
PIObject * dest_o,
void * dest,
void * ev_h,
void * e_h,
int args,
const char * loc) {
// piCout << "piConnect ...";
// piCout << "piConnect" << src << (void*)(dest) << sig;
// piCout << "piConnect" << src->className() << "->" << ((PIObject*)dest)->className();
PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(dest_o->mutex_connect, src != dest_o);
Connection conn(ev_h, e_h, sig, src, dest_o, dest, args);
src->connections << conn;
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s() << "...";
//piCout << "addConnector" << dest_o << src;
// piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s() << "...";
// piCout << "addConnector" << dest_o << src;
dest_o->connectors << src;
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s();
//piCout << "piConnect ok";
// piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s();
// piCout << "piConnect ok";
return conn;
}
PIObject::Connection PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer) {
PIObject::Connection PIObject::piConnectU(PIObject * src,
const PIString & sig,
PIObject * dest_o,
void * dest,
const PIString & hname,
const char * loc,
PIObject * performer) {
if (src == 0 || dest_o == 0 || dest == 0) return Connection();
if (!src->isPIObject()) {
piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")";
@@ -356,29 +357,29 @@ PIObject::Connection PIObject::piConnectU(PIObject * src, const PIString & sig,
piCout << "[piConnectU] Error: can`t find handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
return Connection();
}
void * addr_src(0), * addr_dest(0);
void *addr_src(0), *addr_dest(0);
int args(0);
bool que = (performer != 0);
piForeachC (__MetaFunc & fs, m_src) {
piForeachC(__MetaFunc & fs, m_src) {
if (addr_src != 0) break;
piForeachC (__MetaFunc & fd, m_dest) {
piForeachC(__MetaFunc & fd, m_dest) {
if (addr_src != 0) break;
if (fs.canConnectTo(fd, args)) {
addr_src = fs.addr;
addr_src = fs.addr;
addr_dest = que ? fd.addrV : fd.addr;
}
}
}
if (addr_src == 0) {
piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << sig << "\" in class \"" << src->className()
<< "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
<< "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
return Connection();
}
Connection conn(addr_dest, addr_src, sig, src, dest_o, dest, args, performer);
src->connections << conn;
if (que) performer->proc_event_queue = true;
dest_o->connectors << src;
//piCout << cc << cq << _ol.size();//"connect" << src << "->" << dest_o << ", dest.connectors.size() =" << dest_o->connectors.size();
// piCout << cc << cq << _ol.size();//"connect" << src << "->" << dest_o << ", dest.connectors.size() =" << dest_o->connectors.size();
return conn;
}
@@ -395,7 +396,7 @@ PIObject::Connection PIObject::piConnectLS(PIObject * src, const PIString & sig,
}
PIMutexLocker ml(__meta_mutex());
PIMutexLocker mls(src->mutex_connect);
//piCout << "locked";
// piCout << "locked";
PIVector<__MetaFunc> m_src = src->findEH(sig);
if (m_src.isEmpty()) {
piCout << "[piConnectLS] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
@@ -403,15 +404,16 @@ PIObject::Connection PIObject::piConnectLS(PIObject * src, const PIString & sig,
return Connection();
}
if (m_src.size() != 1) {
piCout << "[piConnectLS] Error: can`t connect overloaded event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
piCout << "[piConnectLS] Error: can`t connect overloaded event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc
<< ")";
delete f;
return Connection();
}
PIObject::Connection conn(0, m_src[0].addr, sig, src);
//piCout << "found";
// piCout << "found";
conn.functor = f;
src->connections << conn;
//piCout << "finished";
// piCout << "finished";
return conn;
}
@@ -468,10 +470,10 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
void PIObject::piDisconnectAll() {
PIMutexLocker _ml(mutex_connect);
PIVector<PIObject * > cv = connectors.toVector();
// piCout << "disconnect connectors =" << connectors.size();
piForeach (PIObject * o, cv) {
// piCout << "disconnect"<< src << o;
PIVector<PIObject *> cv = connectors.toVector();
// piCout << "disconnect connectors =" << connectors.size();
piForeach(PIObject * o, cv) {
// piCout << "disconnect"<< src << o;
if (!o || (o == this)) continue;
if (!o->isPIObject()) continue;
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
@@ -480,7 +482,7 @@ void PIObject::piDisconnectAll() {
PIVector<Connection> & oc(o->connections);
for (int i = 0; i < oc.size_s(); ++i) {
if (oc[i].functor) continue;
//piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src);
// piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src);
if (oc[i].dest_o == this) {
oc[i].destroy();
oc.remove(i);
@@ -488,8 +490,8 @@ void PIObject::piDisconnectAll() {
}
}
}
// piCout << "disconnect connections =" << connections.size();
piForeachC (PIObject::Connection & c, connections) {
// piCout << "disconnect connections =" << connections.size();
piForeachC(PIObject::Connection & c, connections) {
if (c.functor) continue;
if (!c.dest_o) continue;
if (!c.dest_o->isPIObject()) continue;
@@ -502,15 +504,14 @@ void PIObject::piDisconnectAll() {
void PIObject::updateConnectors() {
//piCout << "*** updateConnectors" << this;
// piCout << "*** updateConnectors" << this;
connectors.clear();
PIMutexLocker _ml(mutexObjects());
piForeach (PIObject * o, objects()) {
piForeach(PIObject * o, objects()) {
if (o == this) continue;
PIVector<Connection> & oc(o->connections);
piForeach (Connection & c, oc)
if (c.dest == this)
connectors << o;
piForeach(Connection & c, oc)
if (c.dest == this) connectors << o;
}
}
@@ -523,8 +524,8 @@ void PIObject::postQueuedEvent(const PIObject::__QueuedEvent & e) {
void * PIObject::toThis() const {
//piCout << ptrOffset() << (void*)this << (void*)((char*)this - ptrOffset());
return (void*)((char*)this - ptrOffset());
// piCout << ptrOffset() << (void*)this << (void*)((char*)this - ptrOffset());
return (void *)((char *)this - ptrOffset());
}
@@ -545,7 +546,7 @@ void PIObject::callQueuedEvents() {
PIVector<__QueuedEvent> qe = events_queue;
events_queue.clear();
mutex_queue.unlock();
piForeachC (__QueuedEvent & e, qe) {
piForeachC(__QueuedEvent & e, qe) {
if (e.dest_o->thread_safe_) e.dest_o->mutex_.lock();
e.dest_o->emitter_ = e.src;
callAddrV(e.slot, e.dest, e.values.size_s(), e.values);
@@ -580,7 +581,7 @@ bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_
int j = m.argumentsCount();
if (mac < 0 || mac > j) mac = j;
if ((j <= args) && (ac < j)) {
ac = j;
ac = j;
mfi = i;
}
}
@@ -589,13 +590,13 @@ bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_
return false;
}
ret_args = ac;
ret = ml[mfi];
ret = ml[mfi];
return true;
}
PIVector<PIObject * > & PIObject::objects() {
static PIVector<PIObject * > * ret = new PIVector<PIObject * >();
PIVector<PIObject *> & PIObject::objects() {
static PIVector<PIObject *> * ret = new PIVector<PIObject *>();
return *ret;
}
@@ -609,11 +610,16 @@ PIMutex & PIObject::mutexObjects() {
void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector<PIVariantSimple> & vl) {
args = piMini(args, vl.size_s());
switch (args) {
case 0: ((void(*)(void *))slot)(obj); break;
case 1: ((void(*)(void * , const PIVariantSimple & ))slot)(obj, vl[0]); break;
case 2: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1]); break;
case 3: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1], vl[2]); break;
case 4: ((void(*)(void * , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & , const PIVariantSimple & ))slot)(obj, vl[0], vl[1], vl[2], vl[3]); break;
case 0: ((void (*)(void *))slot)(obj); break;
case 1: ((void (*)(void *, const PIVariantSimple &))slot)(obj, vl[0]); break;
case 2: ((void (*)(void *, const PIVariantSimple &, const PIVariantSimple &))slot)(obj, vl[0], vl[1]); break;
case 3:
((void (*)(void *, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))slot)(obj, vl[0], vl[1], vl[2]);
break;
case 4:
((void (*)(void *, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))
slot)(obj, vl[0], vl[1], vl[2], vl[3]);
break;
default: break;
}
}
@@ -625,7 +631,7 @@ PIString PIObject::simplifyType(const char * a, bool readable) {
int white = -1;
for (int i = 0; i < ret.size_s(); ++i) {
bool iw = ret[i] == ' ' || ret[i] == '\t' || ret[i] == '\r' || ret[i] == '\n';
//piCout << i << iw << white;
// piCout << i << iw << white;
if (white < 0) {
if (iw) {
white = i;
@@ -634,9 +640,9 @@ PIString PIObject::simplifyType(const char * a, bool readable) {
} else {
if (!iw) {
ret.replace(white, i - white, " ");
i = white;
i = white;
white = -1;
//piCout << i;
// piCout << i;
}
}
}
@@ -652,11 +658,9 @@ PIString PIObject::simplifyType(const char * a, bool readable) {
ret.replaceAll("> ", '>');
ret.replaceAll("& ", '&');
ret.replaceAll("* ", '*');
if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim();
if (ret.startsWith("const ") && ret.endsWith("&")) ret.cutLeft(6).cutRight(1).trim();
} else {
if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim();
if (ret.startsWith("const ") && ret.endsWith("&")) ret.cutLeft(6).cutRight(1).trim();
ret.removeAll(' ').removeAll('\t').removeAll('\r').removeAll('\n');
}
return ret;
@@ -670,49 +674,53 @@ bool PIObject::isPIObject(const PIObject * o) {
void PIObject::dump(const PIString & line_prefix) const {
//printf("dump %s \"%s\"\n", className(), name().data());
PICout(PICoutManipulators::AddNewLine) << line_prefix << "class " << className() << " (" << (const void*)this << ", \"" << name() << "\") {";
// printf("dump %s \"%s\"\n", className(), name().data());
PICout(PICoutManipulators::AddNewLine) << line_prefix << "class " << className() << " (" << (const void *)this << ", \"" << name()
<< "\") {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " scope: " << scopeList().join(" -> ");
PICout(PICoutManipulators::AddNewLine) << line_prefix << " properties {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << properties_.size_s();
//printf("dump %d properties\n", properties_.size());
// printf("dump %d properties\n", properties_.size());
const char * o_name = "name";
auto it = properties_.makeIterator();
auto it = properties_.makeIterator();
while (it.next()) {
if (it.key() != piHashData((const uchar *)o_name, strlen(o_name)))
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << it.key() << ": " << it.value();
}
//printf("dump %d properties ok\n", properties_.size());
// printf("dump %d properties ok\n", properties_.size());
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " methods {";
const __MetaData & ehd(__meta_data()[classNameID()]);
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << ehd.eh_func.size_s();
//printf("dump %d methods\n", ehd.eh_func.size());
// printf("dump %d methods\n", ehd.eh_func.size());
for (auto eh = ehd.eh_func.begin(); eh != ehd.eh_func.end(); eh++) {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << eh.value().fullFormat();
}
//printf("dump %d methods ok\n", ehd.eh_func.size());
// printf("dump %d methods ok\n", ehd.eh_func.size());
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " connections {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << connections.size_s();
//printf("dump %d connections\n",connections.size());
for (const Connection & c : connections) {
// printf("dump %d connections\n",connections.size());
for (const Connection & c: connections) {
PIObject * dst = c.dest_o;
__MetaFunc ef = methodEH(c.signal);
__MetaFunc ef = methodEH(c.signal);
PIString src(c.event);
if (ef.func_name)
src = PIStringAscii(ef.func_name) + "(" + ef.arguments() + ")";
if (ef.func_name) src = PIStringAscii(ef.func_name) + "(" + ef.arguments() + ")";
if (dst) {
__MetaFunc hf = dst->methodEH(c.slot);
PIString hf_fn;
if (!hf.func_name) hf_fn = "[BROKEN]";
else hf_fn = PIStringAscii(hf.func_name) + "(" + hf.arguments() + ")";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf_fn;
if (!hf.func_name)
hf_fn = "[BROKEN]";
else
hf_fn = PIStringAscii(hf.func_name) + "(" + hf.arguments() + ")";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest
<< ", \"" << dst->name() << "\")::" << hf_fn;
} else {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> "
<< "[lambda]";
}
}
//printf("dump %d connections ok\n",connections.size());
// printf("dump %d connections ok\n",connections.size());
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
PICout(PICoutManipulators::AddNewLine) << line_prefix << "}";
}
@@ -721,8 +729,8 @@ void PIObject::dump(const PIString & line_prefix) const {
#ifndef MICRO_PIP
void dumpApplication(bool with_objects) {
PIMutexLocker _ml(PIObject::mutexObjects());
//printf("dump application ...\n");
PIDateTime cd = PIDateTime::current();
// printf("dump application ...\n");
PIDateTime cd = PIDateTime::current();
PISystemInfo * pi = PISystemInfo::instance();
PICout(PICoutManipulators::AddNewLine) << "application {";
PICout(PICoutManipulators::AddNewLine) << " PIP version: " << PIPVersion();
@@ -734,7 +742,8 @@ void dumpApplication(bool with_objects) {
PICout(PICoutManipulators::AddNewLine) << " username: \"" << pi->user << "\"";
PICout(PICoutManipulators::AddNewLine) << " exec command: \"" << pi->execCommand << "\"";
PICout(PICoutManipulators::AddNewLine) << " started: " << pi->execDateTime.toString();
PICout(PICoutManipulators::AddNewLine) << " uptime: " << PITime::fromSystemTime(cd.toSystemTime() - pi->execDateTime.toSystemTime()).toString();
PICout(PICoutManipulators::AddNewLine) << " uptime: "
<< PITime::fromSystemTime(cd.toSystemTime() - pi->execDateTime.toSystemTime()).toString();
PICout(PICoutManipulators::AddNewLine) << " PIObjects {";
PICout(PICoutManipulators::AddNewLine) << " count: " << PIObject::objects().size_s();
if (with_objects) {
@@ -743,7 +752,7 @@ void dumpApplication(bool with_objects) {
}
PICout(PICoutManipulators::AddNewLine) << " }";
PICout(PICoutManipulators::AddNewLine) << "}";
//printf("dump application done\n");
// printf("dump application done\n");
}
@@ -774,8 +783,6 @@ void PIObject::__MetaData::addScope(const char * s, uint shash) {
}
void PIObject::Connection::destroy() {
if (functor) delete functor;
functor = nullptr;
@@ -785,9 +792,9 @@ void PIObject::Connection::destroy() {
PIObject::Connection::Connection() {
slot = signal = dest = nullptr;
src_o = dest_o = performer = nullptr;
functor = nullptr;
eventID = 0;
args_count = 0;
functor = nullptr;
eventID = 0;
args_count = 0;
}
@@ -804,11 +811,9 @@ bool PIObject::Connection::disconnect() {
Connection & cc(src_o->connections[i]);
if (cc.eventID == eventID) {
if (dest_o && (cc.dest_o == dest_o)) {
if (cc.slot == slot)
found = true;
if (cc.slot == slot) found = true;
}
if (functor && (cc.functor == functor))
found = true;
if (functor && (cc.functor == functor)) found = true;
}
if (found) {
src_o->connections[i].destroy();
@@ -818,44 +823,43 @@ bool PIObject::Connection::disconnect() {
}
}
if (dest_o) {
if (dest_o->isPIObject())
dest_o->updateConnectors();
if (dest_o->isPIObject()) dest_o->updateConnectors();
}
if (ndm) dest_o->mutex_connect.unlock();
return ret;
}
PRIVATE_DEFINITION_START(PIObject::Deleter)
PIThread thread;
PIConditionVariable cond_var;
PIVector<PIObject*> obj_queue;
PIVector<PIObject *> obj_queue;
PRIVATE_DEFINITION_END(PIObject::Deleter)
PIObject::Deleter::Deleter() {
//piCout << "Deleter start ...";
PRIVATE->thread.setSlot([this](){
PIVector<PIObject*> oq;
// piCout << "Deleter start ...";
PRIVATE->thread.setSlot([this]() {
PIVector<PIObject *> oq;
PRIVATE->thread.lock();
if (PRIVATE->obj_queue.isEmpty()) PRIVATE->cond_var.wait(PRIVATE->thread.mutex());
oq.swap(PRIVATE->obj_queue);
PRIVATE->thread.unlock();
for (PIObject * o : oq) deleteObject(o);
for (PIObject * o: oq)
deleteObject(o);
});
PRIVATE->thread.start();
}
PIObject::Deleter::~Deleter() {
//piCout << "~Deleter ...";
// piCout << "~Deleter ...";
PRIVATE->thread.stop();
PRIVATE->cond_var.notifyAll();
PRIVATE->thread.waitForFinish();
for (PIObject * o : PRIVATE->obj_queue) deleteObject(o);
//piCout << "~Deleter ok";
for (PIObject * o: PRIVATE->obj_queue)
deleteObject(o);
// piCout << "~Deleter ok";
}
@@ -867,24 +871,25 @@ PIObject::Deleter * PIObject::Deleter::instance() {
void PIObject::Deleter::post(PIObject * o) {
if (!o->isPIObject()) return;
//piCout << "[Deleter] post" << o << "...";
// piCout << "[Deleter] post" << o << "...";
PRIVATE->thread.lock();
if (!PRIVATE->obj_queue.contains(o)) {
PRIVATE->obj_queue << o;
PRIVATE->cond_var.notifyAll();
}
PRIVATE->thread.unlock();
//piCout << "[Deleter] post" << o << "done";
// piCout << "[Deleter] post" << o << "done";
}
void PIObject::Deleter::deleteObject(PIObject * o) {
//piCout << "[Deleter] delete" << (uintptr_t)o << "...";
// piCout << "[Deleter] delete" << (uintptr_t)o << "...";
if (o->isPIObject()) {
//piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic ...";
while (o->isInEvent()) piMinSleep();
//piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic done";
// piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic ...";
while (o->isInEvent())
piMinSleep();
// piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic done";
delete o;
}
//piCout << "[Deleter] delete" << (uintptr_t)o << "done";
// piCout << "[Deleter] delete" << (uintptr_t)o << "done";
}
+272 -163
View File
@@ -3,36 +3,36 @@
* \~\brief
* \~english Base object
* \~russian Базовый класс
*/
*/
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIOBJECT_H
#define PIOBJECT_H
#include "piinit.h"
#include "pimutex.h"
#include "piobject_macros.h"
#include "piqueue.h"
#include "piset.h"
#include "pivariant.h"
#include "pivariantsimple.h"
#include "pimutex.h"
#include "piset.h"
#include "piqueue.h"
#include "piobject_macros.h"
//! \ingroup Core
//! \~\brief
@@ -46,13 +46,14 @@ class PIP_EXPORT PIObject {
#endif
typedef PIObject __PIObject__;
typedef void __Parent__;
public:
NO_COPY_CLASS(PIObject);
//! \~english Contructs %PIObject with name "name"
//! \~russian Создает %PIObject с именем "name"
explicit PIObject(const PIString & name = PIString());
virtual ~PIObject();
//! \ingroup Core
@@ -61,19 +62,24 @@ public:
//! \~russian Вспомогательный класс для получения информации об успешности соединения и возможности его разрыва.
class PIP_EXPORT Connection {
friend class PIObject;
Connection(void * sl, void * si, const PIString & e = PIString(),
PIObject * s_o = nullptr, PIObject * d_o = nullptr,
void * d = nullptr, int ac = 0, PIObject * p = nullptr) {
slot = sl;
signal = si;
event = e;
eventID = e.hash();
src_o = s_o;
dest_o = d_o;
dest = d;
Connection(void * sl,
void * si,
const PIString & e = PIString(),
PIObject * s_o = nullptr,
PIObject * d_o = nullptr,
void * d = nullptr,
int ac = 0,
PIObject * p = nullptr) {
slot = sl;
signal = si;
event = e;
eventID = e.hash();
src_o = s_o;
dest_o = d_o;
dest = d;
args_count = ac;
performer = p;
functor = 0;
performer = p;
functor = 0;
}
void destroy();
void * slot;
@@ -81,31 +87,31 @@ public:
std::function<void()> * functor;
PIString event;
uint eventID;
PIObject * src_o, * dest_o;
PIObject *src_o, *dest_o;
PIObject * performer;
void * dest;
int args_count;
public:
public:
//! \~english Contructs invalid %Connection
//! \~russian Создает недействительный %Connection
Connection();
//! \~english Returns if %Connection is valid
//! \~russian Возвращает успешен ли %Connection
bool isValid() const {return signal;}
bool isValid() const { return signal; }
//! \~english Returns source object
//! \~russian Возвращает объект-источник
PIObject * sourceObject() const {return src_o;}
PIObject * sourceObject() const { return src_o; }
//! \~english Returns destination object or "nullptr" if this is lambda connection
//! \~russian Возвращает объект-приемник или "nullptr" если это соединение на лямбда-функцию
PIObject * destinationObject() const {return dest_o;}
PIObject * destinationObject() const { return dest_o; }
//! \~english Returns performer object or "nullptr" if this is non-queued connection
//! \~russian Возвращает объект-исполнитель или "nullptr" если это соединение не отложенное
PIObject * performerObject() const {return performer;}
PIObject * performerObject() const { return performer; }
//! \~english Disconnect this %Connection, returns if operation successful
//! \~russian Разрывает этот %Connection, возвращает успешен ли разрыв
@@ -116,84 +122,159 @@ private:
uint _signature_;
public:
//! \~english Returns object name
//! \~russian Возвращает имя объекта
PIString name() const {return property("name").toString();}
PIString name() const { return property("name").toString(); }
//! \~english Returns object class name
//! \~russian Возвращает имя класса объекта
virtual const char * className() const {return "PIObject";}
virtual const char * className() const { return "PIObject"; }
virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
virtual uint classNameID() const {
static uint ret = PIStringAscii("PIObject").hash();
return ret;
}
static const char * __classNameCC() {return "PIObject";}
static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
static const char * __classNameCC() { return "PIObject"; }
static uint __classNameIDS() {
static uint ret = PIStringAscii("PIObject").hash();
return ret;
}
//! \~english Returns parent class name
//! \~russian Возвращает имя родительского класса
virtual const char * parentClassName() const {return "";}
virtual const char * parentClassName() const { return ""; }
//! \~english Return if \a piCoutObj of this object is active
//! \~russian Возвращает включен ли вывод \a piCoutObj для этого объекта
bool debug() const {return property("debug").toBool();}
bool debug() const { return property("debug").toBool(); }
//! \~english Set object name
//! \~russian Устанавливает имя объекта
void setName(const PIString & name) {setProperty("name", name);}
void setName(const PIString & name) { setProperty("name", name); }
//! \~english Set object \a piCoutObj active
//! \~russian Включает или отключает вывод \a piCoutObj для этого объекта
void setDebug(bool debug) {setProperty("debug", debug);}
void setDebug(bool debug) { setProperty("debug", debug); }
//! \~english Returns property with name "name"
//! \~russian Возвращает свойство объекта по имени "name"
PIVariant property(const char * name) const {return properties_.value(piHashData((const uchar *)name, strlen(name)));}
PIVariant property(const char * name) const { return properties_.value(piHashData((const uchar *)name, strlen(name))); }
//! \~english Set property with name "name" to "value". If there is no such property in object it will be added
//! \~russian Устанавливает у объекта свойство по имени "name" в "value". Если такого свойства нет, оно добавляется
void setProperty(const char * name, const PIVariant & value) {properties_[piHashData((const uchar *)name, strlen(name))] = value; propertyChanged(name);}
void setProperty(const char * name, const PIVariant & value) {
properties_[piHashData((const uchar *)name, strlen(name))] = value;
propertyChanged(name);
}
//! \~english Returns if property with name "name" exists
//! \~russian Возвращает присутствует ли свойство по имени "name"
bool isPropertyExists(const char * name) const {return properties_.contains(piHashData((const uchar *)name, strlen(name)));}
void setThreadSafe(bool yes) {thread_safe_ = yes;}
bool isThreadSafe() const {return thread_safe_;}
bool isPropertyExists(const char * name) const { return properties_.contains(piHashData((const uchar *)name, strlen(name))); }
void setThreadSafe(bool yes) { thread_safe_ = yes; }
bool isThreadSafe() const { return thread_safe_; }
bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl);
bool execute(const PIString & method) {return execute(method, PIVector<PIVariantSimple>());}
bool execute(const PIString & method, const PIVariantSimple & v0) {return execute(method, PIVector<PIVariantSimple>() << v0);}
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return execute(method, PIVector<PIVariantSimple>() << v0 << v1);}
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
bool execute(const PIString & method) { return execute(method, PIVector<PIVariantSimple>()); }
bool execute(const PIString & method, const PIVariantSimple & v0) { return execute(method, PIVector<PIVariantSimple>() << v0); }
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return execute(method, PIVector<PIVariantSimple>() << v0 << v1);
}
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {
return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
}
bool execute(const PIString & method,
const PIVariantSimple & v0,
const PIVariantSimple & v1,
const PIVariantSimple & v2,
const PIVariantSimple & v3) {
return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
}
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl);
bool executeQueued(PIObject * performer, const PIString & method) {return executeQueued(performer, method, PIVector<PIVariantSimple>());}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0);}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1);}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
bool executeQueued(PIObject * performer, const PIString & method) {
return executeQueued(performer, method, PIVector<PIVariantSimple>());
}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0);
}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1);
}
bool executeQueued(PIObject * performer,
const PIString & method,
const PIVariantSimple & v0,
const PIVariantSimple & v1,
const PIVariantSimple & v2) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
}
bool executeQueued(PIObject * performer,
const PIString & method,
const PIVariantSimple & v0,
const PIVariantSimple & v1,
const PIVariantSimple & v2,
const PIVariantSimple & v3) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
}
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariantSimple> & vl) {return o->execute(method, vl);}
static bool execute(PIObject * o, const PIString & method) {return execute(o, method, PIVector<PIVariantSimple>());}
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) {return execute(o, method, PIVector<PIVariantSimple>() << v0);}
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1);}
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariantSimple> & vl) { return o->execute(method, vl); }
static bool execute(PIObject * o, const PIString & method) { return execute(o, method, PIVector<PIVariantSimple>()); }
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) {
return execute(o, method, PIVector<PIVariantSimple>() << v0);
}
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1);
}
static bool
execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
}
static bool execute(PIObject * o,
const PIString & method,
const PIVariantSimple & v0,
const PIVariantSimple & v1,
const PIVariantSimple & v2,
const PIVariantSimple & v3) {
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) {return o->executeQueued(performer, method, vl);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>());}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) {return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) {
return o->executeQueued(performer, method, vl);
}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>());
}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0);
}
static bool
executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1);
}
static bool executeQueued(PIObject * o,
PIObject * performer,
const PIString & method,
const PIVariantSimple & v0,
const PIVariantSimple & v1,
const PIVariantSimple & v2) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
}
static bool executeQueued(PIObject * o,
PIObject * performer,
const PIString & method,
const PIVariantSimple & v0,
const PIVariantSimple & v1,
const PIVariantSimple & v2,
const PIVariantSimple & v3) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
}
void dump(const PIString & line_prefix = PIString()) const;
//! \~english Returns subclass scope of this object (including this class name)
//! \~russian Возвращает цепочку наследования объекта (вместе с классом самого объекта)
PIStringList scopeList() const;
@@ -203,42 +284,50 @@ public:
PIString methodEHArguments(const PIString & name) const;
PIString methodEHFullFormat(const PIString & name) const;
PIString methodEHFromAddr(const void * addr) const;
// / Direct connect
static PIObject::Connection piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
static PIObject::Connection piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
static PIObject::Connection
piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
static PIObject::Connection piConnectU(PIObject * src,
const PIString & sig,
PIObject * dest_o,
void * dest,
const PIString & hname,
const char * loc,
PIObject * performer = 0);
static PIObject::Connection piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc);
template <typename PIINPUT, typename... PITYPES>
static std::function<void()> * __newFunctor(void(*stat_handler)(void*,PITYPES...), PIINPUT functor) {
return (std::function<void()>*)(new std::function<void(PITYPES...)>(functor));
template<typename PIINPUT, typename... PITYPES>
static std::function<void()> * __newFunctor(void (*stat_handler)(void *, PITYPES...), PIINPUT functor) {
return (std::function<void()> *)(new std::function<void(PITYPES...)>(functor));
}
//! \~english Disconnect object from all connections with event name "sig", connected to destination object "dest" and handler "ev_h"
//! \~russian Разрывает все соединения от события "sig" к объекту "dest" и обработчику "ev_h"
void piDisconnect(const PIString & sig, PIObject * dest, void * ev_h) {piDisconnect(this, sig, dest, ev_h);}
void piDisconnect(const PIString & sig, PIObject * dest, void * ev_h) { piDisconnect(this, sig, dest, ev_h); }
//! \~english Disconnect object from all connections with event name "sig", connected to destination object "dest"
//! \~russian Разрывает все соединения от события "sig" к объекту "dest"
void piDisconnect(const PIString & sig, PIObject * dest) {piDisconnect(this, sig, dest);}
void piDisconnect(const PIString & sig, PIObject * dest) { piDisconnect(this, sig, dest); }
//! \~english Disconnect object from all connections with event name "sig"
//! \~russian Разрывает все соединения от события "sig"
void piDisconnect(const PIString & sig) {piDisconnect(this, sig);}
void piDisconnect(const PIString & sig) { piDisconnect(this, sig); }
//! \~english Disconnect object "src" from all connections with event name "sig", connected to destination object "dest" and handler "ev_h"
//! \~english Disconnect object "src" from all connections with event name "sig", connected to destination object "dest" and handler
//! "ev_h"
//! \~russian Разрывает все соединения от события "sig" объекта "src" к объекту "dest" и обработчику "ev_h"
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h);
//! \~english Disconnect object "src" from all connections with event name "sig", connected to destination object "dest"
//! \~russian Разрывает все соединения от события "sig" объекта "src" к объекту "dest"
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest);
//! \~english Disconnect object "src" from all connections with event name "sig"
//! \~russian Разрывает все соединения от события "sig" объекта "src"
static void piDisconnect(PIObject * src, const PIString & sig);
// / Raise events
static void raiseEvent(PIObject * sender, const uint eventID) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
@@ -255,7 +344,7 @@ public:
i.dest_o->eventBegin();
sender->eventBegin();
i.dest_o->emitter_ = sender;
((void( *)(void * ))i.slot)(i.dest);
((void (*)(void *))i.slot)(i.dest);
sender->eventEnd();
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
@@ -267,14 +356,14 @@ public:
if (!sender->isPIObject()) break;
}
}
template <typename T0>
template<typename T0>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0)>*)i.functor))(v0);
(*((std::function<void(T0)> *)i.functor))(v0);
} else {
if (i.performer) {
PIVector<PIVariantSimple> vl;
@@ -286,8 +375,10 @@ public:
i.dest_o->eventBegin();
sender->eventBegin();
i.dest_o->emitter_ = sender;
if (i.args_count == 0) ((void(*)(void *))i.slot)(i.dest);
else ((void(*)(void * , T0))i.slot)(i.dest, v0);
if (i.args_count == 0)
((void (*)(void *))i.slot)(i.dest);
else
((void (*)(void *, T0))i.slot)(i.dest, v0);
sender->eventEnd();
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
@@ -299,13 +390,13 @@ public:
if (!sender->isPIObject()) break;
}
}
template <typename T0, typename T1>
template<typename T0, typename T1>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0, T1)>*)i.functor))(v0, v1);
(*((std::function<void(T0, T1)> *)i.functor))(v0, v1);
} else {
if (i.performer) {
PIVector<PIVariantSimple> vl;
@@ -319,9 +410,9 @@ public:
sender->eventBegin();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
default: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
case 0: ((void (*)(void *))i.slot)(i.dest); break;
case 1: ((void (*)(void *, T0))i.slot)(i.dest, v0); break;
default: ((void (*)(void *, T0, T1))i.slot)(i.dest, v0, v1); break;
}
sender->eventEnd();
if (i.dest_o->isPIObject()) {
@@ -334,13 +425,13 @@ public:
if (!sender->isPIObject()) break;
}
}
template <typename T0, typename T1, typename T2>
template<typename T0, typename T1, typename T2>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0, T1, T2)>*)i.functor))(v0, v1, v2);
(*((std::function<void(T0, T1, T2)> *)i.functor))(v0, v1, v2);
} else {
if (i.performer) {
PIVector<PIVariantSimple> vl;
@@ -355,10 +446,10 @@ public:
sender->eventBegin();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
default: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
case 0: ((void (*)(void *))i.slot)(i.dest); break;
case 1: ((void (*)(void *, T0))i.slot)(i.dest, v0); break;
case 2: ((void (*)(void *, T0, T1))i.slot)(i.dest, v0, v1); break;
default: ((void (*)(void *, T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
}
sender->eventEnd();
if (i.dest_o->isPIObject()) {
@@ -371,13 +462,18 @@ public:
if (!sender->isPIObject()) break;
}
}
template <typename T0, typename T1, typename T2, typename T3>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) {
template<typename T0, typename T1, typename T2, typename T3>
static void raiseEvent(PIObject * sender,
const uint eventID,
const T0 & v0 = T0(),
const T1 & v1 = T1(),
const T2 & v2 = T2(),
const T3 & v3 = T3()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0, T1, T2, T3)>*)i.functor))(v0, v1, v2, v3);
(*((std::function<void(T0, T1, T2, T3)> *)i.functor))(v0, v1, v2, v3);
} else {
if (i.performer) {
PIVector<PIVariantSimple> vl;
@@ -393,11 +489,11 @@ public:
sender->eventBegin();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
case 3: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
default: ((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); break;
case 0: ((void (*)(void *))i.slot)(i.dest); break;
case 1: ((void (*)(void *, T0))i.slot)(i.dest, v0); break;
case 2: ((void (*)(void *, T0, T1))i.slot)(i.dest, v0, v1); break;
case 3: ((void (*)(void *, T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
default: ((void (*)(void *, T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); break;
}
sender->eventEnd();
if (i.dest_o->isPIObject()) {
@@ -410,20 +506,20 @@ public:
if (!sender->isPIObject()) break;
}
}
//! Returns PIObject* with name "name" or 0, if there is no object found
static PIObject * findByName(const PIString & name) {
PIMutexLocker _ml(mutexObjects());
piForeach (PIObject * i, PIObject::objects()) {
piForeach(PIObject * i, PIObject::objects()) {
if (i->name() != name) continue;
return i;
}
return nullptr;
}
//! \~english Returns if this is valid %PIObject (check signature)
//! \~russian Возвращает действительный ли это %PIObject (проверяет подпись)
bool isPIObject() const {return isPIObject(this);}
bool isPIObject() const { return isPIObject(this); }
//! \~english Returns if this is valid %PIObject subclass "T" (check signature and classname)
//! \~russian Возвращает действительный ли это наследник %PIObject типа "T" (проверяет подпись и имя класса)
@@ -435,55 +531,63 @@ public:
}
//! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr"
//! \~russian Возвращает преобразование к типу T если это действительный наследник типа "T" (проверяет через \a isTypeOf()), или "nullptr"
//! \~russian Возвращает преобразование к типу T если это действительный наследник типа "T" (проверяет через \a isTypeOf()), или
//! "nullptr"
template<typename T>
T * cast() const {
if (!isTypeOf<T>()) return (T*)nullptr;
return (T*)this;
if (!isTypeOf<T>()) return (T *)nullptr;
return (T *)this;
}
//! \~english Returns if "o" is valid %PIObject (check signature)
//! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись)
static bool isPIObject(const PIObject * o);
static bool isPIObject(const void * o) {return isPIObject((PIObject*)o);}
static bool isPIObject(const void * o) { return isPIObject((PIObject *)o); }
//! \~english Returns if "o" is valid %PIObject subclass "T" (check signature and classname)
//! \~russian Возвращает действительный ли "o" наследник %PIObject типа "T" (проверяет подпись и имя класса)
template<typename T>
static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();}
static bool isTypeOf(const PIObject * o) {
return o->isTypeOf<T>();
}
template<typename T>
static bool isTypeOf(const void * o) {return isTypeOf<T>((PIObject*)o);}
static bool isTypeOf(const void * o) {
return isTypeOf<T>((PIObject *)o);
}
static PIString simplifyType(const char * a, bool readable = true);
struct PIP_EXPORT __MetaFunc {
__MetaFunc();
bool isNull() const {return addr == nullptr;}
bool isNull() const { return addr == nullptr; }
int argumentsCount() const;
PIString arguments() const;
PIString fullFormat() const;
void __setFuncName(const char * n);
void __addArgument(const char * t, const char * n);
bool canConnectTo(const __MetaFunc & dst, int & args_count) const;
void * addr = nullptr;
void * addrV = nullptr;
uint func_name_id = 0;
void * addr = nullptr;
void * addrV = nullptr;
uint func_name_id = 0;
const char * func_name = nullptr;
const char * type_ret = nullptr;
const char * scope = nullptr;
const char * type_ret = nullptr;
const char * scope = nullptr;
const char * types[__PIOBJECT_MAX_ARGS__];
const char * names[__PIOBJECT_MAX_ARGS__];
uint types_id[__PIOBJECT_MAX_ARGS__];
};
struct PIP_EXPORT __MetaData {
__MetaData() {scope_list << "PIObject"; scope_id << PIStringAscii("PIObject").hash();}
__MetaData() {
scope_list << "PIObject";
scope_id << PIStringAscii("PIObject").hash();
}
void addScope(const char * s, uint shash);
PIVector<const char *> scope_list;
PISet<uint> scope_id;
PISet<const void * > eh_set;
PIMap<const void * , __MetaFunc> eh_func;
PISet<const void *> eh_set;
PIMap<const void *, __MetaFunc> eh_func;
};
typedef PIPair<const void * , __MetaFunc> __EHPair;
typedef PIPair<const void *, __MetaFunc> __EHPair;
//! \~english Execute all posted events from CONNECTU_QUEUED connections
//! \~russian Выполнить все отложенные события от CONNECTU_QUEUED соединений
@@ -497,7 +601,10 @@ public:
//! \brief Если было хотя бы одно CONNECTU_QUEUED соединение с исполнителем this, то выполнить события
//! \details Этот метод более оптимален, чем \a callQueuedEvents(), для объектов, которые не были в роли
//! \"performer\" в макросе CONNECTU_QUEUED
bool maybeCallQueuedEvents() {if (proc_event_queue) callQueuedEvents(); return proc_event_queue;}
bool maybeCallQueuedEvents() {
if (proc_event_queue) callQueuedEvents();
return proc_event_queue;
}
//! \~english Mark object to delete
//! \~russian Пометить объект на удаление
@@ -507,19 +614,18 @@ public:
static PIMap<uint, __MetaData> & __meta_data(); // [hash(classname)]=__MetaData
protected:
//! \~english Returns %PIObject* which has raised an event. This value is correct only in definition of some event handler
//! \~russian Возвращает %PIObject* который вызвал это событие. Значение допустимо только из методов обработчиков событий
PIObject * emitter() const {return emitter_;}
PIObject * emitter() const { return emitter_; }
//! \~english Virtual function executes after property with name "name" has been changed
//! \~russian Виртуальная функция, вызывается после изменения любого свойства.
virtual void propertyChanged(const char * name) {}
EVENT1(deleted, PIObject *, o);
//! \events
//! \{
//! \events
//! \{
//! \fn void deleted(PIObject * o)
//! \brief
@@ -533,16 +639,19 @@ protected:
//! Это событие вызывается из деструктора, поэтому используйте
//! только численное значение "o", не надо кастовать его в другие типы!
//! \}
//! \}
private:
struct __QueuedEvent {
__QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariantSimple> & v = PIVector<PIVariantSimple>()) {
slot = sl;
dest = d;
__QueuedEvent(void * sl = 0,
void * d = 0,
PIObject * d_o = 0,
PIObject * s = 0,
const PIVector<PIVariantSimple> & v = PIVector<PIVariantSimple>()) {
slot = sl;
dest = d;
dest_o = d_o;
src = s;
src = s;
values = v;
}
void * slot;
@@ -558,6 +667,7 @@ private:
~Deleter();
static Deleter * instance();
void post(PIObject * o);
private:
void deleteObject(PIObject * o);
PRIVATE_DECLARATION(PIP_EXPORT)
@@ -570,26 +680,25 @@ private:
void piDisconnectAll();
void postQueuedEvent(const __QueuedEvent & e);
void eventBegin() {in_event_cnt++;}
void eventEnd () {in_event_cnt--;}
bool isInEvent() const {return in_event_cnt > 0;}
void eventBegin() { in_event_cnt++; }
void eventEnd() { in_event_cnt--; }
bool isInEvent() const { return in_event_cnt > 0; }
void * toThis() const;
virtual int ptrOffset() const {return 0;}
static PIVector<PIObject * > & objects();
virtual int ptrOffset() const { return 0; }
static PIVector<PIObject *> & objects();
static PIMutex & mutexObjects();
static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariantSimple> & vl);
PIVector<Connection> connections;
PIMap<uint, PIVariant> properties_;
PISet<PIObject * > connectors;
PISet<PIObject *> connectors;
PIVector<__QueuedEvent> events_queue;
PIMutex mutex_, mutex_connect, mutex_queue;
PIObject * emitter_;
bool thread_safe_, proc_event_queue;
std::atomic_int in_event_cnt;
};
#ifndef MICRO_PIP
+515 -342
View File
@@ -3,24 +3,24 @@
* \~\brief
* \~english PIObject macros
* \~russian Макросы PIObject
*/
*/
/*
PIP - Platform Independent Primitives
Macros for PIObject
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Macros for PIObject
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIOBJECT_MACROS_H
@@ -33,133 +33,141 @@
//! \relatesalso PIObject
//! \~\brief
//! \~english You should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output
//! \~russian Необходимо использовать этот макрос после объявления класса для использования событийной системы и корректного вывода piCoutObj
#define PIOBJECT(name)
//! \~russian Необходимо использовать этот макрос после объявления класса для использования событийной системы и корректного вывода
//! piCoutObj
# define PIOBJECT(name)
//! \relatesalso PIObject
//! \~\brief
//! \~english You should use this macro after class declaration to use EVENT and EVENT_HANDLER of parent class, and \a scopeList()
//! \~russian
#define PIOBJECT_SUBCLASS(name, parent)
# define PIOBJECT_SUBCLASS(name, parent)
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name()
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name()
#define EVENT_HANDLER0(ret, name) ret name()
# define EVENT_HANDLER0(ret, name) ret name()
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0)
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0)
#define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0)
# define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0)
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1)
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1)
#define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1)
# define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1)
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2)
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)
# define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3)
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1, type2 var2,
//! type3 var3)
# define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \
ret name(type0 var0, type1 var1, type2 var2, type3 var3)
//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of EVENT_HANDLER0
//! \~russian Аналог EVENT_HANDLER0
#define EVENT_HANDLER EVENT_HANDLER0
# define EVENT_HANDLER EVENT_HANDLER0
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name()
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name()
#define EVENT_VHANDLER0(ret, name) virtual ret name()
# define EVENT_VHANDLER0(ret, name) virtual ret name()
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0)
#define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0)
# define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0)
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1 var1)
#define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1
//! var1)
# define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1)
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1
//! var1, type2 var2)
# define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2,
//! type3 var3)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1
//! var1, type2 var2, type3 var3)
# define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \
virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of EVENT_VHANDLER0
//! \~russian Аналог EVENT_VHANDLER0
#define EVENT_VHANDLER EVENT_VHANDLER0
# define EVENT_VHANDLER EVENT_VHANDLER0
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event with name \"name\", void name();
//! \~russian Объявляет событие с именем \"name\", void name();
#define EVENT0(name) void name();
# define EVENT0(name) void name();
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event with name \"name\", void name(type0 var0);
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0);
#define EVENT1(name, type0, var0) void name(type0 var0);
# define EVENT1(name, type0, var0) void name(type0 var0);
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event with name \"name\", void name(type0 var0, type1 var1);
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1);
#define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1);
# define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1);
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event with name \"name\", void name(type0 var0, type1 var1, type2 var2);
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1, type2 var2);
#define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2);
# define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2);
//! \relatesalso PIObject
//! \~\brief
//! \~english Declare event with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
#define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);
# define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);
//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of EVENT0
//! \~russian Аналог EVENT0
#define EVENT EVENT0
# define EVENT EVENT0
#define RAISE_EVENT0(src, event)
#define RAISE_EVENT1(src, event, v0)
#define RAISE_EVENT2(src, event, v0, v1)
#define RAISE_EVENT3(src, event, v0, v1, v2)
#define RAISE_EVENT4(src, event, v0, v1, v2, v3)
#define RAISE_EVENT RAISE_EVENT0
# define RAISE_EVENT0(src, event)
# define RAISE_EVENT1(src, event, v0)
# define RAISE_EVENT2(src, event, v0, v1)
# define RAISE_EVENT3(src, event, v0, v1, v2)
# define RAISE_EVENT4(src, event, v0, v1, v2, v3)
# define RAISE_EVENT RAISE_EVENT0
//! \relatesalso PIObject
@@ -173,7 +181,7 @@
//! \~russian
//! \"handler\" может принимать не все аргументы от \"event\".
//! Возвращает \a PIObject::Connection
#define CONNECTU(src, event, dest, handler)
# define CONNECTU(src, event, dest, handler)
//! \relatesalso PIObject
//! \~\brief
@@ -192,7 +200,7 @@
//! Все типы аргументов должны быть зарегистрированы с помощью макроса \a REGISTER_VARIANT(),
//! однако многие стандартные и PIP типы уже там.
//! Возвращает \a PIObject::Connection
#define CONNECTU_QUEUED(src, event, dest, handler, performer)
# define CONNECTU_QUEUED(src, event, dest, handler, performer)
//! \relatesalso PIObject
//! \~\brief
@@ -207,62 +215,72 @@
//! \"event\" и \"functor\" должны иметь одинаковые аргументы.
//! В случае сложной лямбда-функции оберните её ().
//! Возвращает \a PIObject::Connection
#define CONNECTL(src, event, functor)
# define CONNECTL(src, event, functor)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
#define CONNECT0(ret, src, event, dest, handler)
# define CONNECT0(ret, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
#define CONNECT1(ret, type0, src, event, dest, handler)
# define CONNECT1(ret, type0, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
#define CONNECT2(ret, type0, type1, src, event, dest, handler)
# define CONNECT2(ret, type0, type1, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
# define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists.
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! check of event and handler exists.
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
# define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
@@ -271,7 +289,7 @@
//! \~\brief
//! \~english Synonym of \a CONNECT0
//! \~russian Аналог \a CONNECT0
#define CONNECT CONNECT0
# define CONNECT CONNECT0
//! \relatesalso PIObject
@@ -279,45 +297,55 @@
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
#define WEAK_CONNECT0(ret, src, event, dest, handler)
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT0(ret, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
#define WEAK_CONNECT1(ret, type0, src, event, dest, handler)
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT1(ret, type0, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
#define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
#define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
//! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU()
//! \~\brief
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
#define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \relatesalso PIObject
//! \deprecated
@@ -326,367 +354,512 @@
//! \~\brief
//! \~english Synonym of \a WEAK_CONNECT0
//! \~russian Аналог \a WEAK_CONNECT0
#define WEAK_CONNECT WEAK_CONNECT0
# define WEAK_CONNECT WEAK_CONNECT0
//! \relatesalso PIObject
//! \~\brief
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
#define DISCONNECT0(ret, src, event, dest, handler)
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT0(ret, src, event, dest, handler)
//! \relatesalso PIObject
//! \~\brief
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
#define DISCONNECT1(ret, type0, src, event, dest, handler)
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT1(ret, type0, src, event, dest, handler)
//! \relatesalso PIObject
//! \~\brief
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
#define DISCONNECT2(ret, type0, type1, src, event, dest, handler)
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT2(ret, type0, type1, src, event, dest, handler)
//! \relatesalso PIObject
//! \~\brief
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
#define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \relatesalso PIObject
//! \~\brief
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
#define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \relatesalso PIObject
//! \~\brief
//! \~english Synonym of \a DISCONNECT0
//! \~russian Аналог \a DISCONNECT0
#define DISCONNECT DISCONNECT0
# define DISCONNECT DISCONNECT0
//! \relatesalso PIObject
//! \~\brief
//! \~english Returns pointer to events handler \"handler\"
//! \~russian Возвращает указатель на обработчик события \"handler\"
#define HANDLER(handler)
# define HANDLER(handler)
#else
#define _PI_STR(x) #x
#define _PI_SSTR(x) _PI_STR(x)
#define LOCATION __FILE__ ":" _PI_SSTR(__LINE__)
#ifdef CC_GCC
# define __PTYPE(t) typename __PIVariantTypeInfo__<t>::PureType
#else
# define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType
#endif
#define __VVALUE(t, v) v.value< __PTYPE(t) >()
#define __PIOBJECT_MAX_ARGS__ 4
# define _PI_STR(x) #x
# define _PI_SSTR(x) _PI_STR(x)
# define LOCATION __FILE__ ":" _PI_SSTR(__LINE__)
# ifdef CC_GCC
# define __PTYPE(t) typename __PIVariantTypeInfo__<t>::PureType
# else
# define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType
# endif
# define __VVALUE(t, v) v.value<__PTYPE(t)>()
# define __PIOBJECT_MAX_ARGS__ 4
#define PIOBJECT(name) \
protected: \
typedef name __PIObject__; \
public: \
static const char * __classNameCC() {return #name;} \
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
const char * className() const override {return #name;} \
uint classNameID() const override {static uint ret = PIStringAscii(#name).hash(); return ret;} \
private: \
int ptrOffset() const override {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \
class __BaseInitializer__ { \
public: \
__BaseInitializer__() { \
uint pid = PIObject::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
if (__meta_data().contains(id)) return; \
__meta_data()[pid]; \
__meta_data()[id]; \
__MetaData & ehp(__meta_data()[pid]); \
__MetaData & eh(__meta_data()[id]); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.addScope(__classNameCC(), id); \
} \
}; \
__BaseInitializer__ __base_init__;
# define PIOBJECT(name) \
\
protected: \
typedef name __PIObject__; \
\
public: \
static const char * __classNameCC() { \
return #name; \
} \
static uint __classNameIDS() { \
static uint ret = PIStringAscii(#name).hash(); \
return ret; \
} \
const char * className() const override { \
return #name; \
} \
uint classNameID() const override { \
static uint ret = PIStringAscii(#name).hash(); \
return ret; \
} \
\
private: \
int ptrOffset() const override { \
name * o = (name *)100; \
return int(llong((PIObject *)o) - llong(o)); \
} \
class __BaseInitializer__ { \
public: \
__BaseInitializer__() { \
uint pid = PIObject::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
if (__meta_data().contains(id)) return; \
__meta_data()[pid]; \
__meta_data()[id]; \
__MetaData & ehp(__meta_data()[pid]); \
__MetaData & eh(__meta_data()[id]); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.addScope(__classNameCC(), id); \
} \
}; \
__BaseInitializer__ __base_init__;
#define PIOBJECT_PARENT(name) \
class __ParentInitializer__ { \
public: \
__ParentInitializer__() { \
uint pid = name::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[id]); \
if (eh.scope_id.contains(pid)) return; \
__MetaData ehp(__meta_data().value(pid)); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.scope_id = ehp.scope_id; \
eh.scope_list = ehp.scope_list; \
eh.addScope(__classNameCC(), id); \
} \
}; \
__ParentInitializer__ __parent_init__; \
public: \
const char * parentClassName() const override {return #name;} \
typedef name __Parent__; \
private:
# define PIOBJECT_PARENT(name) \
class __ParentInitializer__ { \
public: \
__ParentInitializer__() { \
uint pid = name::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[id]); \
if (eh.scope_id.contains(pid)) return; \
__MetaData ehp(__meta_data().value(pid)); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.scope_id = ehp.scope_id; \
eh.scope_list = ehp.scope_list; \
eh.addScope(__classNameCC(), id); \
} \
}; \
__ParentInitializer__ __parent_init__; \
\
public: \
const char * parentClassName() const override { \
return #name; \
} \
typedef name __Parent__; \
\
private:
#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)
# define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)
#define __EH_INIT_BASE__(ret, name) \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameCC(); \
f.__setFuncName(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = #ret;
# define __EH_INIT_BASE__(ret, name) \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameCC(); \
f.__setFuncName(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = #ret;
#define EH_INIT0(ret, name) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
void * fpV = fp; \
__EH_INIT_BASE__(ret, name) \
STATIC_INITIALIZER_END
# define EH_INIT0(ret, name) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void *)(ret(*)(void *))__stat_eh_##name##__; \
void * fpV = fp; \
__EH_INIT_BASE__(ret, name) \
STATIC_INITIALIZER_END
#define EH_INIT1(ret, name, a0, n0) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
STATIC_INITIALIZER_END
# define EH_INIT1(ret, name, a0, n0) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void *)(ret(*)(void *, a0))__stat_eh_##name##__; \
void * fpV = (void *)(ret(*)(void *, const PIVariantSimple &))__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
STATIC_INITIALIZER_END
#define EH_INIT2(ret, name, a0, n0, a1, n1) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
f.__addArgument(#a1, #n1); \
STATIC_INITIALIZER_END
# define EH_INIT2(ret, name, a0, n0, a1, n1) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void *)(ret(*)(void *, a0, a1))__stat_eh_##name##__; \
void * fpV = (void *)(ret(*)(void *, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
f.__addArgument(#a1, #n1); \
STATIC_INITIALIZER_END
#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
f.__addArgument(#a1, #n1); \
f.__addArgument(#a2, #n2); \
STATIC_INITIALIZER_END
# define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void *)(ret(*)(void *, a0, a1, a2))__stat_eh_##name##__; \
void * fpV = \
(void *)(ret(*)(void *, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
f.__addArgument(#a1, #n1); \
f.__addArgument(#a2, #n2); \
STATIC_INITIALIZER_END
#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
f.__addArgument(#a1, #n1); \
f.__addArgument(#a2, #n2); \
f.__addArgument(#a3, #n3); \
STATIC_INITIALIZER_END
# define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void *)(ret(*)(void *, a0, a1, a2, a3))__stat_eh_##name##__; \
void * fpV = \
(void *)(ret(*)(void *, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &)) \
__stat_eh_v_##name##__; \
__EH_INIT_BASE__(ret, name) \
f.__addArgument(#a0, #n0); \
f.__addArgument(#a1, #n1); \
f.__addArgument(#a2, #n2); \
f.__addArgument(#a3, #n3); \
STATIC_INITIALIZER_END
#define EVENT_HANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \
ret name()
# define EVENT_HANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) { \
return ((__PIObject__ *)__o__)->name(); \
} \
ret name()
#define EVENT_HANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
return ((__PIObject__*)__o__)->name(tv0);} \
ret name(a0 n0)
# define EVENT_HANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) { \
return ((__PIObject__ *)__o__)->name(n0); \
} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
return ((__PIObject__ *)__o__)->name(tv0); \
} \
ret name(a0 n0)
#define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
return ((__PIObject__*)__o__)->name(tv0, tv1);} \
ret name(a0 n0, a1 n1)
# define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) { \
return ((__PIObject__ *)__o__)->name(n0, n1); \
} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
return ((__PIObject__ *)__o__)->name(tv0, tv1); \
} \
ret name(a0 n0, a1 n1)
#define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
return ((__PIObject__*)__o__)->name(tv0, tv1, tv2);} \
ret name(a0 n0, a1 n1, a2 n2)
# define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) { \
return ((__PIObject__ *)__o__)->name(n0, n1, n2); \
} \
static ret __stat_eh_v_##name##__(void * __o__, \
const PIVariantSimple & v0, \
const PIVariantSimple & v1, \
const PIVariantSimple & v2) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
return ((__PIObject__ *)__o__)->name(tv0, tv1, tv2); \
} \
ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
__PTYPE(a3) tv3 = __VVALUE(a3, v3); \
return ((__PIObject__*)__o__)->name(tv0, tv1, tv2, tv3);} \
ret name(a0 n0, a1 n1, a2 n2, a3 n3)
# define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) { \
return ((__PIObject__ *)__o__)->name(n0, n1, n2, n3); \
} \
static ret __stat_eh_v_##name##__(void * __o__, \
const PIVariantSimple & v0, \
const PIVariantSimple & v1, \
const PIVariantSimple & v2, \
const PIVariantSimple & v3) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
__PTYPE(a3) tv3 = __VVALUE(a3, v3); \
return ((__PIObject__ *)__o__)->name(tv0, tv1, tv2, tv3); \
} \
ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_HANDLER EVENT_HANDLER0
# define EVENT_HANDLER EVENT_HANDLER0
#define EVENT_VHANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) { \
return ((__PIObject__*)__o__)->name();} \
virtual ret name()
# define EVENT_VHANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) { \
return ((__PIObject__ *)__o__)->name(); \
} \
virtual ret name()
#define EVENT_VHANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) { \
return ((__PIObject__*)__o__)->name(n0);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0));} \
virtual ret name(a0 n0)
# define EVENT_VHANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) { \
return ((__PIObject__ *)__o__)->name(n0); \
} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0) { \
return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0)); \
} \
virtual ret name(a0 n0)
#define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) { \
return ((__PIObject__*)__o__)->name(n0, n1);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));} \
virtual ret name(a0 n0, a1 n1)
# define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) { \
return ((__PIObject__ *)__o__)->name(n0, n1); \
} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1) { \
return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1)); \
} \
virtual ret name(a0 n0, a1 n1)
#define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) { \
return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { \
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2));} \
virtual ret name(a0 n0, a1 n1, a2 n2)
# define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) { \
return ((__PIObject__ *)__o__)->name(n0, n1, n2); \
} \
static ret __stat_eh_v_##name##__(void * __o__, \
const PIVariantSimple & v0, \
const PIVariantSimple & v1, \
const PIVariantSimple & v2) { \
return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2)); \
} \
virtual ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) { \
return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2, const PIVariantSimple & v3) { \
return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3));} \
virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
# define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) { \
return ((__PIObject__ *)__o__)->name(n0, n1, n2, n3); \
} \
static ret __stat_eh_v_##name##__(void * __o__, \
const PIVariantSimple & v0, \
const PIVariantSimple & v1, \
const PIVariantSimple & v2, \
const PIVariantSimple & v3) { \
return ((__PIObject__ *)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3)); \
} \
virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_VHANDLER EVENT_VHANDLER0
# define EVENT_VHANDLER EVENT_VHANDLER0
#define EVENT0(name) EVENT_HANDLER0(void, name) { \
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid);}
# define EVENT0(name) \
EVENT_HANDLER0(void, name) { \
static uint eid = PIStringAscii(#name).hash(); \
PIObject::raiseEvent(this, eid); \
}
#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) { \
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0);}
# define EVENT1(name, a0, n0) \
EVENT_HANDLER1(void, name, a0, n0) { \
static uint eid = PIStringAscii(#name).hash(); \
PIObject::raiseEvent(this, eid, n0); \
}
#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) { \
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1);}
# define EVENT2(name, a0, n0, a1, n1) \
EVENT_HANDLER2(void, name, a0, n0, a1, n1) { \
static uint eid = PIStringAscii(#name).hash(); \
PIObject::raiseEvent(this, eid, n0, n1); \
}
#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) { \
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2);}
# define EVENT3(name, a0, n0, a1, n1, a2, n2) \
EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) { \
static uint eid = PIStringAscii(#name).hash(); \
PIObject::raiseEvent(this, eid, n0, n1, n2); \
}
#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) { \
static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2, n3);}
# define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) \
EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) { \
static uint eid = PIStringAscii(#name).hash(); \
PIObject::raiseEvent(this, eid, n0, n1, n2, n3); \
}
#define EVENT EVENT0
# define EVENT EVENT0
#define RAISE_EVENT0(src, event) (src)->event();
#define RAISE_EVENT1(src, event, v0) (src)->event(v0);
#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1);
#define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2);
#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
#define RAISE_EVENT RAISE_EVENT0
# define RAISE_EVENT0(src, event) (src)->event();
# define RAISE_EVENT1(src, event, v0) (src)->event(v0);
# define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1);
# define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2);
# define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
# define RAISE_EVENT RAISE_EVENT0
#define CONNECTU(src, event, dest, handler) \
PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION);
# define CONNECTU(src, event, dest, handler) \
PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION);
#define CONNECTU_QUEUED(src, event, dest, handler, performer) \
PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer);
# define CONNECTU_QUEUED(src, event, dest, handler, performer) \
PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer);
#define CONNECTL(src, event, functor) \
PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION);
# define CONNECTL(src, event, functor) \
PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION);
#define CONNECT0(ret, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), \
(void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION);
# define CONNECT0(ret, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *))(&(dest)->__stat_eh_##handler##__), \
(void *)(void (*)(void *))(&(src)->__stat_eh_##event##__), \
0, \
LOCATION);
#define CONNECT1(ret, a0, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), \
(void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION);
# define CONNECT1(ret, a0, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0))(&(dest)->__stat_eh_##handler##__), \
(void *)(void (*)(void *, a0))(&(src)->__stat_eh_##event##__), \
1, \
LOCATION);
#define CONNECT2(ret, a0, a1, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), \
(void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2, LOCATION);
# define CONNECT2(ret, a0, a1, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0, a1))(&(dest)->__stat_eh_##handler##__), \
(void *)(void (*)(void *, a0, a1))(&(src)->__stat_eh_##event##__), \
2, \
LOCATION);
#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), \
(void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3, LOCATION);
# define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), \
(void *)(void (*)(void *, a0, a1, a2))(&(src)->__stat_eh_##event##__), \
3, \
LOCATION);
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), \
(void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4, LOCATION);
# define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), \
(void *)(void (*)(void *, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), \
4, \
LOCATION);
#define CONNECT CONNECT0
# define CONNECT CONNECT0
#define WEAK_CONNECT0(ret, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0, LOCATION);
# define WEAK_CONNECT0(ret, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *))(&(dest)->__stat_eh_##handler##__), \
0, \
0, \
LOCATION);
#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1, LOCATION);
# define WEAK_CONNECT1(ret, a0, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0))(&(dest)->__stat_eh_##handler##__), \
0, \
1, \
LOCATION);
#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2, LOCATION);
# define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0, a1))(&(dest)->__stat_eh_##handler##__), \
0, \
2, \
LOCATION);
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3, LOCATION);
# define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), \
0, \
3, \
LOCATION);
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4, LOCATION);
# define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
PIObject::piConnect(src, \
PIStringAscii(#event), \
dest, \
dest, \
(void *)(ret(*)(void *, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), \
0, \
4, \
LOCATION);
#define WEAK_CONNECT WEAK_CONNECT0
# define WEAK_CONNECT WEAK_CONNECT0
#define DISCONNECT0(ret, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
# define DISCONNECT0(ret, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT1(ret, a0, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
# define DISCONNECT1(ret, a0, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
# define DISCONNECT2(ret, a0, a1, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0, a1))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
# define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
# define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) \
PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void *)(ret(*)(void *, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT DISCONNECT0
# define DISCONNECT DISCONNECT0
#define HANDLER(handler) __stat_eh_##handler##__
# define HANDLER(handler) __stat_eh_##handler##__
#define __PIOBJECT_SIGNATURE__ 0xabcdbadc
# define __PIOBJECT_SIGNATURE__ 0xabcdbadc
#endif
+31 -27
View File
@@ -1,33 +1,33 @@
/*
PIP - Platform Independent Primitives
Private PIP wait object
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Private PIP wait object
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piwaitevent_p.h"
#ifdef WINDOWS
//# ifdef _WIN32_WINNT
//# undef _WIN32_WINNT
//# define _WIN32_WINNT 0x0600
//# endif
// # ifdef _WIN32_WINNT
// # undef _WIN32_WINNT
// # define _WIN32_WINNT 0x0600
// # endif
# include <synchapi.h>
#else
# include <errno.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <errno.h>
#endif
#include "pistring.h"
@@ -45,7 +45,8 @@ void PIWaitEvent::create() {
piCout << "Error with CreateEventA:" << errorString();
}
#else
for (int i = 0; i < 3; ++i) memset(&(fds[i]), 0, sizeof(fds[i]));
for (int i = 0; i < 3; ++i)
memset(&(fds[i]), 0, sizeof(fds[i]));
if (::pipe(pipe_fd) < 0) {
piCout << "Error with pipe:" << errorString();
} else {
@@ -80,16 +81,18 @@ bool PIWaitEvent::wait(int fd, CheckRole role) {
if (ret == WAIT_IO_COMPLETION || ret == WAIT_FAILED) return false;
#else
if (fd == -1) return false;
int nfds = piMaxi(pipe_fd[ReadEnd], fd) + 1;
int nfds = piMaxi(pipe_fd[ReadEnd], fd) + 1;
int fd_index = role;
for (int i = 0; i < 3; ++i) FD_ZERO(&(fds[i]));
for (int i = 0; i < 3; ++i)
FD_ZERO(&(fds[i]));
FD_SET(pipe_fd[ReadEnd], &(fds[CheckRead]));
FD_SET(fd, &(fds[CheckExeption]));
if (fd_index != CheckExeption) FD_SET(fd, &(fds[fd_index]));
int sr = ::select(nfds, &(fds[CheckRead]), &(fds[CheckWrite]), &(fds[CheckExeption]), nullptr);
int sr = ::select(nfds, &(fds[CheckRead]), &(fds[CheckWrite]), &(fds[CheckExeption]), nullptr);
int buf = 0;
while (::read(pipe_fd[ReadEnd], &buf, sizeof(buf)) > 0);
//piCout << "wait result" << sr << FD_ISSET(fd, &(fds[CheckExeption])) << FD_ISSET(fd, &(fds[fd_index]));
while (::read(pipe_fd[ReadEnd], &buf, sizeof(buf)) > 0)
;
// piCout << "wait result" << sr << FD_ISSET(fd, &(fds[CheckExeption])) << FD_ISSET(fd, &(fds[fd_index]));
if (sr == EBADF || sr == EINTR) return false;
if (FD_ISSET(fd, &(fds[CheckExeption]))) return true;
return FD_ISSET(fd, &(fds[fd_index]));
@@ -111,9 +114,10 @@ bool PIWaitEvent::sleep(int us) {
timeval timeout;
timeout.tv_sec = us / 1000000;
timeout.tv_usec = us % 1000000;
int ret = ::select(nfds, &(fds[CheckRead]), nullptr, nullptr, &timeout);
int buf = 0;
while (::read(pipe_fd[ReadEnd], &buf, sizeof(buf)) > 0);
int ret = ::select(nfds, &(fds[CheckRead]), nullptr, nullptr, &timeout);
int buf = 0;
while (::read(pipe_fd[ReadEnd], &buf, sizeof(buf)) > 0)
;
return ret == 0;
#endif
}
+16 -15
View File
@@ -1,34 +1,36 @@
/*
PIP - Platform Independent Primitives
Private PIP wait object
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Private PIP wait object
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIWAITEVENT_P_H
#define PIWAITEVENT_P_H
#include "pibase.h"
// clang-format off
#ifdef WINDOWS
# include <stdarg.h>
# include <windef.h>
# include <winbase.h>
#else
# include <unistd.h>
# include <sys/select.h>
# include <unistd.h>
#endif
// clang-format on
class PIP_EXPORT PIWaitEvent {
@@ -60,7 +62,6 @@ private:
WriteEnd = 1
};
#endif
};
+33 -23
View File
@@ -5,55 +5,62 @@
* \~russian API аутентификации
*/
/*
PIP - Platform Independent Primitives
PIP Authentication API
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PIP Authentication API
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIAUTH_H
#define PIAUTH_H
#include "pip_crypt_export.h"
#include "piobject.h"
#include "picrypt.h"
#include "piobject.h"
#include "pip_crypt_export.h"
class PIP_CRYPT_EXPORT PIAuth : public PIObject
{
class PIP_CRYPT_EXPORT PIAuth: public PIObject {
PIOBJECT(PIAuth)
public:
enum State {NotConnected, AuthProbe, PassRequest, AuthReply, KeyExchange, Connected};
enum State {
NotConnected,
AuthProbe,
PassRequest,
AuthReply,
KeyExchange,
Connected
};
//! Create PIAuth with your digital sign
PIAuth(const PIByteArray & sign);
//! Set server info data for client authorize event
void setInfoData(const PIByteArray & info) {custom_info = info;}
void setInfoData(const PIByteArray & info) { custom_info = info; }
//! Set server password for check
void setServerPassword(const PIString & ps);
//! Set list of trusted clients/servers public digital sign keys
void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) {auth_pkeys = pkeys;}
void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) { auth_pkeys = pkeys; }
//! Get list of trusted clients/servers public digital sign keys
PIVector<PIByteArray> getAuthorizedPublicKeys() {return auth_pkeys;}
PIVector<PIByteArray> getAuthorizedPublicKeys() { return auth_pkeys; }
//! Get your digital sign public key
PIByteArray getSignPublicKey() {return sign_pk;}
PIByteArray getSignPublicKey() { return sign_pk; }
//! Stop authorization
@@ -91,7 +98,10 @@ public:
EVENT1(passwordCheck, bool, result);
private:
enum Role {Client, Server};
enum Role {
Client,
Server
};
State disconnect(PIByteArray & ba, const PIString & error = PIString());
bool isAuthorizedKey(const PIByteArray & pkey);
+16 -17
View File
@@ -5,22 +5,22 @@
* \~russian Шифрование с помощью libsodium
*/
/*
PIP - Platform Independent Primitives
Cryptographic class using lib Sodium
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Cryptographic class using lib Sodium
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICRYPT_H
@@ -41,7 +41,7 @@ public:
PIByteArray setKey(const PIString & secret);
//! Returns current key
PIByteArray key() {return key_;}
PIByteArray key() { return key_; }
//! Encrypt given data "data", result size will be increased by \a sizeCrypt()
PIByteArray crypt(const PIByteArray & data);
@@ -92,7 +92,7 @@ public:
static PIByteArray extractSignPublicKey(const PIByteArray & secret_key);
//! Calculate digital signature for data
PIByteArray signMessage(const PIByteArray & data, PIByteArray secret_key);
PIByteArray signMessage(const PIByteArray & data, PIByteArray secret_key);
//! Verify digital signature of signed message
bool verifySign(const PIByteArray & data, const PIByteArray & signature, PIByteArray public_key);
@@ -104,7 +104,7 @@ public:
static void generateKeypair(PIByteArray & public_key, PIByteArray & secret_key, const PIByteArray & seed);
//! Encrypt given data "data"
PIByteArray crypt(const PIByteArray &data, const PIByteArray & public_key, const PIByteArray & secret_key);
PIByteArray crypt(const PIByteArray & data, const PIByteArray & public_key, const PIByteArray & secret_key);
//! Decrypt given data "crypt_data"
PIByteArray decrypt(const PIByteArray & crypt_data, const PIByteArray & public_key, const PIByteArray & secret_key, bool * ok = 0);
@@ -120,7 +120,6 @@ private:
static bool init();
PIByteArray nonce_, key_;
};
#endif // PICRYPT_H
+14 -14
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Module includes
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Crypt Crypt
//! \~\brief
@@ -51,7 +51,7 @@
#ifndef PICRYPTMODULE_H
#define PICRYPTMODULE_H
#include "picrypt.h"
#include "piauth.h"
#include "picrypt.h"
#endif // PICRYPTMODULE_H
+27 -28
View File
@@ -1,66 +1,65 @@
/*
PIP - Platform Independent Primitives
Contains geo ellipsoid models
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Contains geo ellipsoid models
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piellipsoidmodel.h"
PIEllipsoidModel::PIEllipsoidModel() {
a = 0.0;
flattening = 0.0;
a = 0.0;
flattening = 0.0;
eccentricity = 0.0;
angVelocity = 0.0;
angVelocity = 0.0;
}
PIEllipsoidModel PIEllipsoidModel::WGS84Ellipsoid() {
PIEllipsoidModel v;
v.a = 6378137.0;
v.flattening = 0.335281066475e-2;
v.a = 6378137.0;
v.flattening = 0.335281066475e-2;
v.eccentricity = 8.1819190842622e-2;
v.angVelocity = 7.292115e-5;
v.angVelocity = 7.292115e-5;
return v;
}
PIEllipsoidModel PIEllipsoidModel::PZ90Ellipsoid() {
PIEllipsoidModel v;
v.a = 6378136.0;
v.flattening = 3.35280373518e-3;
v.a = 6378136.0;
v.flattening = 3.35280373518e-3;
v.eccentricity = 8.1819106432923e-2;
v.angVelocity = 7.292115e-5;
v.angVelocity = 7.292115e-5;
return v;
}
PIEllipsoidModel PIEllipsoidModel::GPSEllipsoid() {
PIEllipsoidModel v = WGS84Ellipsoid();
v.angVelocity = 7.2921151467e-5;
v.angVelocity = 7.2921151467e-5;
return v;
}
PIEllipsoidModel PIEllipsoidModel::KrasovskiyEllipsoid() {
PIEllipsoidModel v;
v.a = 6378245.0;
v.flattening = 1.0/298.3;
v.eccentricity = sqrt(v.a*v.a - 6356863.0*6356863.0)/v.a;
v.angVelocity = 7.292115e-5;
v.a = 6378245.0;
v.flattening = 1.0 / 298.3;
v.eccentricity = sqrt(v.a * v.a - 6356863.0 * 6356863.0) / v.a;
v.angVelocity = 7.292115e-5;
return v;
}
+18 -19
View File
@@ -5,22 +5,22 @@
* \~russian Географическая эллипсоидная модель Земли
*/
/*
PIP - Platform Independent Primitives
Contains geo ellipsoid models
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Contains geo ellipsoid models
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIELLIPSOIDMODEL_H
@@ -32,20 +32,19 @@
class PIP_EXPORT PIEllipsoidModel {
public:
PIEllipsoidModel();
double eccSquared() const {return eccentricity * eccentricity;} // eccentricity squared
double b() const {return a * sqrt(1 - eccSquared());}
double eccSquared() const { return eccentricity * eccentricity; } // eccentricity squared
double b() const { return a * sqrt(1 - eccSquared()); }
static PIEllipsoidModel WGS84Ellipsoid();
static PIEllipsoidModel PZ90Ellipsoid();
static PIEllipsoidModel GPSEllipsoid();
static PIEllipsoidModel KrasovskiyEllipsoid();
double a; /// Major axis of Earth in meters
double flattening; /// Flattening (ellipsoid parameter)
double a; /// Major axis of Earth in meters
double flattening; /// Flattening (ellipsoid parameter)
double eccentricity; /// Eccentricity (ellipsoid parameter)
double angVelocity; /// Angular velocity of Earth in radians/sec
double angVelocity; /// Angular velocity of Earth in radians/sec
};
#endif // PIELLIPSOIDMODEL_H
+13 -13
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Module includes
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Geo Geo
//! \~\brief
+243 -219
View File
@@ -1,28 +1,28 @@
/*
PIP - Platform Independent Primitives
Class for geo position storage and conversions
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Class for geo position storage and conversions
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pigeoposition.h"
const double PIGeoPosition::one_cm_tolerance = 0.01; // One centimeter tolerance.
const double PIGeoPosition::one_mm_tolerance = 0.001; // One milimeter tolerance.
const double PIGeoPosition::one_um_tolerance = 0.000001; // One micron tolerance.
double PIGeoPosition::position_tolerance = PIGeoPosition::one_mm_tolerance; // Default tolerance in meters.
const double PIGeoPosition::one_cm_tolerance = 0.01; // One centimeter tolerance.
const double PIGeoPosition::one_mm_tolerance = 0.001; // One milimeter tolerance.
const double PIGeoPosition::one_um_tolerance = 0.000001; // One micron tolerance.
double PIGeoPosition::position_tolerance = PIGeoPosition::one_mm_tolerance; // Default tolerance in meters.
PIGeoPosition::PIGeoPosition() {
@@ -44,81 +44,84 @@ PIGeoPosition::PIGeoPosition(PIMathVectorT3d v, PIGeoPosition::CoordinateSystem
}
PIGeoPosition &PIGeoPosition::transformTo(PIGeoPosition::CoordinateSystem sys) {
if(sys == Unknown || sys == s) return *this;
PIGeoPosition & PIGeoPosition::transformTo(PIGeoPosition::CoordinateSystem sys) {
if (sys == Unknown || sys == s) return *this;
PIGeoPosition tmp(*this);
switch(s) {
switch (s) {
case Unknown: return *this;
case Geodetic:
switch (sys) {
case Unknown:
return *this;
case Geodetic:
switch(sys) {
case Unknown: case Geodetic: return *this;
case Geocentric:
convertGeodeticToGeocentric(*this, tmp, el);
tmp.s = Geocentric;
break;
case Cartesian:
convertGeodeticToCartesian(*this, tmp, el);
tmp.s = Cartesian;
break;
case Spherical:
convertGeodeticToGeocentric(*this, tmp, el);
tmp[0] = 90 - tmp[0]; // geocen -> sph
tmp.s = Spherical;
break;
}
break;
case Geodetic: return *this;
case Geocentric:
switch(sys) {
case Unknown: case Geocentric: return *this;
case Geodetic:
convertGeocentricToGeodetic(*this, tmp, el);
tmp.s = Geodetic;
break;
case Cartesian:
convertGeocentricToCartesian(*this, tmp);
tmp.s = Cartesian;
break;
case Spherical:
tmp[0] = 90 - tmp[0]; // geocen -> sph
tmp.s = Spherical;
break;
}
break;
convertGeodeticToGeocentric(*this, tmp, el);
tmp.s = Geocentric;
break;
case Cartesian:
switch(sys) {
case Unknown: case Cartesian: return *this;
case Geodetic:
convertCartesianToGeodetic(*this, tmp, el);
tmp.s = Geodetic;
break;
case Geocentric:
convertCartesianToGeocentric(*this, tmp);
tmp.s = Geocentric;
break;
case Spherical:
convertCartesianToSpherical(*this, tmp);
tmp.s = Spherical;
break;
}
break;
convertGeodeticToCartesian(*this, tmp, el);
tmp.s = Cartesian;
break;
case Spherical:
switch(sys) {
case Unknown: case Spherical: return *this;
case Geodetic:
(*this)[0] = 90 - (*this)[0]; // sph -> geocen
convertGeocentricToGeodetic(*this, tmp, el);
tmp.s = Geodetic;
break;
case Geocentric:
tmp[0] = 90 - tmp[0]; // sph -> geocen
tmp.s = Geocentric;
break;
case Cartesian:
convertSphericalToCartesian(*this, tmp);
tmp.s = Cartesian;
break;
}
convertGeodeticToGeocentric(*this, tmp, el);
tmp[0] = 90 - tmp[0]; // geocen -> sph
tmp.s = Spherical;
break;
}
break;
case Geocentric:
switch (sys) {
case Unknown:
case Geocentric: return *this;
case Geodetic:
convertGeocentricToGeodetic(*this, tmp, el);
tmp.s = Geodetic;
break;
case Cartesian:
convertGeocentricToCartesian(*this, tmp);
tmp.s = Cartesian;
break;
case Spherical:
tmp[0] = 90 - tmp[0]; // geocen -> sph
tmp.s = Spherical;
break;
}
break;
case Cartesian:
switch (sys) {
case Unknown:
case Cartesian: return *this;
case Geodetic:
convertCartesianToGeodetic(*this, tmp, el);
tmp.s = Geodetic;
break;
case Geocentric:
convertCartesianToGeocentric(*this, tmp);
tmp.s = Geocentric;
break;
case Spherical:
convertCartesianToSpherical(*this, tmp);
tmp.s = Spherical;
break;
}
break;
case Spherical:
switch (sys) {
case Unknown:
case Spherical: return *this;
case Geodetic:
(*this)[0] = 90 - (*this)[0]; // sph -> geocen
convertGeocentricToGeodetic(*this, tmp, el);
tmp.s = Geodetic;
break;
case Geocentric:
tmp[0] = 90 - tmp[0]; // sph -> geocen
tmp.s = Geocentric;
break;
case Cartesian:
convertSphericalToCartesian(*this, tmp);
tmp.s = Cartesian;
break;
}
break;
}
*this = tmp;
@@ -126,7 +129,7 @@ PIGeoPosition &PIGeoPosition::transformTo(PIGeoPosition::CoordinateSystem sys) {
}
double PIGeoPosition::x() const {
if(s == Cartesian) return (*this)[0];
if (s == Cartesian) return (*this)[0];
PIGeoPosition t(*this);
t.transformTo(Cartesian);
return t[0];
@@ -134,7 +137,7 @@ double PIGeoPosition::x() const {
double PIGeoPosition::y() const {
if(s == Cartesian) return (*this)[1];
if (s == Cartesian) return (*this)[1];
PIGeoPosition t(*this);
t.transformTo(Cartesian);
return t[1];
@@ -142,7 +145,7 @@ double PIGeoPosition::y() const {
double PIGeoPosition::z() const {
if(s == Cartesian) return (*this)[2];
if (s == Cartesian) return (*this)[2];
PIGeoPosition t(*this);
t.transformTo(Cartesian);
return t[2];
@@ -150,7 +153,7 @@ double PIGeoPosition::z() const {
double PIGeoPosition::latitudeGeodetic() const {
if(s == Geodetic) return (*this)[0];
if (s == Geodetic) return (*this)[0];
PIGeoPosition t(*this);
t.transformTo(Geodetic);
return t[0];
@@ -158,7 +161,7 @@ double PIGeoPosition::latitudeGeodetic() const {
double PIGeoPosition::latitudeGeocentric() const {
if(s == Geocentric) return (*this)[0];
if (s == Geocentric) return (*this)[0];
PIGeoPosition t(*this);
t.transformTo(Geocentric);
return t[0];
@@ -166,7 +169,7 @@ double PIGeoPosition::latitudeGeocentric() const {
double PIGeoPosition::longitude() const {
if(s != Cartesian) return (*this)[1];
if (s != Cartesian) return (*this)[1];
PIGeoPosition t(*this);
t.transformTo(Spherical);
return t[1];
@@ -174,7 +177,7 @@ double PIGeoPosition::longitude() const {
double PIGeoPosition::theta() const {
if(s == Spherical) return (*this)[0];
if (s == Spherical) return (*this)[0];
PIGeoPosition t(*this);
t.transformTo(Spherical);
return t[0];
@@ -187,7 +190,7 @@ double PIGeoPosition::phi() const {
double PIGeoPosition::radius() const {
if(s == Spherical || s == Geocentric) return (*this)[2];
if (s == Spherical || s == Geocentric) return (*this)[2];
PIGeoPosition t(*this);
t.transformTo(Spherical);
return t[2];
@@ -195,180 +198,192 @@ double PIGeoPosition::radius() const {
double PIGeoPosition::height() const {
if(s == Geodetic) return (*this)[2];
if (s == Geodetic) return (*this)[2];
PIGeoPosition t(*this);
t.transformTo(Geodetic);
return t[2];
}
PIGeoPosition &PIGeoPosition::setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell) {
PIGeoPosition & PIGeoPosition::setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell) {
assertm(lat <= 90 && lat >= -90, "Achtung! Invalid latitude in setGeodetic");
(*this)[0] = lat;
(*this)[1] = lon;
if((*this)[1] < 0) (*this)[1] += 360 * (1 + (unsigned long)((*this)[1]/360));
else if((*this)[1] >= 360) (*this)[1] -= 360 * (unsigned long)((*this)[1]/360);
if ((*this)[1] < 0)
(*this)[1] += 360 * (1 + (unsigned long)((*this)[1] / 360));
else if ((*this)[1] >= 360)
(*this)[1] -= 360 * (unsigned long)((*this)[1] / 360);
(*this)[2] = ht;
el = ell;
s = Geodetic;
el = ell;
s = Geodetic;
return *this;
}
PIGeoPosition &PIGeoPosition::setGeocentric(double lat, double lon, double rad) {
PIGeoPosition & PIGeoPosition::setGeocentric(double lat, double lon, double rad) {
assertm(lat <= 90 && lat >= -90, "Achtung! Invalid latitude in setGeocentric");
assertm(rad >= 0, "Achtung! Invalid radius in setGeocentric");
(*this)[0] = lat;
(*this)[1] = lon;
(*this)[2] = rad;
if((*this)[1] < 0) (*this)[1] += 360*(1+(unsigned long)((*this)[1]/360));
else if((*this)[1] >= 360) (*this)[1] -= 360*(unsigned long)((*this)[1]/360);
if ((*this)[1] < 0)
(*this)[1] += 360 * (1 + (unsigned long)((*this)[1] / 360));
else if ((*this)[1] >= 360)
(*this)[1] -= 360 * (unsigned long)((*this)[1] / 360);
s = Geocentric;
return *this;
}
PIGeoPosition &PIGeoPosition::setSpherical(double theta, double phi, double rad) {
PIGeoPosition & PIGeoPosition::setSpherical(double theta, double phi, double rad) {
assertm(theta <= 180 && theta >= 0, "Achtung! Invalid theta in setSpherical");
assertm(rad >= 0, "Achtung! Invalid radius in setSpherical");
(*this)[0] = theta;
(*this)[1] = phi;
(*this)[2] = rad;
if((*this)[1] < 0) (*this)[1] += 360*(1+(unsigned long)((*this)[1]/360));
else if((*this)[1] >= 360) (*this)[1] -= 360*(unsigned long)((*this)[1]/360);
if ((*this)[1] < 0)
(*this)[1] += 360 * (1 + (unsigned long)((*this)[1] / 360));
else if ((*this)[1] >= 360)
(*this)[1] -= 360 * (unsigned long)((*this)[1] / 360);
s = Spherical;
return *this;
}
PIGeoPosition &PIGeoPosition::setECEF(double x, double y, double z) {
PIGeoPosition & PIGeoPosition::setECEF(double x, double y, double z) {
(*this)[0] = x;
(*this)[1] = y;
(*this)[2] = z;
s = Cartesian;
s = Cartesian;
return *this;
}
void PIGeoPosition::convertSphericalToCartesian(const PIMathVectorT3d &tpr, PIMathVectorT3d &xyz) {
void PIGeoPosition::convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz) {
double st = sin(toRad(tpr[0]));
xyz[0] = tpr[2] * st * cos(toRad(tpr[1]));
xyz[1] = tpr[2] * st * sin(toRad(tpr[1]));
xyz[2] = tpr[2] * cos(toRad(tpr[0]));
xyz[0] = tpr[2] * st * cos(toRad(tpr[1]));
xyz[1] = tpr[2] * st * sin(toRad(tpr[1]));
xyz[2] = tpr[2] * cos(toRad(tpr[0]));
}
void PIGeoPosition::convertCartesianToSpherical(const PIMathVectorT3d &xyz, PIMathVectorT3d &tpr) {
void PIGeoPosition::convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr) {
tpr[2] = xyz.length();
if(tpr[2] <= PIGeoPosition::position_tolerance / 5) { // zero-length Cartesian vector
if (tpr[2] <= PIGeoPosition::position_tolerance / 5) { // zero-length Cartesian vector
tpr[0] = 90.0;
tpr[1] = 0.0;
return;
}
tpr[0] = acos(xyz[2] / tpr[2]) * rad2deg;
if(sqrt(xyz[0] * xyz[0] + xyz[1] * xyz[1]) < PIGeoPosition::position_tolerance / 5) { // pole
if (sqrt(xyz[0] * xyz[0] + xyz[1] * xyz[1]) < PIGeoPosition::position_tolerance / 5) { // pole
tpr[1] = 0.0;
return;
}
tpr[1] = atan2(xyz[1],xyz[0]) * rad2deg;
if(tpr[1] < 0.0) tpr[1] += 360.0;
tpr[1] = atan2(xyz[1], xyz[0]) * rad2deg;
if (tpr[1] < 0.0) tpr[1] += 360.0;
}
void PIGeoPosition::convertCartesianToGeodetic(const PIMathVectorT3d &xyz, PIMathVectorT3d &llh, PIEllipsoidModel ell) {
double p,slat,nn,htold,latold;
void PIGeoPosition::convertCartesianToGeodetic(const PIMathVectorT3d & xyz, PIMathVectorT3d & llh, PIEllipsoidModel ell) {
double p, slat, nn, htold, latold;
p = sqrt(xyz[0] * xyz[0] + xyz[1] * xyz[1]);
if(p < PIGeoPosition::position_tolerance / 5) { // pole or origin
llh[0] = (xyz[2] > 0.0 ? 90.0: -90.0);
llh[1] = 0.0; // lon undefined, really
llh[2] = piAbsd(xyz[2]) - ell.a * sqrt(1.0-ell.eccSquared());
if (p < PIGeoPosition::position_tolerance / 5) { // pole or origin
llh[0] = (xyz[2] > 0.0 ? 90.0 : -90.0);
llh[1] = 0.0; // lon undefined, really
llh[2] = piAbsd(xyz[2]) - ell.a * sqrt(1.0 - ell.eccSquared());
return;
}
llh[0] = atan2(xyz[2], p*(1.0-ell.eccSquared()));
llh[0] = atan2(xyz[2], p * (1.0 - ell.eccSquared()));
llh[2] = 0;
for(int i=0; i<5; i++) {
slat = sin(llh[0]);
nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
htold = llh[2];
for (int i = 0; i < 5; i++) {
slat = sin(llh[0]);
nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
htold = llh[2];
llh[2] = p / cos(llh[0]) - nn;
latold = llh[0];
llh[0] = atan2(xyz[2], p*(1.0 - ell.eccSquared() * (nn / (nn + llh[2]))));
if(piAbsd(llh[0] - latold) < 1.0e-9 && piAbsd(llh[2] - htold) < 1.0e-9 * ell.a) break;
llh[0] = atan2(xyz[2], p * (1.0 - ell.eccSquared() * (nn / (nn + llh[2]))));
if (piAbsd(llh[0] - latold) < 1.0e-9 && piAbsd(llh[2] - htold) < 1.0e-9 * ell.a) break;
}
llh[1] = atan2(xyz[1], xyz[0]);
if(llh[1] < 0.0) llh[1] += M_2PI;
if (llh[1] < 0.0) llh[1] += M_2PI;
llh[0] *= rad2deg;
llh[1] *= rad2deg;
}
void PIGeoPosition::convertGeodeticToCartesian(const PIMathVectorT3d &llh, PIMathVectorT3d &xyz, PIEllipsoidModel ell) {
void PIGeoPosition::convertGeodeticToCartesian(const PIMathVectorT3d & llh, PIMathVectorT3d & xyz, PIEllipsoidModel ell) {
double slat = sin(toRad(llh[0]));
double clat = cos(toRad(llh[0]));
double nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
xyz[0] = (nn + llh[2]) * clat * cos(toRad(llh[1]));
xyz[1] = (nn + llh[2]) * clat * sin(toRad(llh[1]));
xyz[2] = (nn * (1.0 - ell.eccSquared()) + llh[2]) * slat;
double nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
xyz[0] = (nn + llh[2]) * clat * cos(toRad(llh[1]));
xyz[1] = (nn + llh[2]) * clat * sin(toRad(llh[1]));
xyz[2] = (nn * (1.0 - ell.eccSquared()) + llh[2]) * slat;
}
void PIGeoPosition::convertCartesianToGeocentric(const PIMathVectorT3d &xyz, PIMathVectorT3d &llr) {
void PIGeoPosition::convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr) {
convertCartesianToSpherical(xyz, llr);
llr[0] = 90.0 - llr[0]; // convert theta to latitude
}
void PIGeoPosition::convertGeocentricToCartesian(const PIMathVectorT3d &llr, PIMathVectorT3d &xyz) {
void PIGeoPosition::convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz) {
PIMathVectorT3d llh(llr);
llh[0] = 90.0 - llh[0]; // convert latitude to theta
convertSphericalToCartesian(llh, xyz);
}
void PIGeoPosition::convertGeocentricToGeodetic(const PIMathVectorT3d &llr, PIMathVectorT3d &llh, PIEllipsoidModel ell) {
void PIGeoPosition::convertGeocentricToGeodetic(const PIMathVectorT3d & llr, PIMathVectorT3d & llh, PIEllipsoidModel ell) {
double cl, p, sl, slat, nn, htold, latold;
llh[1] = llr[1]; // longitude is unchanged
cl = sin(toRad(90.0 - llr[0]));
sl = cos(toRad(90.0 - llr[0]));
if(llr[2] <= PIGeoPosition::position_tolerance / 5) { // radius is below tolerance, hence assign zero-length, arbitrarily set latitude = longitude = 0
cl = sin(toRad(90.0 - llr[0]));
sl = cos(toRad(90.0 - llr[0]));
if (llr[2] <= PIGeoPosition::position_tolerance /
5) { // radius is below tolerance, hence assign zero-length, arbitrarily set latitude = longitude = 0
llh[0] = llh[1] = 0.0;
llh[2] = -ell.a;
llh[2] = -ell.a;
return;
} else if(cl < 1.e-10) { // near pole ... note that 1mm/radius(Earth) = 1.5e-10
if(llr[0] < 0.0) llh[0] = -90.0;
else llh[0] = 90.0;
} else if (cl < 1.e-10) { // near pole ... note that 1mm/radius(Earth) = 1.5e-10
if (llr[0] < 0.0)
llh[0] = -90.0;
else
llh[0] = 90.0;
llh[1] = 0.0;
llh[2] = llr[2] - ell.a * sqrt(1.0 - ell.eccSquared());
return;
}
llh[0] = atan2(sl, cl * (1.0 - ell.eccSquared()));
p = cl * llr[2];
p = cl * llr[2];
llh[2] = 0.0;
for(int i=0; i<5; i++) {
slat = sin(llh[0]);
nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
htold = llh[2];
for (int i = 0; i < 5; i++) {
slat = sin(llh[0]);
nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
htold = llh[2];
llh[2] = p / cos(llh[0]) - nn;
latold = llh[0];
llh[0] = atan2(sl, cl * (1.0 - ell.eccSquared() * (nn / (nn + llh[2]))));
if(piAbsd(llh[0] - latold) < 1.0e-9 && piAbsd(llh[2] - htold) < 1.0e-9 * ell.a) break;
if (piAbsd(llh[0] - latold) < 1.0e-9 && piAbsd(llh[2] - htold) < 1.0e-9 * ell.a) break;
}
llh[0] *= rad2deg;
}
void PIGeoPosition::convertGeodeticToGeocentric(const PIMathVectorT3d &llh, PIMathVectorT3d &llr, PIEllipsoidModel ell) {
void PIGeoPosition::convertGeodeticToGeocentric(const PIMathVectorT3d & llh, PIMathVectorT3d & llr, PIEllipsoidModel ell) {
double slat = sin(toRad(llh[0]));
double nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
llr[1] = llh[1]; // longitude is unchanged
llr[2] = sqrt((nn+llh[2])*(nn+llh[2]) + nn*ell.eccSquared()*(nn*ell.eccSquared()-2*(nn+llh[2]))*slat*slat); // radius
if(llr[2] <= PIGeoPosition::position_tolerance/5) { // radius is below tolerance, hence assign zero-length
llr[0] = llr[1] = llr[2] = 0; // arbitrarily set latitude = longitude = 0
double nn = ell.a / sqrt(1.0 - ell.eccSquared() * slat * slat);
llr[1] = llh[1]; // longitude is unchanged
llr[2] =
sqrt((nn + llh[2]) * (nn + llh[2]) + nn * ell.eccSquared() * (nn * ell.eccSquared() - 2 * (nn + llh[2])) * slat * slat); // radius
if (llr[2] <= PIGeoPosition::position_tolerance / 5) { // radius is below tolerance, hence assign zero-length
llr[0] = llr[1] = llr[2] = 0; // arbitrarily set latitude = longitude = 0
return;
}
if(1 - piAbsd(slat) < 1.e-10) { // at the pole
if(slat < 0) llr[0] = -90.0;
else llr[0] = 90.0;
if (1 - piAbsd(slat) < 1.e-10) { // at the pole
if (slat < 0)
llr[0] = -90.0;
else
llr[0] = 90.0;
llr[1] = 0.0;
return;
}
@@ -380,79 +395,85 @@ void PIGeoPosition::convertGeodeticToGeocentric(const PIMathVectorT3d &llh, PIMa
double PIGeoPosition::radiusEarth(double geolat, PIEllipsoidModel ell) {
double slat = sin(toRad(geolat));
double e = (1.0 - ell.eccSquared());
double f = (1.0 + (e * e - 1.0) * slat * slat) / (1.0 - ell.eccSquared() * slat * slat);
double e = (1.0 - ell.eccSquared());
double f = (1.0 + (e * e - 1.0) * slat * slat) / (1.0 - ell.eccSquared() * slat * slat);
return (ell.a * sqrt(f));
}
PIGeoPosition &PIGeoPosition::operator=(const PIMathVectorT3d &v) {
*((PIMathVectorT3d*)(this)) = v;
PIGeoPosition & PIGeoPosition::operator=(const PIMathVectorT3d & v) {
*((PIMathVectorT3d *)(this)) = v;
return *this;
}
PIGeoPosition &PIGeoPosition::operator-=(const PIGeoPosition &right) {
PIGeoPosition & PIGeoPosition::operator-=(const PIGeoPosition & right) {
PIGeoPosition r(right);
CoordinateSystem saves = s;
transformTo(Cartesian);
r.transformTo(Cartesian);
(*(PIMathVectorT3d*)(this)) -= r;
(*(PIMathVectorT3d *)(this)) -= r;
transformTo(saves);
return *this;
}
PIGeoPosition &PIGeoPosition::operator+=(const PIGeoPosition &right) {
PIGeoPosition & PIGeoPosition::operator+=(const PIGeoPosition & right) {
PIGeoPosition r(right);
CoordinateSystem saves = s;
transformTo(Cartesian);
r.transformTo(Cartesian);
(*(PIMathVectorT3d*)(this)) += r;
(*(PIMathVectorT3d *)(this)) += r;
transformTo(saves);
return *this;
}
bool PIGeoPosition::operator==(const PIGeoPosition &right) const {
if(el.a != right.el.a || el.eccSquared() != right.el.eccSquared()) return false;
if(range(*this, right) < position_tolerance) return true;
else return false;
bool PIGeoPosition::operator==(const PIGeoPosition & right) const {
if (el.a != right.el.a || el.eccSquared() != right.el.eccSquared()) return false;
if (range(*this, right) < position_tolerance)
return true;
else
return false;
}
void PIGeoPosition::initialize(PIMathVectorT3d v, PIGeoPosition::CoordinateSystem sys, PIEllipsoidModel ell) {
double a(v[0]), b(v[1]), c(v[2]);
if(sys == Geodetic || sys==Geocentric) {
if (sys == Geodetic || sys == Geocentric) {
assertm(a <= 90 && a >= -90, "Achtung! Invalid latitude in constructor");
if(b < 0) b += 360*(1+(unsigned long)(b/360));
else if(b >= 360) b -= 360*(unsigned long)(b/360);
if (b < 0)
b += 360 * (1 + (unsigned long)(b / 360));
else if (b >= 360)
b -= 360 * (unsigned long)(b / 360);
}
if(sys==Geocentric || sys==Spherical) {
if (sys == Geocentric || sys == Spherical) {
assertm(c >= 0, "Achtung! Invalid radius in constructor");
}
if(sys==Spherical) {
if (sys == Spherical) {
assertm(a >= 0 && a <= 180, "Achtung! Invalid theta in constructor");
if(b < 0) b += 360*(1+(unsigned long)(b/360));
else if(b >= 360) b -= 360*(unsigned long)(b/360);
if (b < 0)
b += 360 * (1 + (unsigned long)(b / 360));
else if (b >= 360)
b -= 360 * (unsigned long)(b / 360);
}
(*this)[0] = a;
(*this)[1] = b;
(*this)[2] = c;
el = ell;
s = sys;
el = ell;
s = sys;
}
double PIGeoPosition::range(const PIGeoPosition &a, const PIGeoPosition &b) {
PIGeoPosition l(a),r(b);
double PIGeoPosition::range(const PIGeoPosition & a, const PIGeoPosition & b) {
PIGeoPosition l(a), r(b);
l.transformTo(PIGeoPosition::Cartesian);
r.transformTo(PIGeoPosition::Cartesian);
return (l - r).length();
}
double PIGeoPosition::elevation(const PIGeoPosition &p) const {
double PIGeoPosition::elevation(const PIGeoPosition & p) const {
PIGeoPosition r(*this), s(p);
r.transformTo(Cartesian);
s.transformTo(Cartesian);
@@ -460,7 +481,7 @@ double PIGeoPosition::elevation(const PIGeoPosition &p) const {
}
double PIGeoPosition::elevationGeodetic(const PIGeoPosition &p) const {
double PIGeoPosition::elevationGeodetic(const PIGeoPosition & p) const {
PIGeoPosition r(*this), s(p);
double lat = toRad(r.latitudeGeodetic());
double lng = toRad(r.longitude());
@@ -471,47 +492,49 @@ double PIGeoPosition::elevationGeodetic(const PIGeoPosition &p) const {
PIMathVectorT3d z = s - r;
assertm(z.length() > 1e-4, "Positions are within .1 millimeter");
PIMathVectorT3d kv; // Compute k vector in local North-East-Up (NEU) system
kv[0] = cos(lat) * cos(lng);
kv[1] = cos(lat) * sin(lng);
kv[2] = sin(lat);
local_up = z.dot(kv); // Take advantage of dot method to get Up coordinate in local NEU system
cos_up = local_up / z.length(); // Let's get cos(z), being z the angle with respect to local vertical (Up);
kv[0] = cos(lat) * cos(lng);
kv[1] = cos(lat) * sin(lng);
kv[2] = sin(lat);
local_up = z.dot(kv); // Take advantage of dot method to get Up coordinate in local NEU system
cos_up = local_up / z.length(); // Let's get cos(z), being z the angle with respect to local vertical (Up);
return 90.0 - toDeg(acos(cos_up));
}
double PIGeoPosition::azimuth(const PIGeoPosition &p) const {
double PIGeoPosition::azimuth(const PIGeoPosition & p) const {
PIGeoPosition r(*this), s(p);
r.transformTo(Cartesian);
s.transformTo(Cartesian);
double xy, xyz, cosl, sinl, sint, xn1, xn2, xn3, xe1, xe2;
double z1, z2, z3, p1, p2, alpha;
xy = r[0] * r[0] + r[1] * r[1];
xy = r[0] * r[0] + r[1] * r[1];
xyz = xy + r[2] * r[2];
xy = sqrt(xy);
xy = sqrt(xy);
xyz = sqrt(xyz);
assertm(xy > 1e-14 && xyz > 1e-14, "Divide by Zero Error");
cosl = r[0] / xy;
sinl = r[1] / xy;
sint = r[2] / xyz;
xn1 = -sint * cosl;
xn2 = -sint * sinl;
xn3 = xy / xyz;
xe1 = -sinl;
xe2 = cosl;
z1 = s[0] - r[0];
z2 = s[1] - r[1];
z3 = s[2] - r[2];
p1 = (xn1 * z1) + (xn2 * z2) + (xn3 * z3) ;
p2 = (xe1 * z1) + (xe2 * z2) ;
xn1 = -sint * cosl;
xn2 = -sint * sinl;
xn3 = xy / xyz;
xe1 = -sinl;
xe2 = cosl;
z1 = s[0] - r[0];
z2 = s[1] - r[1];
z3 = s[2] - r[2];
p1 = (xn1 * z1) + (xn2 * z2) + (xn3 * z3);
p2 = (xe1 * z1) + (xe2 * z2);
assertm((piAbsd(p1) + piAbsd(p2)) >= 1.0e-16, "azAngle(), failed p1+p2 test");
alpha = 90 - toDeg(atan2(p1, p2));
if (alpha < 0) return alpha + 360;
else return alpha;
if (alpha < 0)
return alpha + 360;
else
return alpha;
}
double PIGeoPosition::azimuthGeodetic(const PIGeoPosition &p) const {
double PIGeoPosition::azimuthGeodetic(const PIGeoPosition & p) const {
PIGeoPosition r(*this), s(p);
double lat = toRad(r.latitudeGeodetic());
double lng = toRad(r.longitude());
@@ -525,21 +548,23 @@ double PIGeoPosition::azimuthGeodetic(const PIGeoPosition &p) const {
iv[1] = -sin(lat) * sin(lng);
iv[2] = cos(lat);
PIMathVectorT3d jv; // Compute j vector in local North-East-Up (NEU) system
jv[0] = -sin(lng);
jv[1] = cos(lng);
jv[2] = 0.0;
double local_n = z.dot(iv) / z.length(); // Now, let's use dot product to get localN unitary vectors
double local_e = z.dot(jv) / z.length(); // Now, let's use dot product to get localE unitary vector
double test = piAbsd(local_n) + piAbsd(local_e); // Let's test if computing azimuth has any sense
if (test < 1.0e-16) return 0.0; // Warning: If elevation is very close to 90 degrees, we will return azimuth = 0.0
jv[0] = -sin(lng);
jv[1] = cos(lng);
jv[2] = 0.0;
double local_n = z.dot(iv) / z.length(); // Now, let's use dot product to get localN unitary vectors
double local_e = z.dot(jv) / z.length(); // Now, let's use dot product to get localE unitary vector
double test = piAbsd(local_n) + piAbsd(local_e); // Let's test if computing azimuth has any sense
if (test < 1.0e-16) return 0.0; // Warning: If elevation is very close to 90 degrees, we will return azimuth = 0.0
double alpha = toDeg(atan2(local_e, local_n));
if (alpha < 0.0) return alpha + 360.0;
else return alpha;
if (alpha < 0.0)
return alpha + 360.0;
else
return alpha;
}
double PIGeoPosition::getCurvMeridian() const {
double slat = sin(toRad(latitudeGeodetic()));
double w = 1.0 / sqrt(1.0 - el.eccSquared() * slat * slat);
double w = 1.0 / sqrt(1.0 - el.eccSquared() * slat * slat);
return el.a * (1.0 - el.eccSquared()) * w * w * w;
}
@@ -548,4 +573,3 @@ double PIGeoPosition::getCurvPrimeVertical() const {
double slat = sin(toRad(latitudeGeodetic()));
return el.a / sqrt(1.0 - el.eccSquared() * slat * slat);
}
+109 -71
View File
@@ -5,22 +5,22 @@
* \~russian Класс для хранения географической позиции и преобразований
*/
/*
PIP - Platform Independent Primitives
Class for geo position storage and conversions
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Class for geo position storage and conversions
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIGEOPOSITION_H
@@ -29,34 +29,45 @@
#include "piellipsoidmodel.h"
#include "pimathvector.h"
class PIP_EXPORT PIGeoPosition : public PIMathVectorT3d
{
class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d {
public:
enum CoordinateSystem {
Unknown=0, /// Unknown coordinate system
Geodetic, /// Geodetic latitude, longitude, and height above ellipsoid
Geocentric, /// Geocentric (regular spherical coordinates)
Cartesian, /// Cartesian (Earth-centered, Earth-fixed)
Spherical /// Spherical coordinates (theta,phi,radius)
Unknown = 0, /// Unknown coordinate system
Geodetic, /// Geodetic latitude, longitude, and height above ellipsoid
Geocentric, /// Geocentric (regular spherical coordinates)
Cartesian, /// Cartesian (Earth-centered, Earth-fixed)
Spherical /// Spherical coordinates (theta,phi,radius)
};
static const double one_cm_tolerance;/// One centimeter tolerance.
static const double one_mm_tolerance;/// One millimeter tolerance.
static const double one_um_tolerance;/// One micron tolerance.
static double position_tolerance;/// Default tolerance (default 1mm)
static double setPositionTolerance(const double tol) {position_tolerance = tol; return position_tolerance;}
static double getPositionTolerance() {return position_tolerance;}
static const double one_cm_tolerance; /// One centimeter tolerance.
static const double one_mm_tolerance; /// One millimeter tolerance.
static const double one_um_tolerance; /// One micron tolerance.
static double position_tolerance; /// Default tolerance (default 1mm)
static double setPositionTolerance(const double tol) {
position_tolerance = tol;
return position_tolerance;
}
static double getPositionTolerance() { return position_tolerance; }
PIGeoPosition();
PIGeoPosition(double a, double b, double c, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
PIGeoPosition &transformTo(CoordinateSystem sys);
PIGeoPosition &asGeodetic() {transformTo(Geodetic); return *this; } /// Convert to geodetic coordinate
PIGeoPosition &asGeodetic(const PIEllipsoidModel &ell) {setEllipsoidModel(ell); transformTo(Geodetic); return *this;} /// Convert to another ell, then to geodetic coordinates
PIGeoPosition &asECEF() {transformTo(Cartesian); return *this; } /// Convert to cartesian coordinates
PIGeoPosition & transformTo(CoordinateSystem sys);
PIGeoPosition & asGeodetic() {
transformTo(Geodetic);
return *this;
} /// Convert to geodetic coordinate
PIGeoPosition & asGeodetic(const PIEllipsoidModel & ell) {
setEllipsoidModel(ell);
transformTo(Geodetic);
return *this;
} /// Convert to another ell, then to geodetic coordinates
PIGeoPosition & asECEF() {
transformTo(Cartesian);
return *this;
} /// Convert to cartesian coordinates
double x() const;
double y() const;
@@ -70,43 +81,51 @@ public:
double height() const;
/// Set the ellipsoid values for this PIGeoPosition given a ellipsoid.
void setEllipsoidModel(const PIEllipsoidModel &ell) {el = ell;}
void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; }
/// Set the \a PIGeoPosition given geodetic coordinates in degrees. \a CoordinateSystem is set to \a Geodetic.
PIGeoPosition &setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Set the \a PIGeoPosition given geocentric coordinates in degrees. \a CoordinateSystem is set to \a Geocentric
PIGeoPosition &setGeocentric(double lat, double lon, double rad);
PIGeoPosition & setGeocentric(double lat, double lon, double rad);
/// Set the \a PIGeoPosition given spherical coordinates in degrees. \a CoordinateSystem is set to \a Spherical
PIGeoPosition &setSpherical(double theta, double phi, double rad);
PIGeoPosition & setSpherical(double theta, double phi, double rad);
/// Set the \a PIGeoPosition given ECEF coordinates in meeters. \a CoordinateSystem is set to \a Cartesian.
PIGeoPosition &setECEF(double x, double y, double z);
PIGeoPosition & setECEF(double x, double y, double z);
/// Fundamental conversion from spherical to cartesian coordinates.
static void convertSphericalToCartesian(const PIMathVectorT3d &tpr, PIMathVectorT3d &xyz);
static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz);
/// Fundamental routine to convert cartesian to spherical coordinates.
static void convertCartesianToSpherical(const PIMathVectorT3d &xyz, PIMathVectorT3d &tpr);
static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr);
/// Fundamental routine to convert ECEF (cartesian) to geodetic coordinates,
static void convertCartesianToGeodetic(const PIMathVectorT3d &xyz, PIMathVectorT3d &llh, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz,
PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert geodetic to ECEF (cartesian) coordinates,
static void convertGeodeticToCartesian(const PIMathVectorT3d &llh, PIMathVectorT3d &xyz, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
static void convertGeodeticToCartesian(const PIMathVectorT3d & llh,
PIMathVectorT3d & xyz,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert cartesian (ECEF) to geocentric
static void convertCartesianToGeocentric(const PIMathVectorT3d &xyz, PIMathVectorT3d &llr);
static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr);
/// Fundamental routine to convert geocentric to cartesian (ECEF)
static void convertGeocentricToCartesian(const PIMathVectorT3d &llr, PIMathVectorT3d &xyz);
static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz);
/// Fundamental routine to convert geocentric to geodetic
static void convertGeocentricToGeodetic(const PIMathVectorT3d &llr, PIMathVectorT3d &llh, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr,
PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert geodetic to geocentric
static void convertGeodeticToGeocentric(const PIMathVectorT3d &llh, PIMathVectorT3d &llr, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh,
PIMathVectorT3d & llr,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Compute the radius of the ellipsoidal Earth, given the geodetic latitude.
static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
@@ -117,22 +136,20 @@ public:
}
/// Compute the range in meters between two PIGeoPositions.
static double range(const PIGeoPosition &a, const PIGeoPosition &b);
double range(const PIGeoPosition &p) const {
return range((*this), p);
}
static double range(const PIGeoPosition & a, const PIGeoPosition & b);
double range(const PIGeoPosition & p) const { return range((*this), p); }
/// Computes the elevation of the input (p) position as seen from this PIGeoPosition.
double elevation(const PIGeoPosition &p) const;
double elevation(const PIGeoPosition & p) const;
/// Computes the elevation of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system.
double elevationGeodetic(const PIGeoPosition &p) const;
double elevationGeodetic(const PIGeoPosition & p) const;
/// Computes the azimuth of the input (p) position as seen from this PIGeoPosition.
double azimuth(const PIGeoPosition &p) const;
double azimuth(const PIGeoPosition & p) const;
/// Computes the azimuth of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system.
double azimuthGeodetic(const PIGeoPosition &p) const;
double azimuthGeodetic(const PIGeoPosition & p) const;
/// Computes the radius of curvature of the meridian (Rm) corresponding to this PIGeoPosition.
double getCurvMeridian() const;
@@ -141,19 +158,19 @@ public:
double getCurvPrimeVertical() const;
/// Returns as PIMathVectorT3d
const PIMathVectorT3d & vector() const {return *this;}
const PIMathVectorT3d & vector() const { return *this; }
PIGeoPosition &operator=(const PIMathVectorT3d & v);
PIGeoPosition &operator-=(const PIGeoPosition &right);
PIGeoPosition &operator+=(const PIGeoPosition &right);
friend PIGeoPosition operator-(const PIGeoPosition &left, const PIGeoPosition &right);
friend PIGeoPosition operator+(const PIGeoPosition &left, const PIGeoPosition &right);
friend PIGeoPosition operator*(const double &scale, const PIGeoPosition &right);
friend PIGeoPosition operator*(const PIGeoPosition &left, const double &scale);
friend PIGeoPosition operator*(const int &scale, const PIGeoPosition &right);
friend PIGeoPosition operator*(const PIGeoPosition &left, const int &scale);
bool operator==(const PIGeoPosition &right) const;
bool operator!=(const PIGeoPosition &right) const {return !(operator==(right));}
PIGeoPosition & operator=(const PIMathVectorT3d & v);
PIGeoPosition & operator-=(const PIGeoPosition & right);
PIGeoPosition & operator+=(const PIGeoPosition & right);
friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right);
friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right);
friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale);
friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale);
bool operator==(const PIGeoPosition & right) const;
bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); }
private:
@@ -161,15 +178,36 @@ private:
PIEllipsoidModel el;
CoordinateSystem s;
};
inline PIGeoPosition operator-(const PIGeoPosition &left, const PIGeoPosition &right) {PIGeoPosition l(left),r(right); l.transformTo(PIGeoPosition::Cartesian); r.transformTo(PIGeoPosition::Cartesian); l -= r; return l;}
inline PIGeoPosition operator+(const PIGeoPosition &left, const PIGeoPosition &right) {PIGeoPosition l(left),r(right); l.transformTo(PIGeoPosition::Cartesian); r.transformTo(PIGeoPosition::Cartesian); l += r; return l;}
inline PIGeoPosition operator*(const double &scale, const PIGeoPosition &right) {PIMathVectorT3d tmp(right); tmp *= scale; return PIGeoPosition(tmp);}
inline PIGeoPosition operator*(const PIGeoPosition &left, const double &scale) {return operator* (scale, left);}
inline PIGeoPosition operator*(const int &scale, const PIGeoPosition &right) {return operator* (double(scale), right);}
inline PIGeoPosition operator*(const PIGeoPosition &left, const int &scale) {return operator* (double(scale), left);}
inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian);
r.transformTo(PIGeoPosition::Cartesian);
l -= r;
return l;
}
inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian);
r.transformTo(PIGeoPosition::Cartesian);
l += r;
return l;
}
inline PIGeoPosition operator*(const double & scale, const PIGeoPosition & right) {
PIMathVectorT3d tmp(right);
tmp *= scale;
return PIGeoPosition(tmp);
}
inline PIGeoPosition operator*(const PIGeoPosition & left, const double & scale) {
return operator*(scale, left);
}
inline PIGeoPosition operator*(const int & scale, const PIGeoPosition & right) {
return operator*(double(scale), right);
}
inline PIGeoPosition operator*(const PIGeoPosition & left, const int & scale) {
return operator*(double(scale), left);
}
#endif // PIGEOPOSITION_H
+19 -20
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Introspection module - base macros and types
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - base macros and types
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup Introspection Introspection
//! \~\brief
@@ -61,13 +61,12 @@ class PIIntrospection;
class PIIntrospectionServer;
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#define __PIINTROSPECTION_SINGLETON_H__(T) \
static PIIntrospection##T##Interface * instance();
# define __PIINTROSPECTION_SINGLETON_H__(T) static PIIntrospection##T##Interface * instance();
#define __PIINTROSPECTION_SINGLETON_CPP__(T) \
PIIntrospection##T##Interface * PIIntrospection##T##Interface::instance() {\
static PIIntrospection##T##Interface ret;\
return &ret;\
}
# define __PIINTROSPECTION_SINGLETON_CPP__(T) \
PIIntrospection##T##Interface * PIIntrospection##T##Interface::instance() { \
static PIIntrospection##T##Interface ret; \
return &ret; \
}
#endif // PIP_INTROSPECTION
#endif // PIINTROSPECTION_BASE_H
@@ -1,27 +1,27 @@
/*
PIP - Platform Independent Primitives
Introspection module - interface for containers
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - interface for containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piintrospection_containers.h"
PIIntrospectionContainersType::~PIIntrospectionContainersType() {
if (has_demangled) {
//free((void*)demangled);
// free((void*)demangled);
has_demangled = false;
}
}
@@ -29,21 +29,23 @@ PIIntrospectionContainersType::~PIIntrospectionContainersType() {
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_containers_p.h"
# include "piintrospection_containers_p.h"
__PIINTROSPECTION_SINGLETON_CPP__(Containers)
#ifdef CC_GCC
# include <cxxabi.h>
# ifdef CC_GCC
# include <cxxabi.h>
const char * demangle(const char * name) {
int status = -4;
char * res = abi::__cxa_demangle(name, NULL, NULL, &status);
if (status == 0) return res;
return name;
}
#else
const char * demangle(const char * name) {return name;}
#endif
# else
const char * demangle(const char * name) {
return name;
}
# endif
void PIIntrospectionContainersType::finish() {
@@ -53,11 +55,10 @@ void PIIntrospectionContainersType::finish() {
return;
}
size_t l = strlen(name);
if (l > 0)
id = piHashData((const uchar*)name, int(l));
demangled = demangle(name);
if (l > 0) id = piHashData((const uchar *)name, int(l));
demangled = demangle(name);
has_demangled = name != demangled;
//printf("create typeinfo for %s -> %s\n", name, demangled);
// printf("create typeinfo for %s -> %s\n", name, demangled);
}
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Introspection module - interface for containers
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - interface for containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINTROSPECTION_CONTAINERS_H
@@ -58,11 +58,11 @@ private:
# define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())
// clang-format off
# define PIINTROSPECTION_CONTAINER_NEW (t, isz) PIINTROSPECTION_CONTAINERS->containerNew (PIIntrospectionContainersTypeInfo<t>::get(), isz);
# define PIINTROSPECTION_CONTAINER_DELETE(t ) PIINTROSPECTION_CONTAINERS->containerDelete(PIIntrospectionContainersTypeInfo<t>::get() );
# define PIINTROSPECTION_CONTAINER_ALLOC (t, cnt) PIINTROSPECTION_CONTAINERS->containerAlloc (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_FREE (t, cnt) PIINTROSPECTION_CONTAINERS->containerFree (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_USED (t, cnt) PIINTROSPECTION_CONTAINERS->containerUsed (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_NEW(t, isz) PIINTROSPECTION_CONTAINERS->containerNew (PIIntrospectionContainersTypeInfo<t>::get(), isz);
# define PIINTROSPECTION_CONTAINER_DELETE(t) PIINTROSPECTION_CONTAINERS->containerDelete(PIIntrospectionContainersTypeInfo<t>::get() );
# define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt) PIINTROSPECTION_CONTAINERS->containerAlloc (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_FREE(t, cnt) PIINTROSPECTION_CONTAINERS->containerFree (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_USED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUsed (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUnused(PIIntrospectionContainersTypeInfo<t>::get(), cnt);
// clang-format on
@@ -1,44 +1,46 @@
/*
PIP - Platform Independent Primitives
Introspection module - implementation of containers
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - implementation of containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piintrospection_containers_p.h"
#include "piintrospection_containers.h"
#include <stdio.h>
PIIntrospectionContainers::PIIntrospectionContainers() {
//printf("PIIntrospectionContainers %p\n", this);
// printf("PIIntrospectionContainers %p\n", this);
}
void PIIntrospectionContainers::containerNew(const PIIntrospectionContainersType & ti, uint isz) {
PISpinlockLocker _ml(mutex);
//printf("containerNew lock\n");
// printf("containerNew lock\n");
PIIntrospectionContainersType & t(types[ti.id]);
_Type & d(data[ti.id]);
if (!t.inited) {
t = ti;
d.id = ti.id;
t = ti;
d.id = ti.id;
d.item_size = isz;
}
d.count++;
//printf("containerNew unlock\n");
// printf("containerNew unlock\n");
}
@@ -49,7 +51,7 @@ void PIIntrospectionContainers::containerDelete(const PIIntrospectionContainersT
void PIIntrospectionContainers::containerAlloc(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf(" alloc %s %d\n", tn, cnt);
// printf(" alloc %s %d\n", tn, cnt);
if (cnt == 0) return;
PISpinlockLocker _ml(mutex);
data[ti.id].allocated += cnt;
@@ -57,7 +59,7 @@ void PIIntrospectionContainers::containerAlloc(const PIIntrospectionContainersTy
void PIIntrospectionContainers::containerFree(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf(" free %s %d\n", tn, cnt);
// printf(" free %s %d\n", tn, cnt);
if (cnt == 0) return;
PISpinlockLocker _ml(mutex);
data[ti.id].allocated -= cnt;
@@ -65,7 +67,7 @@ void PIIntrospectionContainers::containerFree(const PIIntrospectionContainersTyp
void PIIntrospectionContainers::containerUsed(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf(" used %s %d\n", tn, cnt);
// printf(" used %s %d\n", tn, cnt);
if (cnt == 0) return;
PISpinlockLocker _ml(mutex);
data[ti.id].used += cnt;
@@ -73,7 +75,7 @@ void PIIntrospectionContainers::containerUsed(const PIIntrospectionContainersTyp
void PIIntrospectionContainers::containerUnused(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf("unused %s %d\n", tn, cnt);
// printf("unused %s %d\n", tn, cnt);
if (cnt == 0) return;
PISpinlockLocker _ml(mutex);
data[ti.id].used -= cnt;
@@ -84,14 +86,14 @@ PIVector<PIIntrospectionContainers::TypeInfo> PIIntrospectionContainers::getInfo
PIVector<PIIntrospectionContainers::TypeInfo> ret;
mutex.lock();
std::map<uint, PIIntrospectionContainers::_Type> d = data;
std::map<uint, PIIntrospectionContainersType> t = types;
std::map<uint, PIIntrospectionContainersType> t = types;
mutex.unlock();
ret.reserve(t.size());
for (typename std::map<uint, PIIntrospectionContainersType>::const_iterator i = t.begin(); i != t.end(); ++i) {
ret.push_back(TypeInfo());
TypeInfo & ti(ret.back());
_Type & _t(d[i->first]);
memcpy((void*)&ti, (const void*)&_t, sizeof(_t));
memcpy((void *)&ti, (const void *)&_t, sizeof(_t));
ti.name = PIStringAscii(i->second.demangled);
}
return ret;
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Introspection module - implementation of containers
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - implementation of containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINTROSPECTION_CONTAINERS_P_H
+108 -111
View File
@@ -1,111 +1,108 @@
/*
PIP - Platform Independent Primitives
Introspection module
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_server.h"
#include "piintrospection_server_p.h"
#include "piprocess.h"
#include "pichunkstream.h"
PRIVATE_DEFINITION_START(PIIntrospectionServer)
PIIntrospection::ProcessInfo process_info;
PRIVATE_DEFINITION_END(PIIntrospectionServer)
PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) {
PRIVATE->process_info = PIIntrospection::getInfo();
sysmon = 0;
}
PIIntrospectionServer::~PIIntrospectionServer() {
PIPeer::stop();
if (sysmon)
if (sysmon->property("__iserver__").toBool())
delete sysmon;
sysmon = 0;
}
PIIntrospectionServer * PIIntrospectionServer::instance() {
static PIIntrospectionServer ret;
return &ret;
}
void PIIntrospectionServer::start(const PIString & server_name) {
if (!sysmon) {
sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID());
if (sysmon) {
piCoutObj << "using existing sysmon";
CONNECT1(void, PIObject *, sysmon, deleted, this, sysmonDeleted);
} else {
piCoutObj << "create own sysmon";
sysmon = new PISystemMonitor();
sysmon->setProperty("__iserver__", true);
sysmon->startOnSelf();
}
}
changeName(server_name + genName());
PIPeer::start();
}
PIString PIIntrospectionServer::genName() {
randomize();
return "__introspection__server_" + PIString::fromNumber(randomi() % 1000);
}
void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) {
if (data.size() < 8) return;
PIByteArray rba(data);
uint _sign(0); rba >> _sign;
if (_sign != PIIntrospection::sign) return;
PIIntrospection::RequiredInfo ri;
rba >> ri;
PIChunkStream cs;
if (ri.types[PIIntrospection::itInfo])
cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo());
if (ri.types[PIIntrospection::itProcStat]) {
sysmon_mutex.lock();
cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon));
sysmon_mutex.unlock();
}
if (ri.types[PIIntrospection::itContainers])
cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers());
if (ri.types[PIIntrospection::itObjects])
cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects());
if (ri.types[PIIntrospection::itThreads])
cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads());
PIByteArray ba;
ba << PIIntrospection::sign;
ba.append(cs.data());
send(from, ba);
}
void PIIntrospectionServer::sysmonDeleted() {
PIMutexLocker _ml(sysmon_mutex);
sysmon = 0;
}
#endif // PIP_INTROSPECTION
/*
PIP - Platform Independent Primitives
Introspection module
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
# include "piintrospection_server.h"
# include "pichunkstream.h"
# include "piintrospection_server_p.h"
# include "piprocess.h"
PRIVATE_DEFINITION_START(PIIntrospectionServer)
PIIntrospection::ProcessInfo process_info;
PRIVATE_DEFINITION_END(PIIntrospectionServer)
PIIntrospectionServer::PIIntrospectionServer(): PIPeer(genName()) {
PRIVATE->process_info = PIIntrospection::getInfo();
sysmon = 0;
}
PIIntrospectionServer::~PIIntrospectionServer() {
PIPeer::stop();
if (sysmon)
if (sysmon->property("__iserver__").toBool()) delete sysmon;
sysmon = 0;
}
PIIntrospectionServer * PIIntrospectionServer::instance() {
static PIIntrospectionServer ret;
return &ret;
}
void PIIntrospectionServer::start(const PIString & server_name) {
if (!sysmon) {
sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID());
if (sysmon) {
piCoutObj << "using existing sysmon";
CONNECT1(void, PIObject *, sysmon, deleted, this, sysmonDeleted);
} else {
piCoutObj << "create own sysmon";
sysmon = new PISystemMonitor();
sysmon->setProperty("__iserver__", true);
sysmon->startOnSelf();
}
}
changeName(server_name + genName());
PIPeer::start();
}
PIString PIIntrospectionServer::genName() {
randomize();
return "__introspection__server_" + PIString::fromNumber(randomi() % 1000);
}
void PIIntrospectionServer::dataReceived(const PIString & from, const PIByteArray & data) {
if (data.size() < 8) return;
PIByteArray rba(data);
uint _sign(0);
rba >> _sign;
if (_sign != PIIntrospection::sign) return;
PIIntrospection::RequiredInfo ri;
rba >> ri;
PIChunkStream cs;
if (ri.types[PIIntrospection::itInfo]) cs.add(PIIntrospection::itInfo, PIIntrospection::packInfo());
if (ri.types[PIIntrospection::itProcStat]) {
sysmon_mutex.lock();
cs.add(PIIntrospection::itProcStat, PIIntrospection::packProcStat(sysmon));
sysmon_mutex.unlock();
}
if (ri.types[PIIntrospection::itContainers]) cs.add(PIIntrospection::itContainers, PIIntrospection::packContainers());
if (ri.types[PIIntrospection::itObjects]) cs.add(PIIntrospection::itObjects, PIIntrospection::packObjects());
if (ri.types[PIIntrospection::itThreads]) cs.add(PIIntrospection::itThreads, PIIntrospection::packThreads());
PIByteArray ba;
ba << PIIntrospection::sign;
ba.append(cs.data());
send(from, ba);
}
void PIIntrospectionServer::sysmonDeleted() {
PIMutexLocker _ml(sysmon_mutex);
sysmon = 0;
}
#endif // PIP_INTROSPECTION
@@ -1,77 +1,77 @@
/*! \file piintrospection_server.h
* \ingroup Introspection
* \~\brief
* \~english Introspection server
* \~russian Сервер интроспекции
*/
/*
PIP - Platform Independent Primitives
Introspection module
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINTROSPECTION_SERVER_H
#define PIINTROSPECTION_SERVER_H
#ifdef DOXYGEN
//! \ingroup Introspection
//! \~english Start introspection server with name "name"
//! \~russian Запускает сервер интроспекции с именем "name"
# define PIINTROSPECTION_START(name)
#else
# if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "pipeer.h"
class PIIntrospectionServer;
class PISystemMonitor;
# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance())
# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer);
public:
static PIIntrospectionServer * instance();
void start(const PIString & server_name);
private:
PIIntrospectionServer();
~PIIntrospectionServer();
NO_COPY_CLASS(PIIntrospectionServer);
PIString genName();
virtual void dataReceived(const PIString & from, const PIByteArray & data);
EVENT_HANDLER(void, sysmonDeleted);
PRIVATE_DECLARATION(PIP_EXPORT)
PITimer itimer;
PISystemMonitor * sysmon;
PIMutex sysmon_mutex;
};
# else
# define PIINTROSPECTION_START(name)
# endif
#endif // DOXYGEN
#endif // PIINTROSPECTION_SERVER_H
/*! \file piintrospection_server.h
* \ingroup Introspection
* \~\brief
* \~english Introspection server
* \~russian Сервер интроспекции
*/
/*
PIP - Platform Independent Primitives
Introspection module
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINTROSPECTION_SERVER_H
#define PIINTROSPECTION_SERVER_H
#ifdef DOXYGEN
//! \ingroup Introspection
//! \~english Start introspection server with name "name"
//! \~russian Запускает сервер интроспекции с именем "name"
# define PIINTROSPECTION_START(name)
#else
# if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
# include "pipeer.h"
class PIIntrospectionServer;
class PISystemMonitor;
# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance())
# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer);
public:
static PIIntrospectionServer * instance();
void start(const PIString & server_name);
private:
PIIntrospectionServer();
~PIIntrospectionServer();
NO_COPY_CLASS(PIIntrospectionServer);
PIString genName();
virtual void dataReceived(const PIString & from, const PIByteArray & data);
EVENT_HANDLER(void, sysmonDeleted);
PRIVATE_DECLARATION(PIP_EXPORT)
PITimer itimer;
PISystemMonitor * sysmon;
PIMutex sysmon_mutex;
};
# else
# define PIINTROSPECTION_START(name)
# endif
#endif // DOXYGEN
#endif // PIINTROSPECTION_SERVER_H
@@ -1,171 +1,170 @@
/*
PIP - Platform Independent Primitives
Introspection module - Base server structs
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piintrospection_server_p.h"
#include "pichunkstream.h"
#include "piinit.h"
#include "pisysteminfo.h"
#include "piobject.h"
const uint PIIntrospection::sign = 0x0F1C2B3A;
PIIntrospection::RequiredInfo::RequiredInfo() {
types = itInfo;
}
PIIntrospection::ProcessInfo::ProcessInfo() {
processorsCount = 0;
}
PIIntrospection::ObjectInfo::ObjectInfo() {
queued_events = 0;
}
PIIntrospection::ProcessInfo PIIntrospection::getInfo() {
PIIntrospection::ProcessInfo ret;
PISystemInfo * si = PISystemInfo::instance();
ret.architecture = si->architecture;
ret.execCommand = si->execCommand;
ret.execDateTime = si->execDateTime;
ret.hostname = si->hostname;
ret.OS_name = si->OS_name;
ret.OS_version = si->OS_version;
ret.processorsCount = si->processorsCount;
ret.user = si->user;
ret.build_options = PIInit::buildOptions();
return ret;
}
PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() {
PIVector<PIIntrospection::ObjectInfo> ret;
PIObject::mutexObjects().lock();
const PIVector<PIObject * > & ao(PIObject::objects());
ret.resize(ao.size());
for (int i = 0; i < ao.size_s(); ++i) {
ret[i].classname = PIStringAscii(ao[i]->className());
ret[i].name = ao[i]->name();
//ret[i].properties = ao[i]->properties();
ret[i].parents = ao[i]->scopeList();
ao[i]->mutex_queue.lock();
ret[i].queued_events = ao[i]->events_queue.size_s();
ao[i]->mutex_queue.unlock();
}
PIObject::mutexObjects().unlock();
return ret;
}
PIByteArray PIIntrospection::packInfo() {
PIByteArray ret;
ret << getInfo();
return ret;
}
void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) {
ba >> info;
}
PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) {
ProcessStat ps;
if (sm) {
ps.proc = sm->statistic();
ps.threads = sm->threadsStatistic();
}
PIByteArray ret;
ret << ps.proc << ps.threads;
return ret;
}
void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) {
ba >> info.proc >> info.threads;
}
PIByteArray PIIntrospection::packContainers() {
PIByteArray ret;
PIVector<PIIntrospectionContainers::TypeInfo> data;
PIIntrospectionContainers * p = 0;
#ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_CONTAINERS->p;
#endif
if (p) {
data = p->getInfo();
}
ret << data;
return ret;
}
void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector<PIIntrospectionContainers::TypeInfo> & data) {
data.clear();
ba >> data;
}
PIByteArray PIIntrospection::packThreads() {
PIByteArray ret;
PIIntrospectionThreads * p = 0;
#ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_THREADS->p;
#endif
if (p) {
p->mutex.lock();
PIMap<PIThread*, PIIntrospectionThreads::ThreadInfo> & tm(p->threads);
auto it = tm.makeIterator();
while (it.next()) {
it.value().classname = PIStringAscii(it.key()->className());
it.value().name = it.key()->name();
}
ret << tm.values();
p->mutex.unlock();
} else {
ret << PIVector<PIIntrospectionThreads::ThreadInfo>();
}
return ret;
}
void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector<PIIntrospectionThreads::ThreadInfo> & threads) {
threads.clear();
ba >> threads;
}
PIByteArray PIIntrospection::packObjects() {
PIByteArray ret;
ret << getObjects();
return ret;
}
void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector<PIIntrospection::ObjectInfo> & objects) {
objects.clear();
ba >> objects;
}
/*
PIP - Platform Independent Primitives
Introspection module - Base server structs
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piintrospection_server_p.h"
#include "pichunkstream.h"
#include "piinit.h"
#include "piobject.h"
#include "pisysteminfo.h"
const uint PIIntrospection::sign = 0x0F1C2B3A;
PIIntrospection::RequiredInfo::RequiredInfo() {
types = itInfo;
}
PIIntrospection::ProcessInfo::ProcessInfo() {
processorsCount = 0;
}
PIIntrospection::ObjectInfo::ObjectInfo() {
queued_events = 0;
}
PIIntrospection::ProcessInfo PIIntrospection::getInfo() {
PIIntrospection::ProcessInfo ret;
PISystemInfo * si = PISystemInfo::instance();
ret.architecture = si->architecture;
ret.execCommand = si->execCommand;
ret.execDateTime = si->execDateTime;
ret.hostname = si->hostname;
ret.OS_name = si->OS_name;
ret.OS_version = si->OS_version;
ret.processorsCount = si->processorsCount;
ret.user = si->user;
ret.build_options = PIInit::buildOptions();
return ret;
}
PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() {
PIVector<PIIntrospection::ObjectInfo> ret;
PIObject::mutexObjects().lock();
const PIVector<PIObject *> & ao(PIObject::objects());
ret.resize(ao.size());
for (int i = 0; i < ao.size_s(); ++i) {
ret[i].classname = PIStringAscii(ao[i]->className());
ret[i].name = ao[i]->name();
// ret[i].properties = ao[i]->properties();
ret[i].parents = ao[i]->scopeList();
ao[i]->mutex_queue.lock();
ret[i].queued_events = ao[i]->events_queue.size_s();
ao[i]->mutex_queue.unlock();
}
PIObject::mutexObjects().unlock();
return ret;
}
PIByteArray PIIntrospection::packInfo() {
PIByteArray ret;
ret << getInfo();
return ret;
}
void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) {
ba >> info;
}
PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) {
ProcessStat ps;
if (sm) {
ps.proc = sm->statistic();
ps.threads = sm->threadsStatistic();
}
PIByteArray ret;
ret << ps.proc << ps.threads;
return ret;
}
void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) {
ba >> info.proc >> info.threads;
}
PIByteArray PIIntrospection::packContainers() {
PIByteArray ret;
PIVector<PIIntrospectionContainers::TypeInfo> data;
PIIntrospectionContainers * p = 0;
#ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_CONTAINERS->p;
#endif
if (p) {
data = p->getInfo();
}
ret << data;
return ret;
}
void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector<PIIntrospectionContainers::TypeInfo> & data) {
data.clear();
ba >> data;
}
PIByteArray PIIntrospection::packThreads() {
PIByteArray ret;
PIIntrospectionThreads * p = 0;
#ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_THREADS->p;
#endif
if (p) {
p->mutex.lock();
PIMap<PIThread *, PIIntrospectionThreads::ThreadInfo> & tm(p->threads);
auto it = tm.makeIterator();
while (it.next()) {
it.value().classname = PIStringAscii(it.key()->className());
it.value().name = it.key()->name();
}
ret << tm.values();
p->mutex.unlock();
} else {
ret << PIVector<PIIntrospectionThreads::ThreadInfo>();
}
return ret;
}
void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector<PIIntrospectionThreads::ThreadInfo> & threads) {
threads.clear();
ba >> threads;
}
PIByteArray PIIntrospection::packObjects() {
PIByteArray ret;
ret << getObjects();
return ret;
}
void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector<PIIntrospection::ObjectInfo> & objects) {
objects.clear();
ba >> objects;
}
@@ -1,36 +1,35 @@
/*
PIP - Platform Independent Primitives
Introspection module - Base server structs
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - Base server structs
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINTROSPECTION_SERVER_P_H
#define PIINTROSPECTION_SERVER_P_H
#include "pichunkstream.h"
#include "piintrospection_containers.h"
#include "piintrospection_containers_p.h"
#include "piintrospection_threads.h"
#include "piintrospection_threads_p.h"
#include "pichunkstream.h"
#include "pisystemmonitor.h"
class PIP_EXPORT PIIntrospection {
public:
enum InfoTypes {
itInfo = 0x01,
itProcStat = 0x02,
@@ -89,7 +88,6 @@ public:
static PIByteArray packObjects();
static void unpackObjects(PIByteArray & ba, PIVector<PIIntrospection::ObjectInfo> & objects);
};
@@ -100,7 +98,8 @@ BINARY_STREAM_WRITE(PIIntrospection::RequiredInfo) {
return s;
}
BINARY_STREAM_READ(PIIntrospection::RequiredInfo) {
PIByteArray csba; s >> csba;
PIByteArray csba;
s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
@@ -113,13 +112,21 @@ BINARY_STREAM_READ(PIIntrospection::RequiredInfo) {
BINARY_STREAM_WRITE(PIIntrospection::ProcessInfo) {
PIChunkStream cs;
cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name)
.add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options);
cs.add(1, v.architecture)
.add(2, v.execCommand)
.add(3, v.execDateTime)
.add(4, v.hostname)
.add(5, v.OS_name)
.add(6, v.OS_version)
.add(7, v.processorsCount)
.add(8, v.user)
.add(9, v.build_options);
s << cs.data();
return s;
}
BINARY_STREAM_READ(PIIntrospection::ProcessInfo) {
PIByteArray csba; s >> csba;
PIByteArray csba;
s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
@@ -145,7 +152,8 @@ BINARY_STREAM_WRITE(PIIntrospection::ObjectInfo) {
return s;
}
BINARY_STREAM_READ(PIIntrospection::ObjectInfo) {
PIByteArray csba; s >> csba;
PIByteArray csba;
s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
@@ -1,26 +1,27 @@
/*
PIP - Platform Independent Primitives
Introspection module - interface for threads
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - interface for threads
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_threads.h"
#include "piintrospection_threads_p.h"
# include "piintrospection_threads.h"
# include "piintrospection_threads_p.h"
__PIINTROSPECTION_SINGLETON_CPP__(Threads)
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Introspection module - interface for threads
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - interface for threads
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINTROSPECTION_THREADS_H
@@ -26,17 +26,15 @@
class PIIntrospectionThreads;
# define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance())
# define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance())
// clang-format off
# define PIINTROSPECTION_THREAD_NEW (t ) PIINTROSPECTION_THREADS->threadNew (t );
# define PIINTROSPECTION_THREAD_DELETE (t ) PIINTROSPECTION_THREADS->threadDelete (t );
# define PIINTROSPECTION_THREAD_START (t ) PIINTROSPECTION_THREADS->threadStart (t );
# define PIINTROSPECTION_THREAD_RUN (t ) PIINTROSPECTION_THREADS->threadRun (t );
# define PIINTROSPECTION_THREAD_WAIT (t ) PIINTROSPECTION_THREADS->threadWait (t );
# define PIINTROSPECTION_THREAD_STOP (t ) PIINTROSPECTION_THREADS->threadStop (t );
# define PIINTROSPECTION_THREAD_RUN_DONE(t,us) PIINTROSPECTION_THREADS->threadRunDone(t,us);
// clang-format on
# define PIINTROSPECTION_THREAD_NEW(t) PIINTROSPECTION_THREADS->threadNew(t);
# define PIINTROSPECTION_THREAD_DELETE(t) PIINTROSPECTION_THREADS->threadDelete(t);
# define PIINTROSPECTION_THREAD_START(t) PIINTROSPECTION_THREADS->threadStart(t);
# define PIINTROSPECTION_THREAD_RUN(t) PIINTROSPECTION_THREADS->threadRun(t);
# define PIINTROSPECTION_THREAD_WAIT(t) PIINTROSPECTION_THREADS->threadWait(t);
# define PIINTROSPECTION_THREAD_STOP(t) PIINTROSPECTION_THREADS->threadStop(t);
# define PIINTROSPECTION_THREAD_RUN_DONE(t, us) PIINTROSPECTION_THREADS->threadRunDone(t, us);
class PIP_EXPORT PIIntrospectionThreadsInterface {
friend class PIIntrospection;
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Introspection module - implementation of threads
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - implementation of threads
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piintrospection_threads_p.h"
@@ -22,16 +22,13 @@
PIIntrospectionThreads::ThreadInfo::ThreadInfo() {
id = delay = 0;
state = sStopped;
priority = 0;
state = sStopped;
priority = 0;
run_us = run_count = 0U;
}
PIIntrospectionThreads::PIIntrospectionThreads() {
}
PIIntrospectionThreads::PIIntrospectionThreads() {}
void PIIntrospectionThreads::threadNew(PIThread * t) {
@@ -49,10 +46,10 @@ void PIIntrospectionThreads::threadDelete(PIThread * t) {
void PIIntrospectionThreads::threadStart(PIThread * t) {
PIMutexLocker _ml(mutex);
ThreadInfo & ti(threads[t]);
ti.id = t->tid();
ti.id = t->tid();
ti.priority = t->priority();
ti.delay = t->delay_;
ti.state = sStarting;
ti.delay = t->delay_;
ti.state = sStarting;
}
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Introspection module - implementation of threads
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Introspection module - implementation of threads
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINTROSPECTION_THREADS_P_H
+181 -158
View File
@@ -1,23 +1,24 @@
/*
PIP - Platform Independent Primitives
Class for write binary data to logfile, and read or playback this data
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Class for write binary data to logfile, and read or playback this data
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pibinarylog.h"
#include "pidir.h"
#include "pipropertystorage.h"
@@ -45,9 +46,9 @@
*
*/
static const uchar binlog_sig[] = {'B','I','N','L','O','G'};
static const uchar binlog_sig[] = {'B', 'I', 'N', 'L', 'O', 'G'};
#define PIBINARYLOG_VERSION 0x32
#define PIBINARYLOG_VERSION 0x32
#define PIBINARYLOG_SIGNATURE_SIZE sizeof(binlog_sig)
REGISTER_DEVICE(PIBinaryLog)
@@ -59,9 +60,9 @@ PIBinaryLog::PIBinaryLog() {
setThreadedReadBufferSize(65536);
#endif
is_started = is_indexed = is_pause = false;
current_index = -1;
log_size = 0;
f_new_path = nullptr;
current_index = -1;
log_size = 0;
f_new_path = nullptr;
setPlaySpeed(1.);
setDefaultID(1);
setPlaySpeed(1.0);
@@ -75,7 +76,7 @@ PIBinaryLog::PIBinaryLog() {
setFilePrefix(PIString());
setRapidStart(false);
file.setName("__S__PIBinaryLog::file");
// piCoutObj << "created";
// piCoutObj << "created";
}
@@ -87,12 +88,12 @@ PIBinaryLog::~PIBinaryLog() {
bool PIBinaryLog::openDevice() {
lastrecord.timestamp = PISystemTime();
lastrecord.id = 0;
write_count = 0;
is_started = false;
is_thread_ok = true;
is_indexed = false;
is_pause = false;
lastrecord.id = 0;
write_count = 0;
is_started = false;
is_thread_ok = true;
is_indexed = false;
is_pause = false;
index.clear();
index_pos.clear();
log_size = 0;
@@ -101,14 +102,16 @@ bool PIBinaryLog::openDevice() {
return false;
}
if (path().isEmpty() && mode_ == WriteOnly) {
if (f_new_path) setPath(f_new_path());
else setPath(getLogfilePath(logDir(), filePrefix()));
if (f_new_path)
setPath(f_new_path());
else
setPath(getLogfilePath(logDir(), filePrefix()));
}
if (path().isEmpty() && mode_ == ReadOnly) {
PIDir ld(logDir());
if (ld.isExists()) {
PIVector<PIFile::FileInfo> es = ld.allEntries();
piForeachC(PIFile::FileInfo &i, es) {
piForeachC(PIFile::FileInfo & i, es) {
if (i.extension() == "binlog" && i.isFile() && i.baseName().startsWith(filePrefix())) {
setPath(i.path);
break;
@@ -147,7 +150,7 @@ bool PIBinaryLog::openDevice() {
if (!rapid_start) is_started = true;
}
startlogtime = PISystemTime::current();
pause_time = PISystemTime();
pause_time = PISystemTime();
return true;
}
@@ -160,7 +163,7 @@ bool PIBinaryLog::closeDevice() {
is_indexed = false;
index.clear();
index_pos.clear();
bool e = isEmpty();
bool e = isEmpty();
log_size = 0;
if (canWrite() && e) {
file.remove();
@@ -170,8 +173,8 @@ bool PIBinaryLog::closeDevice() {
}
bool PIBinaryLog::threadedRead(const uchar *readed, ssize_t size) {
// piCout << "binlog threaded read";
bool PIBinaryLog::threadedRead(const uchar * readed, ssize_t size) {
// piCout << "binlog threaded read";
if (!canRead() || isEnd()) return PIIODevice::threadedRead(readed, size);
is_thread_ok = false;
logmutex.lock();
@@ -192,16 +195,15 @@ bool PIBinaryLog::threadedRead(const uchar *readed, ssize_t size) {
pausemutex.unlock();
pt = PISystemTime::current() - startlogtime;
if (is_started) {
if (lastrec_timestamp > pt)
(lastrec_timestamp - pt).sleep();
if (lastrec_timestamp > pt) (lastrec_timestamp - pt).sleep();
} else {
startlogtime = PISystemTime::current() - lastrec_timestamp;
is_started = true;
is_started = true;
}
break;
case PlayVariableSpeed:
delay = lastrec_timestamp.toMilliseconds() - play_time;
//piCoutObj << "delay" << delay;
// piCoutObj << "delay" << delay;
double cdelay;
int dtc;
if (is_started) {
@@ -210,36 +212,40 @@ bool PIBinaryLog::threadedRead(const uchar *readed, ssize_t size) {
return false;
}
if (delay > 0) {
cdelay = delay * play_speed;// TODO: rewrite with condvar
dtc = int(cdelay) / 100;// TODO: rewrite with condvar
cdelay = delay * play_speed; // TODO: rewrite with condvar
dtc = int(cdelay) / 100; // TODO: rewrite with condvar
if (play_speed <= 0.) dtc = 2;
//piCout << play_speed << dtc;
for (int j=0; j<dtc; j++) {
cdelay = delay * play_speed;// TODO: rewrite with condvar
dtc = int(cdelay) / 100;// TODO: rewrite with condvar
piMSleep(100);// TODO: rewrite with condvar
if (play_speed <= 0.) {dtc = 2; j = 0;}
//piCout << " " << play_speed << dtc << j;
// piCout << play_speed << dtc;
for (int j = 0; j < dtc; j++) {
cdelay = delay * play_speed; // TODO: rewrite with condvar
dtc = int(cdelay) / 100; // TODO: rewrite with condvar
piMSleep(100); // TODO: rewrite with condvar
if (play_speed <= 0.) {
dtc = 2;
j = 0;
}
// piCout << " " << play_speed << dtc << j;
}
cdelay = cdelay - dtc*100;// TODO: rewrite with condvar
cdelay = cdelay - dtc * 100; // TODO: rewrite with condvar
PISystemTime::fromMilliseconds(cdelay).sleep();
}
} else is_started = true;
} else
is_started = true;
play_time = lastrec_timestamp.toMilliseconds();
break;
case PlayStaticDelay:
if (is_started) {
if (is_pause) {
piMSleep(100);// TODO: rewrite with condvar
piMSleep(100); // TODO: rewrite with condvar
return false;
}
play_delay.sleep();
} else is_started = true;
} else
is_started = true;
break;
default:
return false;
default: return false;
}
bool res = PIIODevice::threadedRead(readed, size);
bool res = PIIODevice::threadedRead(readed, size);
is_thread_ok = true;
return res;
}
@@ -249,12 +255,13 @@ PIString PIBinaryLog::getLogfilePath(const PIString & log_dir, const PIString &
PIDir dir(log_dir);
dir.setDir(dir.absolutePath());
if (!dir.isExists()) {
piCout << "[PIBinaryLog]" << "Creating directory" << dir.path();
piCout << "[PIBinaryLog]"
<< "Creating directory" << dir.path();
dir.make(true);
}
PIString npath = log_dir + PIDir::separator + prefix + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss");
PIString npath = log_dir + PIDir::separator + prefix + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss");
PIString cnpath = npath + ".binlog";
int i = 1;
int i = 1;
while (PIFile::isExists(cnpath)) {
cnpath = npath + '_' + PIString::fromNumber(i) + ".binlog";
i++;
@@ -265,8 +272,10 @@ PIString PIBinaryLog::getLogfilePath(const PIString & log_dir, const PIString &
PIString PIBinaryLog::createNewFile() {
if (!file.close()) return PIString();
PIString cnpath;
if (f_new_path) cnpath = f_new_path();
else cnpath = getLogfilePath(logDir(), filePrefix());
if (f_new_path)
cnpath = f_new_path();
else
cnpath = getLogfilePath(logDir(), filePrefix());
if (open(cnpath, PIIODevice::WriteOnly)) {
newFile(file.path());
return file.path();
@@ -276,27 +285,27 @@ PIString PIBinaryLog::createNewFile() {
}
void PIBinaryLog::createNewFile(const PIString &path) {
void PIBinaryLog::createNewFile(const PIString & path) {
if (open(path, PIIODevice::WriteOnly)) {
newFile(file.path());
}
else piCoutObj << "Can't create new file, maybe path" << ("\"" + path + "\"") << "is invalid.";
} else
piCoutObj << "Can't create new file, maybe path" << ("\"" + path + "\"") << "is invalid.";
}
void PIBinaryLog::setPause(bool pause) {
pausemutex.lock();
is_pause = pause;
if (pause) pause_time = PISystemTime::current();
if (pause)
pause_time = PISystemTime::current();
else {
if (pause_time > PISystemTime())
pause_time = PISystemTime::current() - pause_time;
if (pause_time > PISystemTime()) pause_time = PISystemTime::current() - pause_time;
}
pausemutex.unlock();
}
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 (id == 0) {
piCoutObj << "Error: can`t write with id = 0! Id must be > 0";
@@ -323,12 +332,14 @@ int PIBinaryLog::writeBinLog(int id, const void *data, int size) {
default: break;
}
logmutex.unlock();
if (res > 0) return size;
else return res;
if (res > 0)
return size;
else
return res;
}
int PIBinaryLog::writeBinLog_raw(int id, const PISystemTime &time, const void *data, int size) {
int PIBinaryLog::writeBinLog_raw(int id, const PISystemTime & time, const void * data, int size) {
if (size <= 0 || !canWrite()) return -1;
PIByteArray logdata;
logdata << id << size << time << PIMemoryBlock(data, size);
@@ -338,8 +349,10 @@ int PIBinaryLog::writeBinLog_raw(int id, const PISystemTime &time, const void *d
write_count++;
log_size = file.size();
logmutex.unlock();
if (res > 0) return size;
else return res;
if (res > 0)
return size;
else
return res;
}
@@ -359,7 +372,8 @@ PIByteArray PIBinaryLog::readBinLog(int id, PISystemTime * time, int * readed_id
return br.data;
}
logmutex.lock();
while (br.id != id && !isEnd()) br = readRecord();
while (br.id != id && !isEnd())
br = readRecord();
logmutex.unlock();
if (br.id == -1) {
piCoutObj << "End of BinLog file";
@@ -376,7 +390,7 @@ PIByteArray PIBinaryLog::readBinLog(int id, PISystemTime * time, int * readed_id
}
int PIBinaryLog::readBinLog(int id, void *read_to, int max_size, PISystemTime * time, int * readed_id) {
int PIBinaryLog::readBinLog(int id, void * read_to, int max_size, PISystemTime * time, int * readed_id) {
if (max_size <= 0 || read_to == 0) return -1;
PIByteArray ba = readBinLog(id, time, readed_id);
if (ba.isEmpty()) return -1;
@@ -401,10 +415,10 @@ PIByteArray PIBinaryLog::getHeader() {
}
ssize_t PIBinaryLog::readDevice(void *read_to, ssize_t max_size) {
ssize_t PIBinaryLog::readDevice(void * read_to, ssize_t max_size) {
PIMutexLocker _ml(logmutex);
if (lastrecord.id == -1 || isEnd()) return 0;
if(!is_thread_ok && lastrecord.id > 0) return lastrecord.data.size();
if (!is_thread_ok && lastrecord.id > 0) return lastrecord.data.size();
if (!canRead()) return -1;
if (max_size <= 0 || read_to == 0) return -1;
BinLogRecord br;
@@ -412,7 +426,8 @@ ssize_t PIBinaryLog::readDevice(void *read_to, ssize_t max_size) {
if (filterID.isEmpty()) {
br = readRecord();
} else {
while (!filterID.contains(br.id) && !isEnd()) br = readRecord();
while (!filterID.contains(br.id) && !isEnd())
br = readRecord();
}
if (br.id == -1) {
fileEnd();
@@ -441,10 +456,10 @@ void PIBinaryLog::restart() {
if (!canRead()) return;
logmutex.unlock();
lastrecord.timestamp = PISystemTime();
lastrecord.id = 0;
is_thread_ok = true;
is_started = !rapidStart();
play_time = 0;
lastrecord.id = 0;
is_thread_ok = true;
is_started = !rapidStart();
play_time = 0;
file.seekToBegin();
checkFileHeader();
moveIndex(0);
@@ -468,10 +483,11 @@ bool PIBinaryLog::writeFileHeader() {
bool PIBinaryLog::checkFileHeader() {
binfo.user_header.clear();
uchar read_sig[PIBINARYLOG_SIGNATURE_SIZE];
for (uint i=0; i<PIBINARYLOG_SIGNATURE_SIZE; i++) read_sig[i] = 0;
for (uint i = 0; i < PIBINARYLOG_SIGNATURE_SIZE; i++)
read_sig[i] = 0;
if (file.read(read_sig, PIBINARYLOG_SIGNATURE_SIZE) < 0) return false;
bool correct = true;
for (uint i=0; i<PIBINARYLOG_SIGNATURE_SIZE; i++)
for (uint i = 0; i < PIBINARYLOG_SIGNATURE_SIZE; i++)
if (read_sig[i] != binlog_sig[i]) correct = false;
if (!correct) {
piCoutObj << "BinLogFile signature is corrupted or invalid file";
@@ -484,7 +500,7 @@ bool PIBinaryLog::checkFileHeader() {
return true;
}
if (read_version == PIBINARYLOG_VERSION) {
log_size = file.size();
log_size = file.size();
uint32_t sz = 0;
file.read(&sz, 4);
if (sz > 0) {
@@ -492,18 +508,15 @@ bool PIBinaryLog::checkFileHeader() {
}
return true;
}
if (read_version == 0)
piCoutObj << "BinLogFile has invalid version";
if (read_version < PIBINARYLOG_VERSION)
piCoutObj << "BinLogFile has too old verion";
if (read_version > PIBINARYLOG_VERSION)
piCoutObj << "BinLogFile has too newest version";
if (read_version == 0) piCoutObj << "BinLogFile has invalid version";
if (read_version < PIBINARYLOG_VERSION) piCoutObj << "BinLogFile has too old verion";
if (read_version > PIBINARYLOG_VERSION) piCoutObj << "BinLogFile has too newest version";
return false;
}
PIBinaryLog::BinLogRecord PIBinaryLog::readRecord() {
// piCoutObj << "readRecord";
// piCoutObj << "readRecord";
logmutex.lock();
PIByteArray ba;
BinLogRecord br;
@@ -511,33 +524,35 @@ PIBinaryLog::BinLogRecord PIBinaryLog::readRecord() {
lastrecord.data.clear();
lastrecord.timestamp = PISystemTime();
ba.resize(sizeof(BinLogRecord) - sizeof(PIByteArray));
if(file.read(ba.data(), ba.size_s()) > 0) {
if (file.read(ba.data(), ba.size_s()) > 0) {
ba >> br.id >> br.size >> br.timestamp;
} else {
br.id = -1;
logmutex.unlock();
// piCoutObj << "readRecord done";
// piCoutObj << "readRecord done";
return br;
}
if (br.id > 0 && br.size > 0) {
ba.resize(br.size);
if(file.read(ba.data(), ba.size_s()) > 0) br.data = ba;
else br.id = 0;
} else br.id = 0;
if (file.read(ba.data(), ba.size_s()) > 0)
br.data = ba;
else
br.id = 0;
} else
br.id = 0;
lastrecord = br;
if (br.id == 0) fileError();
moveIndex(index_pos.value(file.pos(), -1));
logmutex.unlock();
// piCoutObj << "readRecord done";
// piCoutObj << "readRecord done";
return br;
}
void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<PIBinaryLog::BinLogIndex> * index) {
if (!info && !index) return;
if (info) {
info->log_size = -1;
info->log_size = -1;
info->records_count = 0;
info->records.clear();
}
@@ -545,16 +560,17 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
if (f == 0) return;
if (!f->canRead()) return;
if (info) {
info->path = f->path();
info->path = f->path();
info->log_size = f->size();
}
uchar read_sig[PIBINARYLOG_SIGNATURE_SIZE];
for (uint i=0; i<PIBINARYLOG_SIGNATURE_SIZE; i++) read_sig[i] = 0;
for (uint i = 0; i < PIBINARYLOG_SIGNATURE_SIZE; i++)
read_sig[i] = 0;
if (f->read(read_sig, PIBINARYLOG_SIGNATURE_SIZE) < 0) {
if (info) info->records_count = -1;
return;
}
for (uint i=0; i<PIBINARYLOG_SIGNATURE_SIZE; i++) {
for (uint i = 0; i < PIBINARYLOG_SIGNATURE_SIZE; i++) {
if (read_sig[i] != binlog_sig[i]) {
if (info) info->records_count = -2;
return;
@@ -565,7 +581,7 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
if (info) info->records_count = -3;
return;
}
if (read_version == 0) {
if (read_version == 0) {
if (info) info->records_count = -4;
return;
}
@@ -586,9 +602,9 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
}
PIByteArray ba;
BinLogRecord br;
br.id = 0;
br.size = 0;
bool first = true;
br.id = 0;
br.size = 0;
bool first = true;
size_t hdr_size = sizeof(BinLogRecord) - sizeof(PIByteArray);
ba.resize(hdr_size);
while (1) {
@@ -596,20 +612,21 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
{
if (f->read(ba.data(), ba.size()) > 0) {
ba >> br.id >> br.size >> br.timestamp;
} else break;
} else
break;
if (info) {
if (info->log_size - f->pos() >= br.size) {
f->seek(f->pos() + br.size);
}
}
else break;
} else
break;
}
if (br.id > 0) {
if (index) {
BinLogIndex bl_ind;
bl_ind.id = br.id;
bl_ind.id = br.id;
bl_ind.data_size = br.size;
bl_ind.pos = f->pos() - br.size - hdr_size;
bl_ind.pos = f->pos() - br.size - hdr_size;
bl_ind.timestamp = br.timestamp;
index->append(bl_ind);
}
@@ -617,14 +634,14 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
info->records_count++;
if (first) {
info->start_time = br.timestamp;
first = false;
first = false;
}
BinLogRecordInfo &bri(info->records[br.id]);
BinLogRecordInfo & bri(info->records[br.id]);
bri.count++;
if (bri.id == 0) {
bri.id = br.id;
bri.id = br.id;
bri.minimum_size = bri.maximum_size = br.size;
bri.start_time = br.timestamp;
bri.start_time = br.timestamp;
} else {
bri.end_time = br.timestamp;
if (bri.minimum_size > br.size) bri.minimum_size = br.size;
@@ -647,7 +664,7 @@ void PIBinaryLog::moveIndex(int i) {
PIBinaryLog::BinLogInfo PIBinaryLog::getLogInfo(const PIString & path) {
BinLogInfo bi;
bi.path = path;
bi.path = path;
bi.records_count = 0;
PIFile tfile;
if (!tfile.open(path, PIIODevice::ReadOnly)) return bi;
@@ -659,7 +676,8 @@ PIBinaryLog::BinLogInfo PIBinaryLog::getLogInfo(const PIString & path) {
bool PIBinaryLog::cutBinLog(const PIBinaryLog::BinLogInfo & src, const PIString & dst, int from, int to) {
PIBinaryLog slog;
if (!slog.open(src.path, PIIODevice::ReadOnly)) {
piCout << "[PIBinaryLog]" << "Error, can't open" << src.path;
piCout << "[PIBinaryLog]"
<< "Error, can't open" << src.path;
return false;
}
PIVector<int> ids = src.records.keys();
@@ -667,7 +685,8 @@ bool PIBinaryLog::cutBinLog(const PIBinaryLog::BinLogInfo & src, const PIString
PIBinaryLog dlog;
dlog.createNewFile(dst);
if (!dlog.isOpened()) {
piCout << "[PIBinaryLog]" << "Error, can't create" << dst;
piCout << "[PIBinaryLog]"
<< "Error, can't create" << dst;
return false;
}
bool first = true;
@@ -677,34 +696,39 @@ bool PIBinaryLog::cutBinLog(const PIBinaryLog::BinLogInfo & src, const PIString
while (!slog.isEnd() && ((slog.pos() <= to) || to < 0)) {
br = slog.readRecord();
if (first) {
st = br.timestamp;
st = br.timestamp;
first = false;
}
if (ids.contains(br.id)) {
if (dlog.writeBinLog_raw(br.id, br.timestamp - st, br.data) <= 0) {
piCout << "[PIBinaryLog]" << "Error, can't write to file" << dst;
piCout << "[PIBinaryLog]"
<< "Error, can't write to file" << dst;
return false;
}
}
}
if (tm.elapsed_s() > 1) {
tm.reset();
piCout << "[PIBinaryLog]" << "process" << PITime::fromSystemTime(br.timestamp).toString();
piCout << "[PIBinaryLog]"
<< "process" << PITime::fromSystemTime(br.timestamp).toString();
}
}
return true;
}
bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src, const PIString & dst, std::function<bool (const PIString &, PISystemTime)> progress) {
bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src,
const PIString & dst,
std::function<bool(const PIString &, PISystemTime)> progress) {
PIBinaryLog slog;
PIBinaryLog dlog;
PISystemTime dtime;
PISystemTime lt;
PITimeMeasurer tm;
bool first = true;
for (const PIString & fn : src) {
for (const PIString & fn: src) {
if (!slog.open(fn, PIIODevice::ReadOnly)) {
piCout << "[PIBinaryLog]" << "Error, can't open" << fn;
piCout << "[PIBinaryLog]"
<< "Error, can't open" << fn;
return false;
}
if (first) {
@@ -712,10 +736,12 @@ bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src, const PIString & d
dlog.setHeader(slog.getHeader());
dlog.createNewFile(dst);
if (!dlog.isOpened()) {
piCout << "[PIBinaryLog]" << "Error, can't create" << dst;
piCout << "[PIBinaryLog]"
<< "Error, can't create" << dst;
return false;
}
piCout << "[PIBinaryLog]" << "Start join binlogs to" << dst;
piCout << "[PIBinaryLog]"
<< "Start join binlogs to" << dst;
} else {
dtime = lt;
}
@@ -728,7 +754,8 @@ bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src, const PIString & d
st = br.timestamp;
lt = dtime + br.timestamp;
if (dlog.writeBinLog_raw(br.id, lt, br.data) <= 0) {
piCout << "[PIBinaryLog]" << "Error, can't write to file" << dst;
piCout << "[PIBinaryLog]"
<< "Error, can't write to file" << dst;
return false;
}
if (tm.elapsed_s() > 0.1) {
@@ -741,14 +768,16 @@ bool PIBinaryLog::joinBinLogsSerial(const PIStringList & src, const PIString & d
return false;
}
} else {
piCout << "[PIBinaryLog]" << "process" << PITime::fromSystemTime(lt).toString();
piCout << "[PIBinaryLog]"
<< "process" << PITime::fromSystemTime(lt).toString();
}
}
}
slog.close();
//piCout << "[PIBinaryLog]" << "complete" << fn;
// piCout << "[PIBinaryLog]" << "complete" << fn;
}
piCout << "[PIBinaryLog]" << "Finish join binlogs, total time" << PITime::fromSystemTime(lt).toString();
piCout << "[PIBinaryLog]"
<< "Finish join binlogs, total time" << PITime::fromSystemTime(lt).toString();
return true;
}
@@ -762,7 +791,8 @@ bool PIBinaryLog::createIndex() {
parseLog(&file, &binfo, &index);
file.seek(cp);
is_indexed = !index.isEmpty();
for (uint i=0; i<index.size(); i++) index_pos[index[i].pos] = i;
for (uint i = 0; i < index.size(); i++)
index_pos[index[i].pos] = i;
logmutex.unlock();
return is_indexed;
}
@@ -781,20 +811,20 @@ int PIBinaryLog::posForTime(const PISystemTime & time) {
void PIBinaryLog::seekTo(int rindex) {
// piCoutObj << "seekTo";
// piCoutObj << "seekTo";
logmutex.lock();
pausemutex.lock();
if (rindex < index.size_s() && rindex >= 0) {
file.seek(index[rindex].pos);
moveIndex(index_pos.value(file.pos(), -1));
//double prev_pt = play_time;
play_time = index[rindex].timestamp.toMilliseconds();
// double prev_pt = play_time;
play_time = index[rindex].timestamp.toMilliseconds();
lastrecord.timestamp = index[rindex].timestamp;
if (play_mode == PlayRealTime) {
startlogtime = PISystemTime::current() - lastrecord.timestamp;
}
}
// piCoutObj << "seekTo done";
// piCoutObj << "seekTo done";
pausemutex.unlock();
logmutex.unlock();
}
@@ -812,7 +842,7 @@ bool PIBinaryLog::seek(const PISystemTime & time) {
bool PIBinaryLog::seek(llong filepos) {
int ci = -1;
for (uint i=0; i<index.size(); i++) {
for (uint i = 0; i < index.size(); i++) {
if (filepos <= index[i].pos && (filterID.contains(index[i].id) || filterID.isEmpty())) {
ci = i;
break;
@@ -830,18 +860,10 @@ PIString PIBinaryLog::constructFullPathDevice() const {
PIString ret;
ret += logDir() + ":" + filePrefix() + ":" + PIString::fromNumber(defaultID()) + ":";
switch (play_mode) {
case PlayRealTime:
ret += "RT";
break;
case PlayVariableSpeed:
ret += PIString::fromNumber(playSpeed()) + "X";
break;
case PlayStaticDelay:
ret += PIString::fromNumber(playDelay().toMilliseconds()) + "M";
break;
default:
ret += "RT";
break;
case PlayRealTime: ret += "RT"; break;
case PlayVariableSpeed: ret += PIString::fromNumber(playSpeed()) + "X"; break;
case PlayStaticDelay: ret += PIString::fromNumber(playDelay().toMilliseconds()) + "M"; break;
default: ret += "RT"; break;
}
return ret;
}
@@ -859,7 +881,7 @@ void PIBinaryLog::configureFromFullPathDevice(const PIString & full_path) {
if (p.toUpperCase() == "RT") setPlayRealTime();
if (p.toUpperCase().right(1) == "X") setPlaySpeed((p.left(p.size() - 1)).toDouble());
if (p.toUpperCase().right(1) == "M") setPlayDelay(PISystemTime::fromMilliseconds((p.left(p.size() - 1)).toDouble()));
break;
break;
}
}
// piCoutObj << "configured";
@@ -872,7 +894,9 @@ PIPropertyStorage PIBinaryLog::constructVariantDevice() const {
ret.addProperty("log dir", PIVariantTypes::Dir(logDir()));
ret.addProperty("file prefix", filePrefix());
ret.addProperty("default ID", defaultID());
e << "real-time" << "variable speed" << "static delay";
e << "real-time"
<< "variable speed"
<< "static delay";
e.selectValue((int)playMode());
ret.addProperty("play mode", e);
ret.addProperty("play speed", playSpeed());
@@ -892,16 +916,15 @@ void PIBinaryLog::configureFromVariantDevice(const PIPropertyStorage & d) {
void PIBinaryLog::propertyChanged(const char * s) {
default_id = property("defaultID").toInt();
default_id = property("defaultID").toInt();
rapid_start = property("rapidStart").toBool();
play_mode = (PlayMode)property("playMode").toInt();
double ps = property("playSpeed").toDouble();
play_speed = ps > 0. ? 1. / ps : 0.;
play_delay = property("playDelay").toSystemTime();
split_mode = (SplitMode)property("splitMode").toInt();
split_time = property("splitTime").toSystemTime();
split_size = property("splitFileSize").toLLong();
play_mode = (PlayMode)property("playMode").toInt();
double ps = property("playSpeed").toDouble();
play_speed = ps > 0. ? 1. / ps : 0.;
play_delay = property("playDelay").toSystemTime();
split_mode = (SplitMode)property("splitMode").toInt();
split_time = property("splitTime").toSystemTime();
split_size = property("splitFileSize").toLLong();
split_count = property("splitRecordCount").toInt();
// piCoutObj << "propertyChanged" << s << play_mode;
// piCoutObj << "propertyChanged" << s << play_mode;
}
+126 -97
View File
@@ -5,22 +5,22 @@
* \~russian Бинарный лог
*/
/*
PIP - Platform Independent Primitives
Class for write binary data to logfile, and read or playback this data
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Class for write binary data to logfile, and read or playback this data
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIBINARYLOG_H
@@ -32,32 +32,32 @@
//! \~\brief
//! \~english Binary log
//! \~russian Бинарный лог
class PIP_EXPORT PIBinaryLog: public PIIODevice
{
class PIP_EXPORT PIBinaryLog: public PIIODevice {
PIIODEVICE(PIBinaryLog, "binlog");
public:
explicit PIBinaryLog();
virtual ~PIBinaryLog();
//! \brief Play modes for \a PIBinaryLog
enum PlayMode {
PlayRealTime /*! Play in system realtime, default mode */ ,
PlayVariableSpeed /*! Play in software realtime with speed, set by \a setSpeed */ ,
PlayStaticDelay /*! Play with custom static delay, ignoring timestamp */
PlayRealTime /*! Play in system realtime, default mode */,
PlayVariableSpeed /*! Play in software realtime with speed, set by \a setSpeed */,
PlayStaticDelay /*! Play with custom static delay, ignoring timestamp */
};
//! \brief Different split modes for writing \a PIBinaryLog, which can separate files by size, by time or by records count
enum SplitMode {
SplitNone /*! Without separate, default mode */ ,
SplitTime /*! Separate files by record time */ ,
SplitSize /*! Separate files by size */ ,
SplitCount /*! Separate files by records count */
SplitNone /*! Without separate, default mode */,
SplitTime /*! Separate files by record time */,
SplitSize /*! Separate files by size */,
SplitCount /*! Separate files by records count */
};
//! \brief Struct contains information about all records with same ID
struct PIP_EXPORT BinLogRecordInfo {
BinLogRecordInfo() {
id = count = 0;
id = count = 0;
minimum_size = maximum_size = 0;
}
int id;
@@ -89,81 +89,96 @@ public:
//! Current \a PlayMode
PlayMode playMode() const {return play_mode;}
PlayMode playMode() const { return play_mode; }
//! Current \a SplitMode
SplitMode splitMode() const {return split_mode;}
SplitMode splitMode() const { return split_mode; }
//! Current directory where billogs wiil be saved
PIString logDir() const {return property("logDir").toString();}
PIString logDir() const { return property("logDir").toString(); }
//! Returns current file prefix
PIString filePrefix() const {return property("filePrefix").toString();}
PIString filePrefix() const { return property("filePrefix").toString(); }
//! Default ID, used in \a write function
int defaultID() const {return default_id;}
int defaultID() const { return default_id; }
//! Returns current play speed
double playSpeed() const {return play_speed > 0 ? 1. / play_speed : 0.;}
double playSpeed() const { return play_speed > 0 ? 1. / play_speed : 0.; }
//! Returns current play delay
PISystemTime playDelay() const {return play_delay;}
PISystemTime playDelay() const { return play_delay; }
//! Returns current binlog file split time
PISystemTime splitTime() const {return split_time;}
PISystemTime splitTime() const { return split_time; }
//! Returns current binlog file split size
llong splitFileSize() const {return split_size;}
llong splitFileSize() const { return split_size; }
//! Returns current binlog file split records count
int splitRecordCount() const {return split_count;}
int splitRecordCount() const { return split_count; }
//! Returns if rapid start enabled
bool rapidStart() const {return rapid_start;}
bool rapidStart() const { return rapid_start; }
//! Create binlog file with Filename = path
void createNewFile(const PIString &path);
void createNewFile(const PIString & path);
//! Set \a PlayMode
void setPlayMode(PlayMode mode) {setProperty("playMode", (int)mode);}
void setPlayMode(PlayMode mode) { setProperty("playMode", (int)mode); }
//! Set \a SplitMode
void setSplitMode(SplitMode mode) {setProperty("splitMode", (int)mode);}
void setSplitMode(SplitMode mode) { setProperty("splitMode", (int)mode); }
//! Set path to directory where binlogs will be saved
void setLogDir(const PIString & path) {setProperty("logDir", path);}
void setLogDir(const PIString & path) { setProperty("logDir", path); }
//! Set file prefix, used to
void setFilePrefix(const PIString & prefix) {setProperty("filePrefix", prefix);}
void setFilePrefix(const PIString & prefix) { setProperty("filePrefix", prefix); }
//! Set defaultID, used in \a write function
void setDefaultID(int id) {setProperty("defaultID", id);}
void setDefaultID(int id) { setProperty("defaultID", id); }
//! If enabled BinLog \a ThreadedRead starts without delay for first record, i.e. first record will be readed immediately
void setRapidStart(bool enabled) {setProperty("rapidStart", enabled);}
void setRapidStart(bool enabled) { setProperty("rapidStart", enabled); }
//! Set play speed to "speed", default value is 1.0x
//! Also this function set \a playMode to \a PlayVariableSpeed
void setPlaySpeed(double speed) {setPlayMode(PlayVariableSpeed); setProperty("playSpeed", speed);}
void setPlaySpeed(double speed) {
setPlayMode(PlayVariableSpeed);
setProperty("playSpeed", speed);
}
//! Setting static delay between records, default value is 1 sec
//! Also this function set \a playMode to \a PlayStaticDelay
void setPlayDelay(const PISystemTime & delay) {setPlayMode(PlayStaticDelay); setProperty("playDelay", delay);}
void setPlayDelay(const PISystemTime & delay) {
setPlayMode(PlayStaticDelay);
setProperty("playDelay", delay);
}
//! Set \a playMode to \a PlayRealTime
void setPlayRealTime() {setPlayMode(PlayRealTime);}
void setPlayRealTime() { setPlayMode(PlayRealTime); }
//! Set binlog file split time
//! Also this function set \a splitMode to \a SplitTime
void setSplitTime(const PISystemTime & time) {setSplitMode(SplitTime); setProperty("splitTime", time);}
void setSplitTime(const PISystemTime & time) {
setSplitMode(SplitTime);
setProperty("splitTime", time);
}
//! Set binlog file split size
//! Also this function set \a splitMode to \a SplitSize
void setSplitFileSize(llong size) {setSplitMode(SplitSize); setProperty("splitFileSize", size);}
void setSplitFileSize(llong size) {
setSplitMode(SplitSize);
setProperty("splitFileSize", size);
}
//! Set binlog file split records count
//! Also this function set \a splitMode to \a SplitCount
void setSplitRecordCount(int count) {setSplitMode(SplitCount); setProperty("splitRecordCount", count);}
void setSplitRecordCount(int count) {
setSplitMode(SplitCount);
setProperty("splitRecordCount", count);
}
//! Set pause while playing via \a threadedRead or writing via write
void setPause(bool pause);
@@ -171,82 +186,90 @@ public:
//! Set function wich returns new binlog file path when using split mode.
//! Overrides internal file path generator (logdir() + prefix() + current_time()).
//! To restore internal file path generator set this function to "nullptr".
void setFuncGetNewFilePath(std::function<PIString()> f) {f_new_path = f;}
void setFuncGetNewFilePath(std::function<PIString()> f) { f_new_path = f; }
//! Write one record to BinLog file, with ID = id, id must be greather than 0
int writeBinLog(int id, PIByteArray data) {return writeBinLog(id, data.data(), data.size_s());}
int writeBinLog(int id, PIByteArray data) { return writeBinLog(id, data.data(), data.size_s()); }
//! Write one record to BinLog file, with ID = id, id must be greather than 0
int writeBinLog(int id, const void * data, int size);
//! Write one RAW record to BinLog file, with ID = id, Timestamp = time
int writeBinLog_raw(int id, const PISystemTime &time, const PIByteArray &data) {return writeBinLog_raw(id, time, data.data(), data.size_s());}
int writeBinLog_raw(int id, const PISystemTime &time, const void * data, int size);
int writeBinLog_raw(int id, const PISystemTime & time, const PIByteArray & data) {
return writeBinLog_raw(id, time, data.data(), data.size_s());
}
int writeBinLog_raw(int id, const PISystemTime & time, const void * data, int size);
//! Returns count of writed records
int writeCount() const {return write_count;}
int writeCount() const { return write_count; }
//! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed
PIByteArray readBinLog(int id = 0, PISystemTime * time = 0, int * readed_id = 0);
//! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed
int readBinLog(int id, void * read_to, int max_size, PISystemTime * time = 0, int * readed_id = 0);
//! Returns binary log file size
llong logSize() const {return log_size;}
llong logSize() const { return log_size; }
//! Return position in current binlog file
llong logPos() const {return file.pos();}
llong logPos() const { return file.pos(); }
//! Return true, if position at the end of BinLog file
bool isEnd() const {if (isClosed()) return true; return file.isEnd();}
bool isEnd() const {
if (isClosed()) return true;
return file.isEnd();
}
//! Returns if BinLog file is empty
bool isEmpty() const;
//! Returns BinLog pause status
bool isPause() const {return is_pause;}
bool isPause() const { return is_pause; }
//! Returns id of last readed record
int lastReadedID() const {return lastrecord.id;}
int lastReadedID() const { return lastrecord.id; }
//! Returns timestamp of last readed record
PISystemTime lastReadedTimestamp() const {return lastrecord.timestamp;}
PISystemTime lastReadedTimestamp() const { return lastrecord.timestamp; }
//! Returns timestamp of log start
PISystemTime logStartTimestamp() const {return startlogtime;}
PISystemTime logStartTimestamp() const { return startlogtime; }
//!Set custom file header, you can get it back when read this binlog
//! Set custom file header, you can get it back when read this binlog
void setHeader(const PIByteArray & header);
//!Get custom file header
//! Get custom file header
PIByteArray getHeader();
#ifdef DOXYGEN
//! Read one message from binlog file, with ID contains in "filterID" or any ID, if "filterID" is empty
int read(void *read_to, int max_size);
int read(void * read_to, int max_size);
//! Write one record to BinLog file, with ID = "defaultID"
int write(const void * data, int size);
#endif
//! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead
PIVector<int> filterID;
//! Go to begin of BinLog file
void restart();
//! Get binlog info \a BinLogInfo
BinLogInfo logInfo() const {if (is_indexed) return binfo; return getLogInfo(path());}
BinLogInfo logInfo() const {
if (is_indexed) return binfo;
return getLogInfo(path());
}
//! Get binlog index \a BinLogIndex, need \a createIndex before getting index
const PIVector<BinLogIndex> & logIndex() const {return index;}
const PIVector<BinLogIndex> & logIndex() const { return index; }
//! Create index of current binlog file
bool createIndex();
//! Return if current binlog file is indexed
bool isIndexed() {return is_indexed;}
bool isIndexed() { return is_indexed; }
//! Find nearest record of time \"time\". Returns -1 if not indexed or time less than first record
int posForTime(const PISystemTime & time);
@@ -261,22 +284,25 @@ public:
bool seek(llong filepos);
//! Get current record index (position record in file)
int pos() const {if (is_indexed) return current_index; return -1;}
int pos() const {
if (is_indexed) return current_index;
return -1;
}
//! \handlers
//! \{
//! \fn PIString createNewFile()
//! \brief Create new binlog file in \a logDir, if successful returns filename, else returns empty string.
//! Filename is like \a filePrefix + "yyyy_MM_dd__hh_mm_ss.binlog"
//! \}
//! \events
//! \{
//! \fn void fileEnd()
//! \brief Raise on file end while reading
//! \fn void fileError()
//! \brief Raise on file creation error
@@ -284,7 +310,7 @@ public:
//! \brief Raise on new file created
//! \}
EVENT_HANDLER(PIString, createNewFile);
EVENT(fileEnd);
EVENT(fileError);
@@ -298,20 +324,22 @@ public:
static bool cutBinLog(const BinLogInfo & src, const PIString & dst, int from, int to);
//! Create new binlog from serial splitted binlogs "src"
static bool joinBinLogsSerial(const PIStringList & src, const PIString & dst, std::function<bool (const PIString &, PISystemTime)> progress = nullptr);
static bool joinBinLogsSerial(const PIStringList & src,
const PIString & dst,
std::function<bool(const PIString &, PISystemTime)> progress = nullptr);
protected:
PIString constructFullPathDevice() const override;
void configureFromFullPathDevice(const PIString & full_path) override;
PIPropertyStorage constructVariantDevice() const override;
void configureFromVariantDevice(const PIPropertyStorage & d) override;
ssize_t readDevice(void *read_to, ssize_t max_size) override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t size) override;
bool openDevice() override;
bool closeDevice() override;
void propertyChanged(const char * s) override;
bool threadedRead(const uchar *readed, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
bool threadedRead(const uchar * readed, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
private:
struct PIP_EXPORT BinLogRecord {
@@ -324,7 +352,7 @@ private:
bool writeFileHeader();
bool checkFileHeader();
BinLogRecord readRecord();
static void parseLog(PIFile *f, BinLogInfo *info, PIVector<BinLogIndex> * index);
static void parseLog(PIFile * f, BinLogInfo * info, PIVector<BinLogIndex> * index);
void moveIndex(int i);
static PIString getLogfilePath(const PIString & log_dir, const PIString & prefix);
@@ -347,7 +375,7 @@ private:
};
//! \relatesalso PICout \brief Output operator PIBinaryLog::BinLogInfo to PICout
inline PICout operator <<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
inline PICout operator<<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
s.space();
s.saveAndSetControls(0);
s << "[PIBinaryLog] " << bi.path << "\n";
@@ -360,7 +388,8 @@ inline PICout operator <<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
s << "Invalid empty file";
s.restoreControls();
return s;
} if (bi.records_count < 0 && bi.records_count > -4) {
}
if (bi.records_count < 0 && bi.records_count > -4) {
s << "Invalid file or corrupted signature";
s.restoreControls();
return s;
@@ -373,7 +402,7 @@ inline PICout operator <<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
s << "read records " << bi.records_count << " in " << bi.records.size() << " types, log size " << bi.log_size;
s << "\nlog start " << bi.start_time << " , log end " << bi.end_time;
PIVector<int> keys = bi.records.keys();
for (int i : keys) {
for (int i: keys) {
PIBinaryLog::BinLogRecordInfo bri = bi.records.at(i);
s << "\n record id " << bri.id << " , count " << bri.count;
s << "\n record start " << bri.start_time << " , end " << bri.end_time;
+44 -36
View File
@@ -1,37 +1,38 @@
/*
PIP - Platform Independent Primitives
CAN
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
CAN
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pican.h"
#include "pipropertystorage.h"
#include "piwaitevent_p.h"
#if !defined(WINDOWS) && !defined(MAC_OS) && !defined(MICRO_PIP)
# define PIP_CAN
#endif
#ifdef PIP_CAN
# include <sys/ioctl.h>
# include <net/if.h>
# include <linux/can.h>
# include <linux/can/raw.h>
# include <net/if.h>
# include <sys/ioctl.h>
# ifndef AF_CAN
# define AF_CAN 29
# define AF_CAN 29
# endif
# ifndef PF_CAN
# define PF_CAN AF_CAN
# define PF_CAN AF_CAN
# endif
#endif
@@ -44,11 +45,11 @@ PRIVATE_DEFINITION_START(PICAN)
PRIVATE_DEFINITION_END(PICAN)
PICAN::PICAN(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode) {
PICAN::PICAN(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode) {
setThreadedReadBufferSize(256);
setPath(path);
can_id = 0;
sock = 0;
sock = 0;
PRIVATE->event.create();
}
@@ -64,27 +65,27 @@ bool PICAN::openDevice() {
#ifdef PIP_CAN
piCout << "PICAN open device" << path();
sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if(sock < 0){
if (sock < 0) {
piCoutObj << "Error! while opening socket";
return false;
}
ifreq ifr;
strcpy(ifr.ifr_name, path().dataAscii());
piCout << "PICAN try to get interface index...";
if(ioctl(sock, SIOCGIFINDEX, &ifr) < 0){
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
piCoutObj << "Error! while determin the interface ioctl";
return false;
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof tv);
// bind socket to all CAN interface
sockaddr_can addr;
addr.can_family = AF_CAN;
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
piCout << "PICAN try to bind socket to interface" << ifr.ifr_ifindex;
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0){
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
piCoutObj << "Error! while binding socket";
return false;
}
@@ -108,13 +109,14 @@ bool PICAN::closeDevice() {
ssize_t PICAN::readDevice(void * read_to, ssize_t max_size) {
#ifdef PIP_CAN
//piCout << "PICAN read";
// piCout << "PICAN read";
can_frame frame;
ssize_t ret = 0;
if (PRIVATE->event.wait(sock))
ret = ::read(sock, &frame, sizeof(can_frame));
if (ret < 0) {/*piCoutObj << "Error while read CAN frame " << ret;*/ return -1;}
//piCoutObj << "receive CAN frame Id =" << frame.can_id;
if (PRIVATE->event.wait(sock)) ret = ::read(sock, &frame, sizeof(can_frame));
if (ret < 0) { /*piCoutObj << "Error while read CAN frame " << ret;*/
return -1;
}
// piCoutObj << "receive CAN frame Id =" << frame.can_id;
memcpy(read_to, frame.data, piMini(frame.can_dlc, max_size));
readed_id = frame.can_id;
return piMini(frame.can_dlc, max_size);
@@ -125,15 +127,21 @@ ssize_t PICAN::readDevice(void * read_to, ssize_t max_size) {
ssize_t PICAN::writeDevice(const void * data, ssize_t max_size) {
#ifdef PIP_CAN
//piCout << "PICAN write" << can_id << max_size;
if (max_size > 8) {piCoutObj << "Can't send CAN frame bigger than 8 bytes (requested " << max_size << ")!"; return -1;}
// piCout << "PICAN write" << can_id << max_size;
if (max_size > 8) {
piCoutObj << "Can't send CAN frame bigger than 8 bytes (requested " << max_size << ")!";
return -1;
}
can_frame frame;
frame.can_id = can_id;
frame.can_id = can_id;
frame.can_dlc = max_size;
memcpy(frame.data, data, max_size);
ssize_t ret = 0;
ret = ::write(sock, &frame, sizeof(can_frame));
if (ret < 0) {piCoutObj << "Error while send CAN frame " << ret; return -1;}
ret = ::write(sock, &frame, sizeof(can_frame));
if (ret < 0) {
piCoutObj << "Error while send CAN frame " << ret;
return -1;
}
return max_size;
#endif
return 0;
@@ -183,7 +191,7 @@ void PICAN::configureFromFullPathDevice(const PIString & full_path) {
PIPropertyStorage PICAN::constructVariantDevice() const {
PIPropertyStorage ret;
ret.addProperty("path", path());
ret.addProperty("CAN ID", PIString::fromNumber(CANID(),16));
ret.addProperty("CAN ID", PIString::fromNumber(CANID(), 16));
return ret;
}
+16 -16
View File
@@ -5,22 +5,22 @@
* \~russian Устройство CAN
*/
/*
PIP - Platform Independent Primitives
CAN
Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
CAN
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICAN_H
@@ -29,9 +29,9 @@
#include "piiodevice.h"
class PIP_EXPORT PICAN: public PIIODevice
{
class PIP_EXPORT PICAN: public PIIODevice {
PIIODEVICE(PICAN, "can");
public:
explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICAN();
@@ -50,7 +50,7 @@ protected:
void configureFromFullPathDevice(const PIString & full_path) override;
PIPropertyStorage constructVariantDevice() const override;
void configureFromVariantDevice(const PIPropertyStorage & d) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
private:
PRIVATE_DECLARATION(PIP_EXPORT)
+188 -168
View File
@@ -1,28 +1,30 @@
/*
PIP - Platform Independent Primitives
Config parser
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Config parser
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piconfig.h"
#include "pifile.h"
#include "piiostring.h"
#ifdef PIP_STD_IOSTREAM
# include "pistring_std.h"
# include <iostream>
#endif
/*! \class PIConfig
@@ -88,14 +90,14 @@
* internal instance of %PIConfig::Entry with "default" value will be returned.
* \snippet piconfig.cpp PIConfig::Entry
*
*/
*/
/*! \class PIConfig::Branch
* \brief %Branch is a list of entries of configuration file
* \details %Branch provides some features to get entries lists.
* \snippet piconfig.cpp PIConfig::Branch
*
*/
*/
PIConfig::Entry PIConfig::Branch::_empty;
@@ -105,9 +107,11 @@ PIConfig::Entry PIConfig::Entry::_empty;
PIConfig::Branch PIConfig::Branch::allLeaves() {
Branch b;
b.delim = delim;
piForeach (Entry * i, *this) {
if (i->isLeaf()) b << i;
else allLeaves(b, i);
piForeach(Entry * i, *this) {
if (i->isLeaf())
b << i;
else
allLeaves(b, i);
}
return b;
}
@@ -121,27 +125,27 @@ PIConfig::Entry & PIConfig::Branch::getValue(const PIString & vname, const PIStr
return _empty;
}
PIStringList tree = vname.split(delim);
PIString name = tree.front();
PIString name = tree.front();
tree.pop_front();
Entry * ce = 0;
piForeach (Entry * i, *this)
piForeach(Entry * i, *this)
if (i->_name == name) {
ce = i;
break;
}
if (ce == 0) {
_empty._name = vname;
_empty._name = vname;
_empty._value = def;
_empty.delim = delim;
_empty.delim = delim;
if (exist != 0) *exist = false;
return _empty;
}
piForeach (PIString & i, tree) {
piForeach(PIString & i, tree) {
ce = ce->findChild(i);
if (ce == 0) {
_empty._name = vname;
_empty._name = vname;
_empty._value = def;
_empty.delim = delim;
_empty.delim = delim;
if (exist != 0) *exist = false;
return _empty;
}
@@ -154,14 +158,12 @@ PIConfig::Entry & PIConfig::Branch::getValue(const PIString & vname, const PIStr
PIConfig::Branch PIConfig::Branch::getValues(const PIString & name) {
Branch b;
b.delim = delim;
piForeach (Entry * i, *this) {
piForeach(Entry * i, *this) {
if (i->isLeaf()) {
if (i->_name.find(name) >= 0)
b << i;
if (i->_name.find(name) >= 0) b << i;
} else {
piForeach (Entry * j, i->_children)
if (j->_name.find(name) >= 0)
b << j;
piForeach(Entry * j, i->_children)
if (j->_name.find(name) >= 0) b << j;
}
}
return b;
@@ -171,9 +173,8 @@ PIConfig::Branch PIConfig::Branch::getValues(const PIString & name) {
PIConfig::Branch PIConfig::Branch::getLeaves() {
Branch b;
b.delim = delim;
piForeach (Entry * i, *this)
if (i->isLeaf())
b << i;
piForeach(Entry * i, *this)
if (i->isLeaf()) b << i;
return b;
}
@@ -181,9 +182,8 @@ PIConfig::Branch PIConfig::Branch::getLeaves() {
PIConfig::Branch PIConfig::Branch::getBranches() {
Branch b;
b.delim = delim;
piForeach (Entry * i, *this)
if (!i->isLeaf())
b << i;
piForeach(Entry * i, *this)
if (!i->isLeaf()) b << i;
return b;
}
@@ -203,7 +203,7 @@ bool PIConfig::Branch::entryExists(const Entry * e, const PIString & name) const
if (e->_children.isEmpty()) {
return (e->_name == name);
}
piForeachC (Entry * i, e->_children)
piForeachC(Entry * i, e->_children)
if (entryExists(i, name)) return true;
return false;
}
@@ -211,13 +211,13 @@ bool PIConfig::Branch::entryExists(const Entry * e, const PIString & name) const
PIConfig::Entry & PIConfig::Entry::getValue(const PIString & vname, const PIString & def, bool * exist) {
PIStringList tree = vname.split(delim);
Entry * ce = this;
piForeach (PIString & i, tree) {
Entry * ce = this;
piForeach(PIString & i, tree) {
ce = ce->findChild(i);
if (ce == 0) {
_empty._name = vname;
_empty._name = vname;
_empty._value = def;
_empty.delim = delim;
_empty.delim = delim;
if (exist != 0) *exist = false;
return _empty;
}
@@ -230,9 +230,8 @@ PIConfig::Entry & PIConfig::Entry::getValue(const PIString & vname, const PIStri
PIConfig::Branch PIConfig::Entry::getValues(const PIString & vname) {
Branch b;
b.delim = delim;
piForeach (Entry * i, _children)
if (i->_name.find(vname) >= 0)
b << i;
piForeach(Entry * i, _children)
if (i->_name.find(vname) >= 0) b << i;
return b;
}
@@ -241,7 +240,7 @@ bool PIConfig::Entry::entryExists(const Entry * e, const PIString & name) const
if (e->_children.isEmpty()) {
return (e->_name == name);
}
piForeachC (Entry * i, e->_children)
piForeachC(Entry * i, e->_children)
if (entryExists(i, name)) return true;
return false;
}
@@ -249,19 +248,25 @@ bool PIConfig::Entry::entryExists(const Entry * e, const PIString & name) const
#ifdef PIP_STD_IOSTREAM
void PIConfig::Entry::coutt(std::ostream & s, const PIString & p) const {
PIString nl = p + " ";
if (!_value.isEmpty()) s << p << _name << " = " << _value << std::endl;
else std::cout << p << _name << std::endl;
piForeachC (Entry * i, _children) i->coutt(s, nl);
PIString nl = p + " ";
if (!_value.isEmpty())
s << p << _name << " = " << _value << std::endl;
else
std::cout << p << _name << std::endl;
piForeachC(Entry * i, _children)
i->coutt(s, nl);
}
#endif
void PIConfig::Entry::piCoutt(PICout s, const PIString & p) const {
PIString nl = p + " ";
if (!_value.isEmpty()) s << p << _name << " = " << _value << " (" << _type << " " << _comment << ")" << PICoutManipulators::NewLine;
else s << p << _name << PICoutManipulators::NewLine;
piForeachC (Entry * i, _children) i->piCoutt(s, nl);
PIString nl = p + " ";
if (!_value.isEmpty())
s << p << _name << " = " << _value << " (" << _type << " " << _comment << ")" << PICoutManipulators::NewLine;
else
s << p << _name << PICoutManipulators::NewLine;
piForeachC(Entry * i, _children)
i->piCoutt(s, nl);
}
@@ -286,9 +291,9 @@ PIConfig::PIConfig(PIIODevice * device, PIIODevice::DeviceMode mode) {
PIConfig::PIConfig(const PIString & path, PIStringList dirs) {
_init();
internal = true;
own_dev = true;
dev = new PIFile(path, PIIODevice::ReadOnly);
incdirs = dirs;
own_dev = true;
dev = new PIFile(path, PIIODevice::ReadOnly);
incdirs = dirs;
incdirs << PIFile::fileInfo(path).dir();
while (!dev->isOpened()) {
if (dirs.isEmpty()) break;
@@ -318,9 +323,8 @@ bool PIConfig::open(const PIString & path, PIIODevice::DeviceMode mode) {
_destroy();
incdirs << PIFile::fileInfo(path).dir();
own_dev = true;
dev = new PIFile(path, mode);
if (!dev->isOpened())
dev->open(path, mode);
dev = new PIFile(path, mode);
if (!dev->isOpened()) dev->open(path, mode);
_setupDev();
parse();
return dev->isOpened();
@@ -330,7 +334,7 @@ bool PIConfig::open(const PIString & path, PIIODevice::DeviceMode mode) {
bool PIConfig::open(PIString * string, PIIODevice::DeviceMode mode) {
_destroy();
own_dev = true;
dev = new PIIOString(string, mode);
dev = new PIIOString(string, mode);
_setupDev();
parse();
return true;
@@ -340,11 +344,10 @@ bool PIConfig::open(PIString * string, PIIODevice::DeviceMode mode) {
bool PIConfig::open(PIIODevice * device, PIIODevice::DeviceMode mode) {
_destroy();
own_dev = false;
dev = device;
dev = device;
if (dev) {
dev->open(mode);
if (dev->isTypeOf<PIFile>())
incdirs << PIFile::fileInfo(((PIFile*)dev)->path()).dir();
if (dev->isTypeOf<PIFile>()) incdirs << PIFile::fileInfo(((PIFile *)dev)->path()).dir();
}
_setupDev();
parse();
@@ -354,9 +357,9 @@ bool PIConfig::open(PIIODevice * device, PIIODevice::DeviceMode mode) {
void PIConfig::_init() {
delim = PIStringAscii(".");
root.delim = delim;
empty.delim = delim;
delim = PIStringAscii(".");
root.delim = delim;
empty.delim = delim;
empty._parent = 0;
}
@@ -368,7 +371,7 @@ void PIConfig::_destroy() {
}
if (own_dev && dev) delete dev;
dev = nullptr;
piForeach (PIConfig * c, inc_devs)
piForeach(PIConfig * c, inc_devs)
delete c;
inc_devs.clear();
}
@@ -383,14 +386,22 @@ void PIConfig::_setupDev() {
void PIConfig::_clearDev() {
if (!dev) return;
if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->clear(); return;}
if (PIString(dev->className()) == "PIIOString") {((PIIOString*)dev)->clear(); return;}
if (PIString(dev->className()) == "PIFile") {
((PIFile *)dev)->clear();
return;
}
if (PIString(dev->className()) == "PIIOString") {
((PIIOString *)dev)->clear();
return;
}
}
void PIConfig::_flushDev() {
if (!dev) return;
if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->flush();}
if (PIString(dev->className()) == "PIFile") {
((PIFile *)dev)->flush();
}
}
@@ -402,8 +413,14 @@ bool PIConfig::_isEndDev() {
void PIConfig::_seekToBeginDev() {
if (!dev) return;
if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->seekToBegin(); return;}
if (PIString(dev->className()) == "PIIOString") {((PIIOString*)dev)->seekToBegin(); return;}
if (PIString(dev->className()) == "PIFile") {
((PIFile *)dev)->seekToBegin();
return;
}
if (PIString(dev->className()) == "PIIOString") {
((PIIOString *)dev)->seekToBegin();
return;
}
}
@@ -414,7 +431,7 @@ PIString PIConfig::_readLineDev() {
void PIConfig::_writeDev(const PIString & l) {
//piCout << "write \"" << l << "\"";
// piCout << "write \"" << l << "\"";
if (!stream) return;
stream->append(l);
}
@@ -428,14 +445,14 @@ bool PIConfig::isOpened() const {
PIConfig::Entry & PIConfig::getValue(const PIString & vname, const PIString & def, bool * exist) {
PIStringList tree = vname.split(delim);
Entry * ce = &root;
piForeach (PIString & i, tree) {
Entry * ce = &root;
piForeach(PIString & i, tree) {
ce = ce->findChild(i);
if (ce == 0) {
if (exist != 0) *exist = false;
empty._name = vname;
empty._name = vname;
empty._value = def;
empty.delim = delim;
empty.delim = delim;
return empty;
}
}
@@ -447,50 +464,52 @@ PIConfig::Entry & PIConfig::getValue(const PIString & vname, const PIString & de
PIConfig::Branch PIConfig::getValues(const PIString & vname) {
Branch b;
b.delim = delim;
piForeach (Entry * i, root._children)
if (i->_name.find(vname) >= 0)
b << i;
piForeach(Entry * i, root._children)
if (i->_name.find(vname) >= 0) b << i;
return b;
};
void PIConfig::addEntry(const PIString & name, const PIString & value, const PIString & type, bool write) {
if (getValue(name)._parent != 0)
return;
bool toRoot = false;
if (getValue(name)._parent != 0) return;
bool toRoot = false;
PIStringList tree = name.split(delim);
PIString ename = tree.back();
PIString ename = tree.back();
tree.pop_back();
Entry * te, * ce, * entry = &root;
Entry *te, *ce, *entry = &root;
if (tree.isEmpty()) toRoot = true;
piForeach (PIString & i, tree) {
piForeach(PIString & i, tree) {
te = entry->findChild(i);
if (te == 0) {
ce = new Entry();
ce->delim = delim;
ce->_tab = entry->_tab;
ce->_line = entry->_line;
ce->_name = i;
ce = new Entry();
ce->delim = delim;
ce->_tab = entry->_tab;
ce->_line = entry->_line;
ce->_name = i;
ce->_parent = entry;
entry->_children << ce;
entry = ce;
} else entry = te;
} else
entry = te;
}
PIConfig::Branch ch = entry->_children;
ch.sort(PIConfig::Entry::compare);
te = (entry->isLeaf() ? 0 : ch.back());
ce = new Entry();
ce->delim = delim;
ce->_name = ename;
te = (entry->isLeaf() ? 0 : ch.back());
ce = new Entry();
ce->delim = delim;
ce->_name = ename;
ce->_value = value;
ce->_type = type;
ce->_type = type;
if (te == 0) {
ce->_tab = entry->_tab;
if (toRoot) ce->_line = other.size_s() - 1;
else ce->_line = entry->_line;
if (toRoot)
ce->_line = other.size_s() - 1;
else
ce->_line = entry->_line;
} else {
ce->_tab = te->_tab;
if (toRoot) ce->_line = other.size_s() - 1;
if (toRoot)
ce->_line = other.size_s() - 1;
else {
ch = entry->_parent->_children;
ch.sort(PIConfig::Entry::compare);
@@ -500,7 +519,7 @@ void PIConfig::addEntry(const PIString & name, const PIString & value, const PIS
ce->_parent = entry;
entry->_children << ce;
other.insert(ce->_line, "");
Branch b = allLeaves();
Branch b = allLeaves();
bool found = false;
for (int i = 0; i < b.size_s(); ++i) {
if (found) {
@@ -510,8 +529,7 @@ void PIConfig::addEntry(const PIString & name, const PIString & value, const PIS
if (b[i] == ce) {
found = true;
if (i > 0)
if (b[i - 1]->_line == b[i]->_line)
b[i - 1]->_line++;
if (b[i - 1]->_line == b[i]->_line) b[i - 1]->_line++;
}
}
if (write) writeAll();
@@ -525,18 +543,17 @@ void PIConfig::setValue(const PIString & name, const PIString & value, const PIS
return;
}
e._value = value;
e._type = type;
e._type = type;
if (write) writeAll();
}
int PIConfig::entryIndex(const PIString & name) {
PIStringList tree = name.split(delim);
Entry * ce = &root;
piForeach (PIString & i, tree) {
Entry * ce = &root;
piForeach(PIString & i, tree) {
ce = ce->findChild(i);
if (ce == 0)
return -1;
if (ce == 0) return -1;
}
return allLeaves().indexOf(ce);
}
@@ -600,8 +617,7 @@ void PIConfig::removeEntry(Branch & b, PIConfig::Entry * e) {
leaf = false;
} else {
int cc = e->_children.size_s();
piForTimes (cc)
removeEntry(b, e->_children.back());
piForTimes(cc) removeEntry(b, e->_children.back());
}
bool found = false;
for (int i = 0; i < b.size_s(); ++i) {
@@ -620,10 +636,16 @@ void PIConfig::removeEntry(Branch & b, PIConfig::Entry * e) {
PIString PIConfig::getPrefixFromLine(PIString line, bool * exists) {
line.trim();
if (line.left(1) == "#") {if (exists) *exists = false; return PIString();}
if (line.left(1) == "#") {
if (exists) *exists = false;
return PIString();
}
int ci = line.find("#");
if (ci >= 0) line.cutRight(line.size() - ci);
if (line.find("=") >= 0) {if (exists) *exists = false; return PIString();}
if (line.find("=") >= 0) {
if (exists) *exists = false;
return PIString();
}
if (line.find("[") >= 0 && line.find("]") >= 0) {
if (exists) *exists = true;
return line.takeRange('[', ']').trim();
@@ -634,51 +656,47 @@ PIString PIConfig::getPrefixFromLine(PIString line, bool * exists) {
void PIConfig::writeAll() {
//cout << this << " write < " << size() << endl;
// cout << this << " write < " << size() << endl;
_clearDev();
buildFullNames(&root);
Branch b = allLeaves();
PIString prefix, tprefix;
bool isPrefix;
//for (int i = 0; i < b.size_s(); ++i)
// for (int i = 0; i < b.size_s(); ++i)
// cout << b[i]->_name << " = " << b[i]->_value << endl;
int j = 0;
for (int i = 0; i < other.size_s(); ++i) {
//cout << j << endl;
// cout << j << endl;
if (j >= 0 && j < b.size_s()) {
if (b[j]->_line == i) {
b[j]->buildLine();
_writeDev((b[j]->_all).cutLeft(prefix.size()) + "\n");
//cout << this << " " << b[j]->_all << endl;
// cout << this << " " << b[j]->_all << endl;
++j;
} else {
_writeDev(other[i]);
tprefix = getPrefixFromLine(other[i], &isPrefix);
if (isPrefix) {
prefix = tprefix;
if (!prefix.isEmpty())
prefix += delim;
if (!prefix.isEmpty()) prefix += delim;
}
if (i < other.size_s() - 1)
_writeDev('\n');
//cout << this << " " << other[i] << endl;
if (i < other.size_s() - 1) _writeDev('\n');
// cout << this << " " << other[i] << endl;
}
} else {
_writeDev(other[i]);
tprefix = getPrefixFromLine(other[i], &isPrefix);
if (isPrefix) {
prefix = tprefix;
if (!prefix.isEmpty())
prefix += delim;
if (!prefix.isEmpty()) prefix += delim;
}
if (i < other.size_s() - 1)
_writeDev('\n');
//cout << this << " " << other[i] << endl;
if (i < other.size_s() - 1) _writeDev('\n');
// cout << this << " " << other[i] << endl;
}
}
_flushDev();
readAll();
//cout << this << " write > " << size() << endl;
// cout << this << " write > " << size() << endl;
}
@@ -699,7 +717,7 @@ bool PIConfig::entryExists(const Entry * e, const PIString & name) const {
if (e->_children.isEmpty()) {
return (e->_name == name);
}
piForeachC (Entry * i, e->_children)
piForeachC(Entry * i, e->_children)
if (entryExists(i, name)) return true;
return false;
}
@@ -708,7 +726,7 @@ bool PIConfig::entryExists(const Entry * e, const PIString & name) const {
void PIConfig::updateIncludes() {
if (internal) return;
all_includes.clear();
piForeach (PIConfig * c, includes)
piForeach(PIConfig * c, includes)
all_includes << c->allLeaves();
}
@@ -719,15 +737,15 @@ PIString PIConfig::parseLine(PIString v) {
i = v.find("${");
if (i < 0) break;
PIString w = v.mid(i + 1).takeRange('{', '}'), r;
l = w.length() + 3;
w = parseLine(w);
l = w.length() + 3;
w = parseLine(w);
w.trim();
bool ex = false;
bool ex = false;
PIConfig::Entry & me = getValue(w, "", &ex);
if (ex) {
r = me._value;
} else {
piForeachC (PIConfig::Entry * e, all_includes)
piForeachC(PIConfig::Entry * e, all_includes)
if (e->_full_name == w) {
r = e->_value;
break;
@@ -740,13 +758,13 @@ PIString PIConfig::parseLine(PIString v) {
void PIConfig::parse() {
//piCout << "[PIConfig] charset" << PIFile::defaultCharset();
// piCout << "[PIConfig] charset" << PIFile::defaultCharset();
PIString src, str, tab, comm, all, name, type, prefix, tprefix;
PIStringList tree;
Entry * entry = 0, * te = 0, * ce = 0;
Entry *entry = 0, *te = 0, *ce = 0;
int ind, sind;
bool isNew = false, isPrefix = false, wasMultiline = false, isMultiline = false;
piForeach (PIConfig * c, inc_devs)
piForeach(PIConfig * c, inc_devs)
delete c;
inc_devs.clear();
includes.clear();
@@ -757,16 +775,15 @@ void PIConfig::parse() {
while (!_isEndDev()) {
other.push_back(PIString());
src = str = parseLine(_readLineDev());
tprefix = getPrefixFromLine(src, &isPrefix);
tprefix = getPrefixFromLine(src, &isPrefix);
if (isPrefix) {
prefix = tprefix;
if (!prefix.isEmpty())
prefix += delim;
if (!prefix.isEmpty()) prefix += delim;
}
//piCout << "line \"" << str << "\"";
// piCout << "line \"" << str << "\"";
tab = str.left(str.find(str.trimmed().left(1)));
str.trim();
all = str;
all = str;
sind = str.find('#');
if (sind > 0) {
@@ -774,7 +791,8 @@ void PIConfig::parse() {
if (!comm.isEmpty()) {
type = comm[0];
comm.cutLeft(1).trim();
} else type = "s";
} else
type = "s";
str = str.left(sind).trim();
} else {
type = "s";
@@ -798,14 +816,14 @@ void PIConfig::parse() {
ce = 0;
wasMultiline = isMultiline;
//piCout << "[PIConfig] str" << str.size() << str << str.toUTF8();
ind = str.find('=');
// piCout << "[PIConfig] str" << str.size() << str << str.toUTF8();
ind = str.find('=');
if ((ind > 0) && (str[0] != '#')) {
tree = (prefix + str.left(ind).trimmed()).split(delim);
if (tree.front() == "include") {
name = str.mid(ind + 1).trimmed();
name = str.mid(ind + 1).trimmed();
PIConfig * iconf = new PIConfig(name, incdirs);
//piCout << "include" << name << iconf->dev;
// piCout << "include" << name << iconf->dev;
if (!iconf->dev) {
delete iconf;
} else {
@@ -818,41 +836,43 @@ void PIConfig::parse() {
name = tree.back();
tree.pop_back();
entry = &root;
piForeachC (PIString & i, tree) {
piForeachC(PIString & i, tree) {
te = entry->findChild(i);
if (te == 0) {
ce = new Entry();
ce->delim = delim;
ce->_tab = tab;
ce->_line = lines;
ce->_name = i;
ce = new Entry();
ce->delim = delim;
ce->_tab = tab;
ce->_line = lines;
ce->_name = i;
ce->_parent = entry;
entry->_children << ce;
entry = ce;
} else entry = te;
} else
entry = te;
}
isNew = false;
ce = entry->findChild(name);
ce = entry->findChild(name);
if (ce == 0) {
ce = new Entry();
ce = new Entry();
isNew = true;
}
ce->delim = delim;
ce->_tab = tab;
ce->_name = name;
ce->_value = str.mid(ind + 1).trimmed();
ce->_type = type;
ce->delim = delim;
ce->_tab = tab;
ce->_name = name;
ce->_value = str.mid(ind + 1).trimmed();
ce->_type = type;
ce->_comment = comm;
//piCout << "[PIConfig] comm" << comm.size() << comm << comm.toUTF8();
//piCout << "[PIConfig] type" << type.size() << type << type.toUTF8();
ce->_line = lines;
ce->_all = all;
// piCout << "[PIConfig] comm" << comm.size() << comm << comm.toUTF8();
// piCout << "[PIConfig] type" << type.size() << type << type.toUTF8();
ce->_line = lines;
ce->_all = all;
if (isNew) {
ce->_parent = entry;
entry->_children << ce;
}
}
} else other.back() = src;
} else
other.back() = src;
lines++;
}
setEntryDelim(&root, delim);
@@ -861,13 +881,13 @@ void PIConfig::parse() {
#ifdef PIP_STD_IOSTREAM
std::ostream &operator <<(std::ostream & s, const PIConfig::Entry & v) {
std::ostream & operator<<(std::ostream & s, const PIConfig::Entry & v) {
s << v.value();
return s;
}
std::ostream &operator <<(std::ostream & s, const PIConfig::Branch & v) {
std::ostream & operator<<(std::ostream & s, const PIConfig::Branch & v) {
v.coutt(s, "");
return s;
}
+13 -13
View File
@@ -5,22 +5,22 @@
* \~russian Разбор и запись конфигурационных файлов
*/
/*
PIP - Platform Independent Primitives
Configuration parser and writer
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Configuration parser and writer
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONFIG_H
+88 -88
View File
@@ -1,46 +1,47 @@
/*
PIP - Platform Independent Primitives
Directory
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Directory
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "pidir.h"
#include "piincludes_p.h"
const PIChar PIDir::separator = '/';
#ifdef QNX
# define _stat_struct_ struct stat
# define _stat_call_ stat
# define _stat_link_ lstat
# define _stat_struct_ struct stat
# define _stat_call_ stat
# define _stat_link_ lstat
#else
# define _stat_struct_ struct stat64
# define _stat_call_ stat64
# define _stat_link_ lstat64
# define _stat_struct_ struct stat64
# define _stat_call_ stat64
# define _stat_link_ lstat64
#endif
#ifndef WINDOWS
# ifdef ANDROID
# include <dirent.h>
# include <dirent.h>
# else
# ifdef FREERTOS
# ifdef FREERTOS
extern "C" {
# include <sys/dirent.h>
# include <sys/dirent.h>
}
# else
# include <sys/dir.h>
# endif
# else
# include <sys/dir.h>
# endif
# endif
# include <sys/stat.h>
#endif
@@ -70,7 +71,7 @@ PIDir::PIDir(const PIFile & file) {
}
bool PIDir::operator ==(const PIDir & d) const {
bool PIDir::operator==(const PIDir & d) const {
return d.absolutePath() == absolutePath();
}
@@ -94,7 +95,7 @@ PIString PIDir::path() const {
return path_.mid(1);
} else
#endif
return path_;
return path_;
}
@@ -108,7 +109,7 @@ PIString PIDir::absolutePath() const {
return path_.mid(1);
} else
#endif
return path_;
return path_;
}
return PIDir(PIDir::current().path() + separator + path_).path();
}
@@ -131,7 +132,7 @@ PIDir & PIDir::cleanPath() {
}
PIString sep = PIString(separator);
path_.replaceAll(sep + sep, sep);
bool is_abs = isAbsolute();
bool is_abs = isAbsolute();
PIStringList l = PIString(p).split(separator);
l.removeAll(".");
l.removeAll("");
@@ -150,8 +151,7 @@ PIDir & PIDir::cleanPath() {
break;
}
path_ = l.join(separator);
if (is_abs)
path_.prepend(separator);
if (is_abs) path_.prepend(separator);
if (path_.isEmpty()) path_ = ".";
return *this;
}
@@ -160,7 +160,7 @@ PIDir & PIDir::cleanPath() {
PIString PIDir::relative(const PIString & path) const {
PIDir td(path);
PIStringList dl(absolutePath().split(separator)), pl(td.absolutePath().split(separator)), rl;
//piCout << pl << "rel to" << dl;
// piCout << pl << "rel to" << dl;
while (!dl.isEmpty() && !pl.isEmpty()) {
if (dl.front() != pl.front()) break;
dl.pop_front();
@@ -179,8 +179,7 @@ PIDir & PIDir::setDir(const PIString & path) {
#ifdef WINDOWS
path_.replaceAll("\\", separator);
if (path_.length() > 2)
if (path_.mid(1, 2).contains(":"))
path_.prepend(separator);
if (path_.mid(1, 2).contains(":")) path_.prepend(separator);
#endif
cleanPath();
return *this;
@@ -197,56 +196,54 @@ PIDir & PIDir::cd(const PIString & path) {
bool PIDir::make(bool withParents) {
PIDir d = cleanedPath();
//PIString tp;
// PIString tp;
#ifndef WINDOWS
bool is_abs = isAbsolute();
#endif
if (withParents) {
PIStringList l = d.path().split(separator);
//piCout << l;
// piCout << l;
l.removeAll("");
//piCout << l;
// piCout << l;
PIString cdp;
piForeachC (PIString & i, l) {
piForeachC(PIString & i, l) {
if (!cdp.isEmpty()
#ifndef WINDOWS
|| is_abs
|| is_abs
#endif
)
)
cdp += separator;
cdp += i;
//piCout << "dir" << cdp;
// piCout << "dir" << cdp;
if (!isExists(cdp))
if (!makeDir(cdp))
return false;
if (!makeDir(cdp)) return false;
}
/*for (int i = l.size_s() - 1; i >= 0; --i) {
if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator);
else {
tp = separator;
if (!is_abs) tp.push_front('.');
}
piCout << "check" << tp;
if (isExists(tp)) {
for (int j = i + 1; j <= l.size_s(); ++j) {
tp = PIStringList(l).remove(j, l.size_s() - j).join(separator);
piCout << "make" << tp;
if (makeDir(tp)) continue;
else return false;
}
break;
};
if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator);
else {
tp = separator;
if (!is_abs) tp.push_front('.');
}
piCout << "check" << tp;
if (isExists(tp)) {
for (int j = i + 1; j <= l.size_s(); ++j) {
tp = PIStringList(l).remove(j, l.size_s() - j).join(separator);
piCout << "make" << tp;
if (makeDir(tp)) continue;
else return false;
}
break;
};
}*/
return true;
} else
if (makeDir(d.path())) return true;
} else if (makeDir(d.path()))
return true;
return false;
}
bool PIDir::rename(const PIString & new_name) {
if (!PIDir::rename(path(), new_name))
return false;
if (!PIDir::rename(path(), new_name)) return false;
setDir(new_name);
return true;
}
@@ -278,8 +275,10 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
if (!isExists()) return l;
PIString dp = absolutePath();
PIString p(dp);
if (dp == ".") dp.clear();
else if (!dp.endsWith(separator)) dp += separator;
if (dp == ".")
dp.clear();
else if (!dp.endsWith(separator))
dp += separator;
// piCout << "start entries from" << p;
#ifdef WINDOWS
if (dp == separator) {
@@ -290,7 +289,7 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
for (DWORD i = 0; i < ll; ++i) {
if (letters[i] == '\0') {
clet.resize(2);
fi.path = clet;
fi.path = clet;
fi.flags = PIFile::FileInfo::Dir;
l << fi;
clet.clear();
@@ -298,7 +297,8 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
clet += PIChar(letters[i]);
}
} else {
WIN32_FIND_DATAA fd; memset(&fd, 0, sizeof(fd));
WIN32_FIND_DATAA fd;
memset(&fd, 0, sizeof(fd));
p += "\\*";
void * hf = FindFirstFileA((LPCSTR)(p.data()), &fd);
if (!hf) return l;
@@ -313,7 +313,7 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
l.sort(sort_compare);
if (!hdd) {
PIFile::FileInfo fi;
fi.path = "..";
fi.path = "..";
fi.flags = PIFile::FileInfo::Dir | PIFile::FileInfo::DotDot;
l.push_front(fi);
}
@@ -322,8 +322,8 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
#else
# if defined(QNX) || defined(FREERTOS)
struct dirent * de = 0;
DIR * dir = 0;
dir = opendir(p.data());
DIR * dir = 0;
dir = opendir(p.data());
if (dir) {
for (;;) {
de = readdir(dir);
@@ -334,12 +334,14 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
}
# else
dirent ** list;
int cnt = scandir(p.data(), &list, 0,
# if defined(MAC_OS) || defined(ANDROID) || defined(BLACKBERRY)
alphasort);
# else
versionsort);
# endif
int cnt = scandir(p.data(),
&list,
0,
# if defined(MAC_OS) || defined(ANDROID) || defined(BLACKBERRY)
alphasort);
# else
versionsort);
# endif
for (int i = 0; i < cnt; ++i) {
l << PIFile::fileInfo(dp + PIString(list[i]->d_name));
free(list[i]);
@@ -347,7 +349,7 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
free(list);
# endif
#endif
// piCout << "end entries from" << p;
// piCout << "end entries from" << p;
return l;
}
@@ -370,16 +372,17 @@ PIVector<PIFile::FileInfo> PIDir::allEntries() {
PIStringList cdirs, ndirs;
cdirs << path();
while (!cdirs.isEmpty()) {
piForeachC (PIString & d, cdirs) {
scan_ = d;
piForeachC(PIString & d, cdirs) {
scan_ = d;
PIVector<PIFile::FileInfo> el = PIDir(d).entries();
piForeachC (PIFile::FileInfo & de, el) {
piForeachC(PIFile::FileInfo & de, el) {
if (de.name() == "." || de.name() == "..") continue;
if (de.isSymbolicLink()) continue; /// TODO: resolve symlinks
if (de.isDir()) {
dirs << de;
ndirs << de.path;
} else ret << de;
} else
ret << de;
}
}
cdirs = ndirs;
@@ -391,7 +394,6 @@ PIVector<PIFile::FileInfo> PIDir::allEntries() {
}
bool PIDir::isExists(const PIString & path) {
#ifdef WINDOWS
DWORD ret = GetFileAttributes((LPCTSTR)(path.data()));
@@ -434,20 +436,20 @@ PIDir PIDir::home() {
#ifdef WINDOWS
rc = new char[1024];
memset(rc, 0, 1024);
if (ExpandEnvironmentStrings((LPCTSTR)"%HOMEPATH%", (LPTSTR)rc, 1024) == 0) {
if (ExpandEnvironmentStrings((LPCTSTR) "%HOMEPATH%", (LPTSTR)rc, 1024) == 0) {
delete[] rc;
return PIDir();
}
PIString hp(rc);
memset(rc, 0, 1024);
if (ExpandEnvironmentStrings((LPCTSTR)"%HOMEDRIVE%", (LPTSTR)rc, 1024) == 0) {
if (ExpandEnvironmentStrings((LPCTSTR) "%HOMEDRIVE%", (LPTSTR)rc, 1024) == 0) {
delete[] rc;
return PIDir();
}
PIString hd(rc);
hp.replaceAll("\\", PIDir::separator);
delete[] rc;
//s.prepend(separator);
// s.prepend(separator);
return PIDir(hd + hp);
#else
# ifndef ESP_PLATFORM
@@ -485,7 +487,7 @@ PIDir PIDir::temporary() {
}
PIVector<PIFile::FileInfo> PIDir::allEntries(const PIString &path) {
PIVector<PIFile::FileInfo> PIDir::allEntries(const PIString & path) {
return PIDir(path).allEntries();
}
@@ -535,5 +537,3 @@ bool PIDir::renameDir(const PIString & path, const PIString & new_name) {
printf("[PIDir] renameDir(\"%s\", \"%s\") error: %s\n", path.data(), new_name.data(), errorString().data());
return false;
}
+72 -58
View File
@@ -5,22 +5,22 @@
* \~russian Локальная директория
*/
/*
PIP - Platform Independent Primitives
Directory
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Directory
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIDIR_H
@@ -33,80 +33,82 @@
//! \~\brief
//! \~english Local directory.
//! \~russian Локальная директория.
class PIP_EXPORT PIDir
{
class PIP_EXPORT PIDir {
public:
//! \~english Constructs directory with path "dir"
//! \~russian Создает директорию с путём "dir"
PIDir(const PIString & dir = PIString());
//! \~english Constructs directory with "file" directory path
//! \~russian Создает директорию с путём директории файла "file"
PIDir(const PIFile & file);
//! \~english Returns if this directory exists
//! \~russian Возвращает существует ли эта директория
bool isExists() const {return PIDir::isExists(path());}
bool isExists() const { return PIDir::isExists(path()); }
//! \~english Returns if path of this directory is absolute
//! \~russian Возвращает абсолютный ли путь у директории
bool isAbsolute() const;
//! \~english Returns if path of this directory is relative
//! \~russian Возвращает относительный ли путь у директории
bool isRelative() const {return !isAbsolute();}
bool isRelative() const { return !isAbsolute(); }
//! \~english Returns path of current reading directory. This path valid only while \a allEntries() functions
//! \~russian Возвращает путь текущей директории чтения. Этот путь действителен только во время выполнения метода \a allEntries()
const PIString & scanDir() const {return scan_;}
const PIString & scanDir() const { return scan_; }
//! \~english Returns path of this directory
//! \~russian Возвращает путь директории
PIString path() const;
//! \~english Returns absolute path of this directory
//! \~russian Возвращает абсолютный путь директории
PIString absolutePath() const;
//! \~english Simplify path of this directory
//! \~russian Упрощает путь директории
PIDir & cleanPath();
//! \~english Returns %PIDir with simplified path of this directory
//! \~russian Возвращает %PIDir с упрощённым путём директории
PIDir cleanedPath() const {PIDir d(path()); d.cleanPath(); return d;}
PIDir cleanedPath() const {
PIDir d(path());
d.cleanPath();
return d;
}
//! \~english Returns relative to this directory path "path"
//! \~russian Возвращает путь "path" относительно этой директории
PIString relative(const PIString & path) const;
//! \~english Set this directory path to simplified "path"
//! \~russian Устанавливает путь директории упрощённым "path"
PIDir & setDir(const PIString & path);
//! \~english Set this directory path as current for application
//! \~russian Устанавливает путь директории текущим путём приложения
bool setCurrent() {return PIDir::setCurrent(path());}
bool setCurrent() { return PIDir::setCurrent(path()); }
//! \~english Returns this directory content
//! \~russian Возвращает содержимое этой директории
PIVector<PIFile::FileInfo> entries();
//! \~english Returns this directory content recursively
//! \~russian Возвращает содержимое этой директории рекурсивно
PIVector<PIFile::FileInfo> allEntries();
//! \~english Make this directory, recursively if "withParents"
//! \~russian Создаёт эту директорию, рекурсивно если "withParents"
bool make(bool withParents = true);
//! \~english Remove this directory
//! \~russian Удаляет эту директорию
bool remove() {return PIDir::remove(path());}
bool remove() { return PIDir::remove(path()); }
//! \~english Rename this directory
//! \~russian Переименовывает эту директорию
@@ -118,18 +120,18 @@ public:
//! \~english Change this directory to parent
//! \~russian Изменяет директорию на родительскую
PIDir & up() {return cd("..");}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator ==(const PIDir & d) const;
PIDir & up() { return cd(".."); }
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const PIDir & d) const {return !((*this) == d);}
bool operator==(const PIDir & d) const;
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator!=(const PIDir & d) const { return !((*this) == d); }
static const PIChar separator;
//! \~english Returns current directory for application
//! \~russian Возвращает текущую директорию приложения
@@ -157,11 +159,11 @@ public:
//! \~english Remove directory "path"
//! \~russian Удаляет директорию "path"
static bool remove(const PIString & path) {return removeDir(path);}
static bool remove(const PIString & path) { return removeDir(path); }
//! \~english Rename directory "path"
//! \~russian Переименовывает директорию "path"
static bool rename(const PIString & path, const PIString & new_name) {return PIDir::renameDir(path, new_name);}
static bool rename(const PIString & path, const PIString & new_name) { return PIDir::renameDir(path, new_name); }
//! \~english Set path "path" as current for application
//! \~russian Устанавливает путь "path" текущим путём приложения
@@ -169,27 +171,39 @@ public:
//! \~english Set directory "dir" path as current for application
//! \~russian Устанавливает путь директории "dir" текущим путём приложения
static bool setCurrent(const PIDir & dir) {return setCurrent(dir.path());}
static bool setCurrent(const PIDir & dir) { return setCurrent(dir.path()); }
private:
static bool makeDir(const PIString & path);
static bool removeDir(const PIString & path);
static bool renameDir(const PIString & path, const PIString & new_name);
PIString path_, scan_;
};
inline bool operator <(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path < v1.path);}
inline bool operator >(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path > v1.path);}
inline bool operator ==(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path == v1.path);}
inline bool operator !=(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path != v1.path);}
inline bool operator<(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {
return (v0.path < v1.path);
}
inline bool operator>(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {
return (v0.path > v1.path);
}
inline bool operator==(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {
return (v0.path == v1.path);
}
inline bool operator!=(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {
return (v0.path != v1.path);
}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIDir & v) {s.saveAndSetControls(0); s << "PIDir(\"" << v.path() << "\")"; s.restoreControls(); return s;}
inline PICout operator<<(PICout s, const PIDir & v) {
s.saveAndSetControls(0);
s << "PIDir(\"" << v.path() << "\")";
s.restoreControls();
return s;
}
#endif // PIDIR_H
+276 -250
View File
@@ -1,46 +1,48 @@
/*
PIP - Platform Independent Primitives
Ethernet, UDP/TCP Broadcast/Multicast
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Ethernet, UDP/TCP Broadcast/Multicast
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "piethernet.h"
#include "piconfig.h"
#include "pisysteminfo.h"
#include "pipropertystorage.h"
#include "piconstchars.h"
#include "piincludes_p.h"
#include "pipropertystorage.h"
#include "pisysteminfo.h"
// clang-format off
#ifdef QNX
# include <arpa/inet.h>
# include <fcntl.h>
# include <hw/nicinfo.h>
# include <ifaddrs.h>
# include <net/if.h>
# include <net/if_dl.h>
# include <hw/nicinfo.h>
# include <netdb.h>
# include <netinet/in.h>
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <sys/types.h>
# include <sys/ioctl.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <ifaddrs.h>
# include <fcntl.h>
# ifdef BLACKBERRY
# include <netinet/in.h>
# include <netinet/in.h>
# else
# include <sys/dcmd_io-net.h>
# include <sys/dcmd_io-net.h>
# endif
# define ip_mreqn ip_mreq
# define ip_mreqn ip_mreq
# define imr_address imr_interface
#else
# ifdef WINDOWS
@@ -67,7 +69,9 @@
# endif
# endif
#endif
// clang-format on
#include "piwaitevent_p.h"
#include <errno.h>
@@ -81,21 +85,21 @@
* UDP and TCP. This class allow you send and receive packets to/from
* another computer through network. Also it supports broadcast and
* multicast extensions.
*
*
* \section PIEthernet_sec1 IPv4
*
*
*
*
* \section PIEthernet_sec2 UDP
* User Datagram Protocol
*
*
* \section PIEthernet_sec3 TCP
* Transmission Control Protocol
*
*
* */
#ifndef WINDOWS
PIString getSockAddr(sockaddr * s) {
return s == 0 ? PIString() : PIStringAscii(inet_ntoa(((sockaddr_in*)s)->sin_addr));
return s == 0 ? PIString() : PIStringAscii(inet_ntoa(((sockaddr_in *)s)->sin_addr));
}
#endif
@@ -145,7 +149,8 @@ void PIEthernet::Address::setPort(ushort _port) {
void PIEthernet::Address::set(const PIString & ip_port) {
PIString _ip; int p(0);
PIString _ip;
int p(0);
splitIPPort(ip_port, &_ip, &p);
port_ = p;
initIP(_ip);
@@ -159,13 +164,13 @@ void PIEthernet::Address::set(const PIString & _ip, ushort _port) {
void PIEthernet::Address::set(uint _ip, ushort _port) {
ip_ = _ip;
ip_ = _ip;
port_ = _port;
}
void PIEthernet::Address::clear() {
ip_ = 0;
ip_ = 0;
port_ = 0;
}
@@ -176,7 +181,8 @@ bool PIEthernet::Address::isNull() const {
PIEthernet::Address PIEthernet::Address::resolve(const PIString & host_port) {
PIString host; int port(0);
PIString host;
int port(0);
splitIPPort(host_port, &host, &port);
return resolve(host, port);
}
@@ -185,16 +191,14 @@ PIEthernet::Address PIEthernet::Address::resolve(const PIString & host_port) {
PIEthernet::Address PIEthernet::Address::resolve(const PIString & host, ushort port) {
Address ret(0, port);
hostent * he = gethostbyname(host.dataAscii());
if (!he)
return ret;
if (he->h_addr_list[0])
ret.setIP(*((uint*)(he->h_addr_list[0])));
if (!he) return ret;
if (he->h_addr_list[0]) ret.setIP(*((uint *)(he->h_addr_list[0])));
return ret;
}
void PIEthernet::Address::splitIPPort(const PIString & ipp, PIString * _ip, int * _port) {
//piCout << "parse" << ipp;
// piCout << "parse" << ipp;
int sp = ipp.findLast(":");
if (_ip != 0) *_ip = (sp >= 0 ? ipp.left(sp) : ipp);
if (_port != 0 && sp >= 0) *_port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt();
@@ -224,7 +228,8 @@ PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) {
}
PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags<PIEthernet::Parameters> params_): PIIODevice(ip_port, ReadWrite) {
PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags<PIEthernet::Parameters> params_)
: PIIODevice(ip_port, ReadWrite) {
construct();
addr_r.set(ip_port);
setType(type_);
@@ -236,7 +241,7 @@ PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const P
PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
construct();
addr_s.set(ip_port);
sock = sock_;
sock = sock_;
opened_ = connected_ = true;
init();
setParameters(PIEthernet::ReuseAddress | PIEthernet::MulticastLoop);
@@ -244,21 +249,21 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
setPath(ip_port);
ethNonblocking(sock);
PRIVATE->event.create();
//piCoutObj << "new tcp client" << sock_;
// piCoutObj << "new tcp client" << sock_;
}
PIEthernet::~PIEthernet() {
//piCout << "~PIEthernet";
// piCout << "~PIEthernet";
stopAndWait();
close();
PRIVATE->event.destroy();
//piCout << "~PIEthernet done";
// piCout << "~PIEthernet done";
}
void PIEthernet::construct() {
//piCout << " PIEthernet" << uint(this);
// piCout << " PIEthernet" << uint(this);
setOption(BlockingWrite);
connected_ = connecting_ = listen_threaded = server_bounded = false;
sock = sock_s = -1;
@@ -273,17 +278,16 @@ void PIEthernet::construct() {
#else
setThreadedReadBufferSize(65536);
#endif
//setPriority(piHigh);
// setPriority(piHigh);
}
bool PIEthernet::init() {
if (isOpened()) return true;
if (sock != -1) return true;
//piCout << "init " << type();
// piCout << "init " << type();
PRIVATE->event.destroy();
if (sock_s == sock)
sock_s = -1;
if (sock_s == sock) sock_s = -1;
closeSocket(sock);
closeSocket(sock_s);
int st = 0, pr = 0;
@@ -309,7 +313,7 @@ bool PIEthernet::init() {
if (params[PIEthernet::Broadcast]) ethSetsockoptBool(sock, SOL_SOCKET, SO_BROADCAST);
applyTimeouts();
applyOptInt(IPPROTO_IP, IP_TTL, TTL());
//piCoutObj << "inited" << path();
// piCoutObj << "inited" << path();
return true;
}
@@ -324,10 +328,10 @@ PIString PIEthernet::macFromBytes(const PIByteArray & mac) {
}
PIByteArray PIEthernet::macToBytes(const PIString & mac) {
PIByteArray PIEthernet::macToBytes(const PIString & mac) {
PIByteArray r;
PIStringList sl = mac.split(PIStringAscii(":"));
piForeachC (PIString & i, sl)
piForeachC(PIString & i, sl)
r << uchar(i.toInt(16));
return r;
}
@@ -363,25 +367,26 @@ PIEthernet::Address PIEthernet::getBroadcast(const PIEthernet::Address & ip, con
bool PIEthernet::openDevice() {
if (connected_) return true;
//piCoutObj << "open";
// piCoutObj << "open";
init();
if (sock == -1 || path().isEmpty()) return false;
addr_r.set(path());
//if (type() == TCP_Client)
// if (type() == TCP_Client)
// connecting_ = true;
if (type() != UDP || mode() == PIIODevice::WriteOnly)
return true;
if (type() != UDP || mode() == PIIODevice::WriteOnly) return true;
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
PRIVATE->addr_.sin_family = AF_INET;
PRIVATE->addr_.sin_port = htons(addr_r.port());
if (params[PIEthernet::Broadcast]) PRIVATE->addr_.sin_addr.s_addr = INADDR_ANY;
else PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_port = htons(addr_r.port());
if (params[PIEthernet::Broadcast])
PRIVATE->addr_.sin_addr.s_addr = INADDR_ANY;
else
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
//piCout << "bind to" << (params[PIEthernet::Broadcast] ? "255.255.255.255" : ip_) << ":" << port_ << " ...";
// piCout << "bind to" << (params[PIEthernet::Broadcast] ? "255.255.255.255" : ip_) << ":" << port_ << " ...";
int tries = 0;
while ((bind(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
while ((bind(sock, (sockaddr *)&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
init();
tries++;
}
@@ -400,24 +405,22 @@ bool PIEthernet::openDevice() {
bool PIEthernet::closeDevice() {
//piCoutObj << "close";
bool ned = connected_;
// piCoutObj << "close";
bool ned = connected_;
connected_ = connecting_ = false;
server_thread_.stop();
PRIVATE->event.interrupt();
if (server_thread_.isRunning()) {
if (!server_thread_.waitForFinish(1000))
server_thread_.terminate();
if (!server_thread_.waitForFinish(1000)) server_thread_.terminate();
}
PRIVATE->event.destroy();
if (sock_s == sock)
sock_s = -1;
if (sock_s == sock) sock_s = -1;
closeSocket(sock);
closeSocket(sock_s);
while (!clients_.isEmpty())
delete clients_.back();
if (ned) {
//piCoutObj << "Disconnect on close";
// piCoutObj << "Disconnect on close";
disconnected(false);
}
return true;
@@ -425,8 +428,7 @@ bool PIEthernet::closeDevice() {
void PIEthernet::closeSocket(int & sd) {
if (sd != -1)
ethClosesocket(sd, type() != PIEthernet::UDP);
if (sd != -1) ethClosesocket(sd, type() != PIEthernet::UDP);
sd = -1;
}
@@ -445,13 +447,14 @@ void PIEthernet::applyTimeouts() {
void PIEthernet::applyTimeout(int fd, int opt, double ms) {
if (fd == 0) return;
//piCoutObj << "setReadIsBlocking" << yes;
// piCoutObj << "setReadIsBlocking" << yes;
#ifdef WINDOWS
DWORD _tm = ms;
#else
double s = ms / 1000.;
timeval _tm;
_tm.tv_sec = piFloord(s); s -= _tm.tv_sec;
_tm.tv_sec = piFloord(s);
s -= _tm.tv_sec;
_tm.tv_usec = s * 1000000.;
#endif
ethSetsockopt(fd, SOL_SOCKET, opt, &_tm, sizeof(_tm));
@@ -461,8 +464,7 @@ void PIEthernet::applyTimeout(int fd, int opt, double ms) {
void PIEthernet::applyOptInt(int level, int opt, int val) {
if (sock < 0) return;
ethSetsockoptInt(sock, level, opt, val);
if (sock_s != sock && sock_s != -1)
ethSetsockoptInt(sock_s, level, opt, val);
if (sock_s != sock && sock_s != -1) ethSetsockoptInt(sock_s, level, opt, val);
}
@@ -474,8 +476,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
return false;
}
if (isClosed()) {
if (mcast_queue.contains(group))
return false;
if (mcast_queue.contains(group)) return false;
mcast_queue.enqueue(group);
if (!mcast_groups.contains(group)) mcast_groups << group;
return true;
@@ -488,7 +489,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
#endif
memset(&mreq, 0, sizeof(mreq));
#ifdef LINUX
//mreq.imr_address.s_addr = INADDR_ANY;
// mreq.imr_address.s_addr = INADDR_ANY;
/*PIEthernet::InterfaceList il = interfaces();
const PIEthernet::Interface * ci = il.getByAddress(addr_r.ipString());
if (ci != 0) mreq.imr_ifindex = ci->index;*/
@@ -499,14 +500,14 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
#else
mreq.imr_interface.s_addr = INADDR_ANY;
#endif
else
else
#ifndef LWIP
mreq.imr_address.s_addr = addr_r.ip();
#else
mreq.imr_interface.s_addr = addr_r.ip();
#endif
//piCout << "join group" << group << "ip" << ip_ << "with index" << mreq.imr_ifindex << "socket" << sock;
// piCout << "join group" << group << "ip" << ip_ << "with index" << mreq.imr_ifindex << "socket" << sock;
mreq.imr_multiaddr.s_addr = inet_addr(group.dataAscii());
if (ethSetsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != 0) {
piCoutObj << "Can`t join multicast group" << group << "," << ethErrorString();
@@ -539,7 +540,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
#else
mreq.imr_interface.s_addr = INADDR_ANY;
#endif
else
else
#ifndef LWIP
mreq.imr_address.s_addr = addr_r.ip();
#else
@@ -565,14 +566,14 @@ bool PIEthernet::connect(bool threaded) {
if (sock == -1) return false;
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
addr_r.set(path());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
connecting_ = true;
connected_ = connectTCP();
connected_ = connectTCP();
connecting_ = false;
if (!connected_) {
piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
@@ -592,26 +593,25 @@ bool PIEthernet::listen(bool threaded) {
if (server_thread_.isRunning()) {
if (!server_bounded) return true;
server_thread_.stop();
if (!server_thread_.waitForFinish(100))
server_thread_.terminate();
if (!server_thread_.waitForFinish(100)) server_thread_.terminate();
}
listen_threaded = true;
server_bounded = false;
server_bounded = false;
server_thread_.start(server_func);
return true;
}
listen_threaded = server_bounded = false;
addr_r.set(path());
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
opened_ = false;
opened_ = false;
int tries = 0;
while ((bind(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
while ((bind(sock, (sockaddr *)&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
init();
tries++;
}
@@ -620,7 +620,7 @@ bool PIEthernet::listen(bool threaded) {
return false;
}
if (::listen(sock, 64) == -1) {
piCoutObj << "Can`t listen on"<< addr_r << "," << ethErrorString();
piCoutObj << "Can`t listen on" << addr_r << "," << ethErrorString();
return false;
}
opened_ = server_bounded = true;
@@ -652,9 +652,9 @@ bool PIEthernet::send(const PIEthernet::Address & addr, const void * data, int s
return true;
}
Address pa = addr_s;
addr_s = addr;
int wr = write(data, size);
addr_s = pa;
addr_s = addr;
int wr = write(data, size);
addr_s = pa;
return (wr == size);
}
@@ -674,66 +674,65 @@ bool PIEthernet::send(const PIEthernet::Address & addr, const PIByteArray & data
return true;
}
Address pa = addr_s;
addr_s = addr;
int wr = write(data);
addr_s = pa;
addr_s = addr;
int wr = write(data);
addr_s = pa;
return (wr == data.size_s());
}
void PIEthernet::interrupt() {
//piCout << "interrupt";
// piCout << "interrupt";
PRIVATE->event.interrupt();
}
ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
//piCout << "read" << sock;
// piCout << "read" << sock;
if (sock == -1) init();
if (sock == -1 || read_to == 0) return -1;
int rs = 0, lerr = 0;
//piCoutObj << "read from " << path() << connecting_;
// piCoutObj << "read from " << path() << connecting_;
switch (type()) {
case TCP_Client:
if (connecting_) {
addr_r.set(path());
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
//piCoutObj << "connect to " << path() << "...";
// piCoutObj << "connect to " << path() << "...";
connected_ = connectTCP();
//piCoutObj << "connect to " << path() << connected_;
if (!connected_)
piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
// piCoutObj << "connect to " << path() << connected_;
if (!connected_) piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
opened_.exchange(connected_);
if (connected_) {
connecting_ = false;
connected();
} else
piMSleep(10);
//piCout << "connected to" << path();
// piCout << "connected to" << path();
}
if (!connected_) return -1;
errorClear();
#ifdef WINDOWS
{
long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE);
switch (wr) {
case 0: return -1;
case FD_READ:
//piCout << "fd_read ...";
rs = ethRecv(sock, read_to, max_size);
break;
case FD_CLOSE:
//piCout << "fd_close ...";
rs = -1;
break;
default: break;
}
long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE);
switch (wr) {
case 0: return -1;
case FD_READ:
// piCout << "fd_read ...";
rs = ethRecv(sock, read_to, max_size);
break;
case FD_CLOSE:
// piCout << "fd_close ...";
rs = -1;
break;
default: break;
}
}
#else
if (PRIVATE->event.wait(sock)) {
@@ -741,10 +740,10 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
rs = ethRecv(sock, read_to, max_size);
}
#endif
//piCoutObj << "readed" << rs;
// piCoutObj << "readed" << rs;
if (rs <= 0) {
lerr = ethErrorCore();
//piCoutObj << "readed" << rs << "error" << lerr;
// piCoutObj << "readed" << rs << "error" << lerr;
// async normal returns
#ifdef WINDOWS
@@ -752,7 +751,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
#else
if (lerr == EWOULDBLOCK || lerr == EAGAIN || lerr == EINTR) {
#endif
//piCoutObj << "Ignore would_block" << lerr;
// piCoutObj << "Ignore would_block" << lerr;
return -1;
}
@@ -763,15 +762,15 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
#else
if (lerr == ETIMEDOUT) {
#endif
//piCoutObj << "Ignore read timeout";
// piCoutObj << "Ignore read timeout";
return -1;
}
}
// disconnect here
//piCoutObj << "Disconnnected, check for event, connected =" << connected_;
// piCoutObj << "Disconnnected, check for event, connected =" << connected_;
if (connected_.exchange(false)) {
opened_ = false;
//piCoutObj << "Disconnect on read," << ethErrorString();
// piCoutObj << "Disconnect on read," << ethErrorString();
closeSocket(sock);
init();
disconnected(rs < 0);
@@ -779,38 +778,38 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
if (params[KeepConnection]) {
connect();
}
//piCoutObj << "eth" << ip_ << "disconnected";
// piCoutObj << "eth" << ip_ << "disconnected";
}
if (rs > 0) received(read_to, rs);
return rs;
case UDP: {
memset(&PRIVATE->raddr_, 0, sizeof(PRIVATE->raddr_));
//piCoutObj << "read from" << path() << "...";
// piCoutObj << "read from" << path() << "...";
#ifdef WINDOWS
long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE);
switch (wr) {
case FD_READ:
//piCout << "fd_read ...";
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&PRIVATE->raddr_);
// piCout << "fd_read ...";
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr *)&PRIVATE->raddr_);
break;
case FD_CLOSE:
//piCout << "fd_close ...";
// piCout << "fd_close ...";
rs = -1;
break;
default: break;
}
#else
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&PRIVATE->raddr_);
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr *)&PRIVATE->raddr_);
#endif
//piCoutObj << "read from" << path() << rs << "bytes";
// piCoutObj << "read from" << path() << rs << "bytes";
if (rs > 0) {
addr_lr.set(uint(PRIVATE->raddr_.sin_addr.s_addr), ntohs(PRIVATE->raddr_.sin_port));
//piCoutObj << "read from" << ip_r << ":" << port_r << rs << "bytes";
// piCoutObj << "read from" << ip_r << ":" << port_r << rs << "bytes";
received(read_to, rs);
}
//else piCoutObj << "read returt" << rs << ", error" << ethErrorString();
// else piCoutObj << "read returt" << rs << ", error" << ethErrorString();
return rs;
}
}
default: break;
}
return -1;
@@ -820,39 +819,42 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
if (sock == -1) init();
if (sock == -1 || !isWriteable()) {
//piCoutObj << "Can`t send to uninitialized socket";
// piCoutObj << "Can`t send to uninitialized socket";
return -1;
}
//piCoutObj << "sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
// piCoutObj << "sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
int ret = 0;
switch (type()) {
case UDP:
PRIVATE->saddr_.sin_port = htons(addr_s.port());
PRIVATE->saddr_.sin_port = htons(addr_s.port());
PRIVATE->saddr_.sin_addr.s_addr = addr_s.ip();
PRIVATE->saddr_.sin_family = AF_INET;
//piCoutObj << "write to" << ip_s << ":" << port_s << "socket" << sock_s << max_size << "bytes ...";
return ethSendto(sock_s, data, max_size,
PRIVATE->saddr_.sin_family = AF_INET;
// piCoutObj << "write to" << ip_s << ":" << port_s << "socket" << sock_s << max_size << "bytes ...";
return ethSendto(sock_s,
data,
max_size,
#ifndef WINDOWS
isOptionSet(BlockingWrite) ? 0 : MSG_DONTWAIT
isOptionSet(BlockingWrite) ? 0 : MSG_DONTWAIT
#else
0
0
#endif
, (sockaddr * )&PRIVATE->saddr_, sizeof(PRIVATE->saddr_));
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok";
,
(sockaddr *)&PRIVATE->saddr_,
sizeof(PRIVATE->saddr_));
// piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok";
case TCP_Client: {
if (connecting_) {
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
addr_r.set(path());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
//piCoutObj << "connect to " << ip << ":" << port_;
// piCoutObj << "connect to " << ip << ":" << port_;
connected_ = connectTCP();
if (!connected_)
piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
if (!connected_) piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
opened_.exchange(connected_);
if (connected_) {
connecting_ = false;
@@ -860,10 +862,10 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
}
}
if (!connected_) return -1;
auto disconnectFunc = [this](){
auto disconnectFunc = [this]() {
if (connected_.exchange(false)) {
opened_ = false;
//piCoutObj << "Disconnect on write," << ethErrorString();
// piCoutObj << "Disconnect on write," << ethErrorString();
closeSocket(sock);
init();
disconnected(true);
@@ -876,7 +878,7 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
return -1;
}
} else {
ssize_t remain_size = max_size;
ssize_t remain_size = max_size;
const char * remain_data = (const char *)data;
while (remain_size > 0) {
int sr = ::send(sock, remain_data, remain_size, 0);
@@ -888,7 +890,7 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
if (err == EAGAIN || err == EWOULDBLOCK) {
#endif
piMinSleep();
//piCoutObj << "wait for write";
// piCoutObj << "wait for write";
continue;
} else {
disconnectFunc();
@@ -899,7 +901,8 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
remain_size -= sr;
}
}
return ret;}
return ret;
}
default: break;
}
return -1;
@@ -919,13 +922,13 @@ PIIODevice::DeviceInfoFlags PIEthernet::deviceInfoFlags() const {
void PIEthernet::clientDeleted(PIObject * o) {
clients_mutex.lock();
clients_.removeOne((PIEthernet*)o);
clients_.removeOne((PIEthernet *)o);
clients_mutex.unlock();
}
void PIEthernet::server_func(void * eth) {
PIEthernet * ce = (PIEthernet * )eth;
PIEthernet * ce = (PIEthernet *)eth;
if (ce->listen_threaded) {
if (!ce->server_bounded) {
if (!ce->listen(false)) {
@@ -949,9 +952,9 @@ void PIEthernet::server_func(void * eth) {
return;
}
#endif
//piCout << "server" << "accept ...";
int s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
//piCout << "server" << "accept done" << ethErrorString();
// piCout << "server" << "accept ...";
int s = accept(ce->sock, (sockaddr *)&client_addr, &slen);
// piCout << "server" << "accept done" << ethErrorString();
if (s == -1) {
int lerr = ethErrorCore();
#ifdef WINDOWS
@@ -976,7 +979,7 @@ void PIEthernet::server_func(void * eth) {
ce->clients_ << e;
ce->clients_mutex.unlock();
ce->newConnection(e);
//cout << "connected " << ip << endl;
// cout << "connected " << ip << endl;
}
@@ -992,19 +995,20 @@ void PIEthernet::setType(Type t, bool reopen) {
bool PIEthernet::connectTCP() {
::connect(sock, (sockaddr * )&(PRIVATE->addr_), sizeof(PRIVATE->addr_));
//piCout << errorString();
::connect(sock, (sockaddr *)&(PRIVATE->addr_), sizeof(PRIVATE->addr_));
// piCout << errorString();
#ifdef WINDOWS
long wr = waitForEvent(PRIVATE->event, FD_CONNECT | FD_CLOSE);
switch (wr) {
case FD_CONNECT:
//piCout << "fd_connect ...";
// piCout << "fd_connect ...";
return ethIsWriteable(sock);
default: break;
}
#else
if (PRIVATE->event.wait(sock, PIWaitEvent::CheckWrite)) {
if (ethIsWriteable(sock)) return true;
if (ethIsWriteable(sock))
return true;
else {
closeSocket(sock);
init();
@@ -1019,16 +1023,15 @@ bool PIEthernet::connectTCP() {
long PIEthernet::waitForEvent(PIWaitEvent & event, long mask) {
if (!event.isCreate() || sock < 0) return 0;
if (WSAEventSelect(sock, event.getEvent(), mask) == SOCKET_ERROR) {
if (ethErrorCore() == WSAEINPROGRESS)
return 0;
if (ethErrorCore() == WSAEINPROGRESS) return 0;
}
if (event.wait()) {
//DWORD wr = WSAWaitForMultipleEvents(1, &(PRIVATE->read_event), FALSE, WSA_INFINITE, TRUE);
//if (wr == WSA_WAIT_EVENT_0) {
// DWORD wr = WSAWaitForMultipleEvents(1, &(PRIVATE->read_event), FALSE, WSA_INFINITE, TRUE);
// if (wr == WSA_WAIT_EVENT_0) {
WSANETWORKEVENTS events;
memset(&events, 0, sizeof(events));
WSAEnumNetworkEvents(sock, event.getEvent(), &events);
//piCoutObj << "wait result" << events.lNetworkEvents;
// piCoutObj << "wait result" << events.lNetworkEvents;
return events.lNetworkEvents;
}
return 0;
@@ -1037,8 +1040,8 @@ long PIEthernet::waitForEvent(PIWaitEvent & event, long mask) {
bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
PIConfig::Entry * em = (PIConfig::Entry *)e_main;
PIConfig::Entry * ep = (PIConfig::Entry *)e_parent;
setReadIP(readDeviceSetting<PIString>("ip", readIP(), em, ep));
setReadPort(readDeviceSetting<int>("port", readPort(), em, ep));
setParameter(PIEthernet::Broadcast, readDeviceSetting<bool>("broadcast", isParameterSet(PIEthernet::Broadcast), em, ep));
@@ -1061,7 +1064,7 @@ PIString PIEthernet::constructFullPathDevice() const {
ret += ":" + readIP() + ":" + PIString::fromNumber(readPort());
if (type() == PIEthernet::UDP) {
ret += ":" + sendIP() + ":" + PIString::fromNumber(sendPort());
piForeachC (PIString & m, multicastGroups())
piForeachC(PIString & m, multicastGroups())
ret += ":mcast:" + m;
}
return ret;
@@ -1070,7 +1073,7 @@ PIString PIEthernet::constructFullPathDevice() const {
void PIEthernet::configureFromFullPathDevice(const PIString & full_path) {
PIStringList pl = full_path.split(":");
bool mcast = false;
bool mcast = false;
for (int i = 0; i < pl.size_s(); ++i) {
PIString p(pl[i]);
switch (i) {
@@ -1079,14 +1082,26 @@ void PIEthernet::configureFromFullPathDevice(const PIString & full_path) {
if (p == "udp") setType(UDP);
if (p == "tcp") setType(TCP_Client);
break;
case 1: setReadIP(p); setSendIP(p); break;
case 2: setReadPort(p.toInt()); setSendPort(p.toInt()); break;
case 1:
setReadIP(p);
setSendIP(p);
break;
case 2:
setReadPort(p.toInt());
setSendPort(p.toInt());
break;
case 3: setSendIP(p); break;
case 4: setSendPort(p.toInt()); break;
}
if (i <= 4) continue;
if (i % 2 == 1) {if (p.toLowerCase() == "mcast") mcast = true;}
else {if (mcast) {joinMulticastGroup(p); mcast = false;}}
if (i % 2 == 1) {
if (p.toLowerCase() == "mcast") mcast = true;
} else {
if (mcast) {
joinMulticastGroup(p);
mcast = false;
}
}
}
}
@@ -1095,7 +1110,8 @@ PIPropertyStorage PIEthernet::constructVariantDevice() const {
PIPropertyStorage ret;
PIVariantTypes::Enum e;
e << "UDP" << "TCP";
e << "UDP"
<< "TCP";
if (type() == PIEthernet::UDP)
e.selectValue(0);
else
@@ -1118,21 +1134,21 @@ void PIEthernet::configureFromVariantDevice(const PIPropertyStorage & d) {
setSendIP(d.propertyValueByName("send IP").toString());
setSendPort(d.propertyValueByName("send port").toInt());
PIStringList mcgl = d.propertyValueByName("multicast").toStringList();
piForeachC (PIString & g, mcgl) {
piForeachC(PIString & g, mcgl) {
joinMulticastGroup(g);
}
}
PIEthernet::InterfaceList PIEthernet::interfaces() {
//piCout << "PIEthernet::interfaces()";
// piCout << "PIEthernet::interfaces()";
PIEthernet::InterfaceList il;
Interface ci;
ci.index = -1;
ci.mtu = 1500;
ci.mtu = 1500;
#ifdef WINDOWS
int ret = 0;
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
int ret = 0;
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO));
if (!pAdapterInfo) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersInfo";
@@ -1149,9 +1165,9 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
while (pAdapter) {
ci.name = PIString(pAdapter->AdapterName);
ci.name = PIString(pAdapter->AdapterName);
ci.index = pAdapter->Index;
ci.mac = macFromBytes(PIByteArray(pAdapter->Address, pAdapter->AddressLength));
ci.mac = macFromBytes(PIByteArray(pAdapter->Address, pAdapter->AddressLength));
ci.flags = PIEthernet::ifActive | PIEthernet::ifRunning;
if (pAdapter->Type == MIB_IF_TYPE_PPP) ci.flags |= PIEthernet::ifPTP;
if (pAdapter->Type == MIB_IF_TYPE_LOOPBACK) ci.flags |= PIEthernet::ifLoopback;
@@ -1159,7 +1175,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ci.ptp.clear();
IP_ADDR_STRING * as = &(pAdapter->IpAddressList);
while (as) {
// piCout << "[pAdapter]" << ci.name << PIString(as->IpAddress.String);
// piCout << "[pAdapter]" << ci.name << PIString(as->IpAddress.String);
ci.address = PIStringAscii(as->IpAddress.String);
ci.netmask = PIStringAscii(as->IpMask.String);
if (ci.address == "0.0.0.0") {
@@ -1174,21 +1190,17 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
} else {
switch (ret) {
case ERROR_NO_DATA: break;
case ERROR_NOT_SUPPORTED:
piCout << "[PIEthernet] GetAdaptersInfo not supported";
break;
default:
piCout << "[PIEthernet] GetAdaptersInfo failed with error:" << ret;
case ERROR_NOT_SUPPORTED: piCout << "[PIEthernet] GetAdaptersInfo not supported"; break;
default: piCout << "[PIEthernet] GetAdaptersInfo failed with error:" << ret;
}
}
if (pAdapterInfo)
HeapFree(GetProcessHeap(), 0, pAdapterInfo);
if (pAdapterInfo) HeapFree(GetProcessHeap(), 0, pAdapterInfo);
#else
#ifdef MICRO_PIP
#else
# ifdef ANDROID
# ifdef MICRO_PIP
# else
# ifdef ANDROID
struct ifconf ifc;
int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
ifc.ifc_len = 256;
ifc.ifc_buf = new char[ifc.ifc_len];
if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
@@ -1200,24 +1212,21 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
PIStringList inl;
struct ifreq ir;
for (int i = 0; i < icnt; ++i) {
ci.flags = 0;
ci.flags = 0;
PIString in = PIStringAscii(ifc.ifc_req[i].ifr_name);
if (in.isEmpty()) continue;
ci.name = in;
strcpy(ir.ifr_name, in.dataAscii());
if (ioctl(s, SIOCGIFHWADDR, &ir) == 0)
ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6));
if (ioctl(s, SIOCGIFADDR, &ir) >= 0)
ci.address = getSockAddr(&ir.ifr_addr);
if (ioctl(s, SIOCGIFNETMASK, &ir) >= 0)
ci.netmask = getSockAddr(&ir.ifr_addr);
if (ioctl(s, SIOCGIFHWADDR, &ir) == 0) ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6));
if (ioctl(s, SIOCGIFADDR, &ir) >= 0) ci.address = getSockAddr(&ir.ifr_addr);
if (ioctl(s, SIOCGIFNETMASK, &ir) >= 0) ci.netmask = getSockAddr(&ir.ifr_addr);
ioctl(s, SIOCGIFMTU, &ci.mtu);
if (ci.address == "127.0.0.1") ci.flags |= PIEthernet::ifLoopback;
il << ci;
}
delete ifc.ifc_buf;
# else
struct ifaddrs * ret, * cif = 0;
# else
struct ifaddrs *ret, *cif = 0;
int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (getifaddrs(&ret) == 0) {
cif = ret;
@@ -1230,12 +1239,12 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
cif = cif->ifa_next;
continue;
}
ci.name = PIString(cif->ifa_name);
ci.name = PIString(cif->ifa_name);
ci.address = getSockAddr(cif->ifa_addr);
ci.netmask = getSockAddr(cif->ifa_netmask);
ci.mac.clear();
# ifdef QNX
# ifndef BLACKBERRY
# ifdef QNX
# ifndef BLACKBERRY
int fd = ::open((PIString("/dev/io-net/") + ci.name).dataAscii(), O_RDONLY);
if (fd != 0) {
nic_config_t nic;
@@ -1243,20 +1252,20 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
::close(fd);
ci.mac = macFromBytes(PIByteArray(nic.permanent_address, 6));
}
# endif
# else
# ifdef MAC_OS
# endif
# else
# ifdef MAC_OS
PIString req = PISystemInfo::instance()->ifconfigPath + " " + ci.name + " | grep ether";
FILE * fp = popen(req.dataAscii(), "r");
FILE * fp = popen(req.dataAscii(), "r");
if (fp != 0) {
char in[256];
if (fgets(in, 256, fp) != 0) {
req = PIString(in).trim();
req = PIString(in).trim();
ci.mac = req.cutLeft(req.find(" ") + 1).trim().toUpperCase();
}
pclose(fp);
}
# else
# else
if (s != -1) {
struct ifreq ir;
strcpy(ir.ifr_name, cif->ifa_name);
@@ -1265,8 +1274,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ci.mtu = ir.ifr_mtu;
}
}
# endif
# endif
# endif
# endif
ci.flags = 0;
if (cif->ifa_flags & IFF_UP) ci.flags |= PIEthernet::ifActive;
if (cif->ifa_flags & IFF_RUNNING) ci.flags |= PIEthernet::ifRunning;
@@ -1276,10 +1285,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
if (cif->ifa_flags & IFF_POINTOPOINT) ci.flags |= PIEthernet::ifPTP;
ci.broadcast.clear();
ci.ptp.clear();
if (ci.flags[PIEthernet::ifBroadcast])
ci.broadcast = getSockAddr(cif->ifa_broadaddr);
if (ci.flags[PIEthernet::ifPTP])
ci.ptp = getSockAddr(cif->ifa_dstaddr);
if (ci.flags[PIEthernet::ifBroadcast]) ci.broadcast = getSockAddr(cif->ifa_broadaddr);
if (ci.flags[PIEthernet::ifPTP]) ci.ptp = getSockAddr(cif->ifa_dstaddr);
ci.index = if_nametoindex(cif->ifa_name);
il << ci;
cif = cif->ifa_next;
@@ -1288,7 +1295,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
} else
piCout << "[PIEthernet] Can`t get interfaces:" << errorString();
if (s != -1) ::close(s);
# endif
# endif
# endif
#endif
return il;
@@ -1306,10 +1313,9 @@ PIEthernet::Address PIEthernet::interfaceAddress(const PIString & interface_) {
int s = ::socket(AF_INET, SOCK_DGRAM, 0);
ioctl(s, SIOCGIFADDR, &ifr);
::close(s);
struct sockaddr_in * sa = (struct sockaddr_in * )&ifr.ifr_addr;
struct sockaddr_in * sa = (struct sockaddr_in *)&ifr.ifr_addr;
return Address(uint(sa->sin_addr.s_addr));
#endif
}
@@ -1317,13 +1323,13 @@ PIVector<PIEthernet::Address> PIEthernet::allAddresses() {
PIEthernet::InterfaceList il = interfaces();
PIVector<Address> ret;
bool has_127 = false;
piForeachC (PIEthernet::Interface & i, il) {
piForeachC(PIEthernet::Interface & i, il) {
if (i.address == "127.0.0.1") has_127 = true;
Address a(i.address);
if (a.ip() == 0) continue;
ret << a;
}
// piCout << "[PIEthernet::allAddresses]" << al;
// piCout << "[PIEthernet::allAddresses]" << al;
if (!has_127) ret << Address("127.0.0.1");
return ret;
}
@@ -1343,8 +1349,14 @@ int PIEthernet::ethErrorCore() {
PIString PIEthernet::ethErrorString() {
#ifdef WINDOWS
char * msg = nullptr;
int err = WSAGetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
int err = WSAGetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&msg,
0,
NULL);
PIString ret = PIStringAscii("code ") + PIString::fromNumber(err) + PIStringAscii(" - ");
if (msg) {
ret += PIString::fromSystem(msg).trim();
@@ -1362,9 +1374,11 @@ int PIEthernet::ethRecv(int sock, void * buf, int size, int flags) {
if (sock < 0) return -1;
return recv(sock,
#ifdef WINDOWS
(char*)
(char *)
#endif
buf, size, flags);
buf,
size,
flags);
}
@@ -1376,9 +1390,13 @@ int PIEthernet::ethRecvfrom(int sock, void * buf, int size, int flags, sockaddr
socklen_t len = sizeof(sockaddr);
return recvfrom(sock,
# ifdef WINDOWS
(char*)
(char *)
# endif
buf, size, flags, addr, &len);
buf,
size,
flags,
addr,
&len);
#endif
}
@@ -1387,33 +1405,41 @@ int PIEthernet::ethSendto(int sock, const void * buf, int size, int flags, socka
if (sock < 0) return -1;
return sendto(sock,
#ifdef WINDOWS
(const char*)
(const char *)
#endif
buf, size, flags, addr, addr_len);
buf,
size,
flags,
addr,
addr_len);
}
void PIEthernet::ethClosesocket(int sock, bool shutdown) {
//piCout << "close socket" << sock << shutdown;
// piCout << "close socket" << sock << shutdown;
if (sock < 0) return;
if (shutdown) ::shutdown(sock,
if (shutdown)
::shutdown(sock,
#ifdef WINDOWS
SD_BOTH);
closesocket(sock);
SD_BOTH);
closesocket(sock);
#else
SHUT_RDWR);
::close(sock);
SHUT_RDWR);
::close(sock);
#endif
}
int PIEthernet::ethSetsockopt(int sock, int level, int optname, const void * optval, int optlen) {
if (sock < 0) return -1;
return setsockopt(sock, level, optname,
return setsockopt(sock,
level,
optname,
#ifdef WINDOWS
(char*)
(char *)
#endif
optval, optlen);
optval,
optlen);
}
@@ -1424,7 +1450,7 @@ int PIEthernet::ethSetsockoptInt(int sock, int level, int optname, int value) {
#else
int
#endif
so = value;
so = value;
return ethSetsockopt(sock, level, optname, &so, sizeof(so));
}
@@ -1436,7 +1462,7 @@ int PIEthernet::ethSetsockoptBool(int sock, int level, int optname, bool value)
#else
int
#endif
so = (value ? 1 : 0);
so = (value ? 1 : 0);
return ethSetsockopt(sock, level, optname, &so, sizeof(so));
}
@@ -1473,9 +1499,9 @@ bool PIEthernet::ethIsWriteable(int sock) {
::select(0, nullptr, &fd_test, nullptr, &timeout);
return FD_ISSET(sock, &fd_test);
#else
int ret = 0;
int ret = 0;
socklen_t len = sizeof(ret);
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)&ret, &len);
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&ret, &len);
return ret == 0;
#endif
}
+287 -221
View File
@@ -5,61 +5,61 @@
* \~russian Устройство Ethernet
*/
/*
PIP - Platform Independent Primitives
Ethernet, UDP/TCP Broadcast/Multicast
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Ethernet, UDP/TCP Broadcast/Multicast
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIETHERNET_H
#define PIETHERNET_H
#include "pitimer.h"
#include "piiodevice.h"
#include "pitimer.h"
#ifdef ANDROID
struct
struct
#else
class
class
#endif
sockaddr;
class PIP_EXPORT PIEthernet: public PIIODevice
{
class PIP_EXPORT PIEthernet: public PIIODevice {
PIIODEVICE(PIEthernet, "eth");
friend class PIPeer;
public:
//! Contructs UDP %PIEthernet with empty read address
explicit PIEthernet();
//! \brief Type of %PIEthernet
enum Type {
UDP /** UDP - User Datagram Protocol */ ,
TCP_Client /** TCP client - allow connection to TCP server */ ,
UDP /** UDP - User Datagram Protocol */,
TCP_Client /** TCP client - allow connection to TCP server */,
TCP_Server /** TCP server - receive connections from TCP clients */
};
//! \brief Parameters of %PIEthernet
enum Parameters {
ReuseAddress /** Rebind address if there is already binded. Enabled by default */ = 0x1,
Broadcast /** Broadcast send. Disabled by default */ = 0x2,
Broadcast /** Broadcast send. Disabled by default */ = 0x2,
SeparateSockets /** If this parameter is set, %PIEthernet will initialize two different sockets,
for receive and send, instead of single one. Disabled by default */ = 0x4,
MulticastLoop /** Enable receiving multicast packets from same host. Enabled by default */ = 0x8,
KeepConnection /** Automatic reconnect TCP connection on disconnect. Enabled by default */ = 0x10,
for receive and send, instead of single one. Disabled by default */
= 0x4,
MulticastLoop /** Enable receiving multicast packets from same host. Enabled by default */ = 0x8,
KeepConnection /** Automatic reconnect TCP connection on disconnect. Enabled by default */ = 0x10,
DisonnectOnTimeout /** Disconnect TCP connection on read timeout expired. Disabled by default */ = 0x20
};
@@ -67,8 +67,8 @@ public:
//! \brief IPv4 network address, IP and port
class PIP_EXPORT Address {
friend class PIEthernet;
public:
public:
//! Contructs %Address with binary representation of IP and port
Address(uint ip = 0, ushort port = 0);
@@ -79,10 +79,10 @@ public:
Address(const PIString & ip, ushort port);
//! Returns binary IP
uint ip() const {return ip_;}
uint ip() const { return ip_; }
//! Returns port
ushort port() const {return port_;}
ushort port() const { return port_; }
//! Returns string IP
PIString ipString() const;
@@ -121,6 +121,7 @@ public:
static Address resolve(const PIString & host, ushort port);
static void splitIPPort(const PIString & ipp, PIString * ip, int * port);
private:
void initIP(const PIString & _ip);
union {
@@ -132,301 +133,351 @@ public:
//! Contructs %PIEthernet with type "type", read address "ip_port" and parameters "params"
explicit PIEthernet(Type type, const PIString & ip_port = PIString(), const PIFlags<Parameters> params = PIEthernet::ReuseAddress | PIEthernet::MulticastLoop | PIEthernet::KeepConnection);
explicit PIEthernet(Type type,
const PIString & ip_port = PIString(),
const PIFlags<Parameters> params = PIEthernet::ReuseAddress | PIEthernet::MulticastLoop |
PIEthernet::KeepConnection);
virtual ~PIEthernet();
//! Set read address
void setReadAddress(const PIString & ip, int port) {addr_r.set(ip, port); setPath(addr_r.toString());}
void setReadAddress(const PIString & ip, int port) {
addr_r.set(ip, port);
setPath(addr_r.toString());
}
//! Set read address in format "i.i.i.i:p"
void setReadAddress(const PIString & ip_port) {addr_r.set(ip_port); setPath(addr_r.toString());}
void setReadAddress(const PIString & ip_port) {
addr_r.set(ip_port);
setPath(addr_r.toString());
}
//! Set read address
void setReadAddress(const Address & addr) {addr_r = addr; setPath(addr_r.toString());}
void setReadAddress(const Address & addr) {
addr_r = addr;
setPath(addr_r.toString());
}
//! Set read IP
void setReadIP(const PIString & ip) {addr_r.setIP(ip); setPath(addr_r.toString());}
void setReadIP(const PIString & ip) {
addr_r.setIP(ip);
setPath(addr_r.toString());
}
//! Set read port
void setReadPort(int port) {addr_r.setPort(port); setPath(addr_r.toString());}
void setReadPort(int port) {
addr_r.setPort(port);
setPath(addr_r.toString());
}
//! Set send address
void setSendAddress(const PIString & ip, int port) {addr_s.set(ip, port);}
void setSendAddress(const PIString & ip, int port) { addr_s.set(ip, port); }
//! Set send address in format "i.i.i.i:p"
void setSendAddress(const PIString & ip_port) {addr_s.set(ip_port);}
void setSendAddress(const PIString & ip_port) { addr_s.set(ip_port); }
//! Set send address
void setSendAddress(const Address & addr) {addr_s = addr;}
//! Set send IP
void setSendIP(const PIString & ip) {addr_s.setIP(ip);}
//! Set send port
void setSendPort(int port) {addr_s.setPort(port);}
//! Returns read address in format "i.i.i.i:p"
Address readAddress() const {return addr_r;}
//! Returns read IP
PIString readIP() const {return addr_r.ipString();}
//! Returns read port
int readPort() const {return addr_r.port();}
//! Returns send address in format "i.i.i.i:p"
Address sendAddress() const {return addr_s;}
//! Returns send IP
PIString sendIP() const {return addr_s.ipString();}
//! Returns send port
int sendPort() const {return addr_s.port();}
//! Returns address of last received UDP packet in format "i.i.i.i:p"
Address lastReadAddress() const {return addr_lr;}
//! Returns IP of last received UDP packet
PIString lastReadIP() const {return addr_lr.ipString();}
//! Returns port of last received UDP packet
int lastReadPort() const {return addr_lr.port();}
void setSendAddress(const Address & addr) { addr_s = addr; }
//! Set send IP
void setSendIP(const PIString & ip) { addr_s.setIP(ip); }
//! Set send port
void setSendPort(int port) { addr_s.setPort(port); }
//! Returns read address in format "i.i.i.i:p"
Address readAddress() const { return addr_r; }
//! Returns read IP
PIString readIP() const { return addr_r.ipString(); }
//! Returns read port
int readPort() const { return addr_r.port(); }
//! Returns send address in format "i.i.i.i:p"
Address sendAddress() const { return addr_s; }
//! Returns send IP
PIString sendIP() const { return addr_s.ipString(); }
//! Returns send port
int sendPort() const { return addr_s.port(); }
//! Returns address of last received UDP packet in format "i.i.i.i:p"
Address lastReadAddress() const { return addr_lr; }
//! Returns IP of last received UDP packet
PIString lastReadIP() const { return addr_lr.ipString(); }
//! Returns port of last received UDP packet
int lastReadPort() const { return addr_lr.port(); }
//! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {params = parameters_;}
void setParameters(PIFlags<PIEthernet::Parameters> parameters_) { params = parameters_; }
//! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this
void setParameter(PIEthernet::Parameters parameter, bool on = true) {params.setFlag(parameter, on);}
void setParameter(PIEthernet::Parameters parameter, bool on = true) { params.setFlag(parameter, on); }
//! Returns if parameter "parameter" is set
bool isParameterSet(PIEthernet::Parameters parameter) const {return params[parameter];}
bool isParameterSet(PIEthernet::Parameters parameter) const { return params[parameter]; }
//! Returns parameters
PIFlags<PIEthernet::Parameters> parameters() const {return params;}
PIFlags<PIEthernet::Parameters> parameters() const { return params; }
//! Returns %PIEthernet type
Type type() const {return eth_type;}
//! Returns read timeout
double readTimeout() const {return property("readTimeout").toDouble();}
//! Returns write timeout
double writeTimeout() const {return property("writeTimeout").toDouble();}
//! Set timeout for read
void setReadTimeout(double ms) {setProperty("readTimeout", ms);}
//! Set timeout for write
void setWriteTimeout(double ms) {setProperty("writeTimeout", ms);}
//! Returns TTL (Time To Live)
int TTL() const {return property("TTL").toInt();}
//! Returns multicast TTL (Time To Live)
int multicastTTL() const {return property("MulticastTTL").toInt();}
//! Set TTL (Time To Live), default is 64
void setTTL(int ttl) {setProperty("TTL", ttl);}
//! Set multicast TTL (Time To Live), default is 1
void setMulticastTTL(int ttl) {setProperty("MulticastTTL", ttl);}
Type type() const { return eth_type; }
//! Returns read timeout
double readTimeout() const { return property("readTimeout").toDouble(); }
//! Returns write timeout
double writeTimeout() const { return property("writeTimeout").toDouble(); }
//! Set timeout for read
void setReadTimeout(double ms) { setProperty("readTimeout", ms); }
//! Set timeout for write
void setWriteTimeout(double ms) { setProperty("writeTimeout", ms); }
//! Returns TTL (Time To Live)
int TTL() const { return property("TTL").toInt(); }
//! Returns multicast TTL (Time To Live)
int multicastTTL() const { return property("MulticastTTL").toInt(); }
//! Set TTL (Time To Live), default is 64
void setTTL(int ttl) { setProperty("TTL", ttl); }
//! Set multicast TTL (Time To Live), default is 1
void setMulticastTTL(int ttl) { setProperty("MulticastTTL", ttl); }
//! Join to multicast group with address "group". Use only for UDP
bool joinMulticastGroup(const PIString & group);
//! Leave multicast group with address "group". Use only for UDP
bool leaveMulticastGroup(const PIString & group);
//! Returns joined multicast groups. Use only for UDP
const PIStringList & multicastGroups() const {return mcast_groups;}
const PIStringList & multicastGroups() const { return mcast_groups; }
//! If \"threaded\" queue connect to TCP server with address \a readAddress() in
//! any \a read() or \a write() call. Otherwise connect immediate.
//! Use only for TCP_Client
bool connect(bool threaded = true);
//! Connect to TCP server with address "ip":"port". Use only for TCP_Client
bool connect(const PIString & ip, int port, bool threaded = true) {setPath(ip + PIStringAscii(":") + PIString::fromNumber(port)); return connect(threaded);}
bool connect(const PIString & ip, int port, bool threaded = true) {
setPath(ip + PIStringAscii(":") + PIString::fromNumber(port));
return connect(threaded);
}
//! Connect to TCP server with address "ip_port". Use only for TCP_Client
bool connect(const PIString & ip_port, bool threaded = true) {setPath(ip_port); return connect(threaded);}
bool connect(const PIString & ip_port, bool threaded = true) {
setPath(ip_port);
return connect(threaded);
}
//! Connect to TCP server with address "addr". Use only for TCP_Client
bool connect(const Address & addr, bool threaded = true) {setPath(addr.toString()); return connect(threaded);}
bool connect(const Address & addr, bool threaded = true) {
setPath(addr.toString());
return connect(threaded);
}
//! Returns if %PIEthernet connected to TCP server. Use only for TCP_Client
bool isConnected() const {return connected_;}
bool isConnected() const { return connected_; }
//! Returns if %PIEthernet is connecting to TCP server. Use only for TCP_Client
bool isConnecting() const {return connecting_;}
bool isConnecting() const { return connecting_; }
//! Start listen for incoming TCP connections on address \a readAddress(). Use only for TCP_Server
bool listen(bool threaded = false);
//! Start listen for incoming TCP connections on address "ip":"port". Use only for TCP_Server
bool listen(const PIString & ip, int port, bool threaded = false) {return listen(PIEthernet::Address(ip, port), threaded);}
bool listen(const PIString & ip, int port, bool threaded = false) { return listen(PIEthernet::Address(ip, port), threaded); }
//! Start listen for incoming TCP connections on address "ip_port". Use only for TCP_Server
bool listen(const PIString & ip_port, bool threaded = false) {return listen(PIEthernet::Address(ip_port), threaded);}
bool listen(const PIString & ip_port, bool threaded = false) { return listen(PIEthernet::Address(ip_port), threaded); }
//! Start listen for incoming TCP connections on address "addr". Use only for TCP_Server
bool listen(const Address & addr, bool threaded = false);
PIEthernet * client(int index) {return clients_[index];}
int clientsCount() const {return clients_.size_s();}
PIVector<PIEthernet * > clients() const {return clients_;}
PIEthernet * client(int index) { return clients_[index]; }
int clientsCount() const { return clients_.size_s(); }
PIVector<PIEthernet *> clients() const { return clients_; }
//! Send data "data" with size "size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
bool send(const void * data, int size, bool threaded = false);
//! Send data "data" with size "size" to address "ip":"port"
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {return send(PIEthernet::Address(ip, port), data, size, threaded);}
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {
return send(PIEthernet::Address(ip, port), data, size, threaded);
}
//! Send data "data" with size "size" to address "ip_port"
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {return send(PIEthernet::Address(ip_port), data, size, threaded);}
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {
return send(PIEthernet::Address(ip_port), data, size, threaded);
}
//! Send data "data" with size "size" to address "addr"
bool send(const Address & addr, const void * data, int size, bool threaded = false);
//! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
bool send(const PIByteArray & data, bool threaded = false);
//! Send data "data" to address "ip":"port" for UDP
bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {return send(PIEthernet::Address(ip, port), data, threaded);}
bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {
return send(PIEthernet::Address(ip, port), data, threaded);
}
//! Send data "data" to address "ip_port" for UDP
bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {return send(PIEthernet::Address(ip_port), data, threaded);}
bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {
return send(PIEthernet::Address(ip_port), data, threaded);
}
//! Send data "data" to address "addr" for UDP
bool send(const Address & addr, const PIByteArray & data, bool threaded = false);
bool canWrite() const override {return mode() & WriteOnly;}
bool canWrite() const override { return mode() & WriteOnly; }
void interrupt() override;
int socket() const {return sock;}
EVENT1(newConnection, PIEthernet * , client);
int socket() const { return sock; }
EVENT1(newConnection, PIEthernet *, client);
EVENT0(connected);
EVENT1(disconnected, bool, withError);
//! Flags of network interface
enum InterfaceFlag {
ifActive /** Is active */ = 0x1,
ifRunning /** Is running */ = 0x2,
ifActive /** Is active */ = 0x1,
ifRunning /** Is running */ = 0x2,
ifBroadcast /** Support broadcast */ = 0x4,
ifMulticast /** Support multicast */ = 0x8,
ifLoopback /** Is loopback */ = 0x10,
ifPTP /** Is point-to-point */ = 0x20
ifLoopback /** Is loopback */ = 0x10,
ifPTP /** Is point-to-point */ = 0x20
};
//! %PIFlags of network interface flags
typedef PIFlags<InterfaceFlag> InterfaceFlags;
//! Network interface descriptor
struct PIP_EXPORT Interface {
//! System index
int index;
//! MTU
int mtu;
//! System name
PIString name;
//! MAC address in format "hh:hh:hh:hh:hh:hh" or empty if there is no MAC address
PIString mac;
//! IP address in format "i.i.i.i" or empty if there is no IP address
PIString address;
//! Netmask of IP address in format "i.i.i.i" or empty if there is no netmask
PIString netmask;
//! Broadcast address in format "i.i.i.i" or empty if there is no broadcast address
PIString broadcast;
//! Point-to-point address or empty if there is no point-to-point address
PIString ptp;
//! Flags of interface
InterfaceFlags flags;
//! Returns if interface is active
bool isActive() const {return flags[PIEthernet::ifActive];}
bool isActive() const { return flags[PIEthernet::ifActive]; }
//! Returns if interface is running
bool isRunning() const {return flags[PIEthernet::ifRunning];}
bool isRunning() const { return flags[PIEthernet::ifRunning]; }
//! Returns if interface support broadcast
bool isBroadcast() const {return flags[PIEthernet::ifBroadcast];}
bool isBroadcast() const { return flags[PIEthernet::ifBroadcast]; }
//! Returns if interface support multicast
bool isMulticast() const {return flags[PIEthernet::ifMulticast];}
bool isMulticast() const { return flags[PIEthernet::ifMulticast]; }
//! Returns if interface is loopback
bool isLoopback() const {return flags[PIEthernet::ifLoopback];}
bool isLoopback() const { return flags[PIEthernet::ifLoopback]; }
//! Returns if interface is point-to-point
bool isPTP() const {return flags[PIEthernet::ifPTP];}
bool isPTP() const { return flags[PIEthernet::ifPTP]; }
};
//! Array of \a Interface with some features
class PIP_EXPORT InterfaceList: public PIVector<PIEthernet::Interface> {
public:
InterfaceList(): PIVector<PIEthernet::Interface>() {}
//! Get interface with system index "index" or 0 if there is no one
const Interface * getByIndex(int index) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].index == index) return &((*this)[i]); return 0;}
const Interface * getByIndex(int index) const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].index == index) return &((*this)[i]);
return 0;
}
//! Get interface with system name "name" or 0 if there is no one
const Interface * getByName(const PIString & name) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].name == name) return &((*this)[i]); return 0;}
const Interface * getByName(const PIString & name) const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].name == name) return &((*this)[i]);
return 0;
}
//! Get interface with IP address "address" or 0 if there is no one
const Interface * getByAddress(const PIString & address) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].address == address) return &((*this)[i]); return 0;}
const Interface * getByAddress(const PIString & address) const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].address == address) return &((*this)[i]);
return 0;
}
//! Get loopback interface or 0 if there is no one
const Interface * getLoopback() const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].isLoopback()) return &((*this)[i]); return 0;}
const Interface * getLoopback() const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].isLoopback()) return &((*this)[i]);
return 0;
}
};
//! Returns all system network interfaces
static InterfaceList interfaces();
static PIEthernet::Address interfaceAddress(const PIString & interface_);
//! Returns all system network IP addresses
static PIVector<PIEthernet::Address> allAddresses();
static PIString macFromBytes(const PIByteArray & mac);
static PIByteArray macToBytes(const PIString & mac);
static PIString applyMask(const PIString & ip, const PIString & mask);
static Address applyMask(const Address & ip, const Address & mask);
static Address applyMask(const Address & ip, const Address & mask);
static PIString getBroadcast(const PIString & ip, const PIString & mask);
static Address getBroadcast(const Address & ip, const Address & mask);
static Address getBroadcast(const Address & ip, const Address & mask);
//! \events
//! \{
//! \events
//! \{
//! \fn void newConnection(PIEthernet * client)
//! \brief Raise on new TCP connection received
//! \fn void connected()
//! \brief Raise if succesfull TCP connection
@@ -439,32 +490,32 @@ public:
#ifdef DOXYGEN
//! \brief read ip, default ""
string ip;
//! \brief read port, default 0
int port;
//! \brief ethernet parameters
int parameters;
//! \brief read timeout, default 1000 ms
double readTimeout;
//! \brief write timeout, default 1000 ms
double writeTimeout;
//! \brief time-to-live, default 64
int TTL;
//! \brief time-to-live for multicast, default 1
int multicastTTL;
#endif
//! \}
//! \}
protected:
explicit PIEthernet(int sock, PIString ip_port);
void propertyChanged(const char * name) override;
PIString constructFullPathDevice() const override;
void configureFromFullPathDevice(const PIString & full_path) override;
PIPropertyStorage constructVariantDevice() const override;
@@ -475,7 +526,7 @@ protected:
DeviceInfoFlags deviceInfoFlags() const override;
//! Executes when any read function was successful. Default implementation does nothing
virtual void received(const void * data, int size) {;}
virtual void received(const void * data, int size) { ; }
void construct();
bool init();
@@ -485,7 +536,7 @@ protected:
void applyTimeouts();
void applyTimeout(int fd, int opt, double ms);
void applyOptInt(int level, int opt, int val);
PRIVATE_DECLARATION(PIP_EXPORT)
int sock, sock_s;
std::atomic_bool connected_, connecting_, listen_threaded, server_bounded;
@@ -493,7 +544,7 @@ protected:
Type eth_type;
PIThread server_thread_;
PIMutex clients_mutex;
PIVector<PIEthernet * > clients_;
PIVector<PIEthernet *> clients_;
PIQueue<PIString> mcast_queue;
PIStringList mcast_groups;
PIFlags<PIEthernet::Parameters> params;
@@ -518,15 +569,30 @@ private:
static int ethSetsockoptBool(int sock, int level, int optname, bool value = true);
static void ethNonblocking(int sock);
static bool ethIsWriteable(int sock);
};
inline bool operator <(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name < v1.name);}
inline bool operator ==(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name == v1.name && v0.address == v1.address && v0.netmask == v1.netmask);}
inline bool operator !=(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name != v1.name || v0.address != v1.address || v0.netmask != v1.netmask);}
inline PICout operator <<(PICout s, const PIEthernet::Address & v) {s.space(); s.saveAndSetControls(0); s << "Address(" << v.toString() << ")"; s.restoreControls(); return s;}
inline bool operator<(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {
return (v0.name < v1.name);
}
inline bool operator==(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {
return (v0.name == v1.name && v0.address == v1.address && v0.netmask == v1.netmask);
}
inline bool operator!=(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {
return (v0.name != v1.name || v0.address != v1.address || v0.netmask != v1.netmask);
}
inline PICout operator<<(PICout s, const PIEthernet::Address & v) {
s.space();
s.saveAndSetControls(0);
s << "Address(" << v.toString() << ")";
s.restoreControls();
return s;
}
inline bool operator ==(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() == v1.ip() && v0.port() == v1.port());}
inline bool operator !=(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() != v1.ip() || v0.port() != v1.port());}
inline bool operator==(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {
return (v0.ip() == v1.ip() && v0.port() == v1.port());
}
inline bool operator!=(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {
return (v0.ip() != v1.ip() || v0.port() != v1.port());
}
#endif // PIETHERNET_H
+108 -104
View File
@@ -1,25 +1,26 @@
/*
PIP - Platform Independent Primitives
File
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
File
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "pifile.h"
#include "pidir.h"
#include "piincludes_p.h"
#include "piiostream.h"
#include "pitime_win.h"
#ifdef WINDOWS
@@ -36,38 +37,38 @@
# define S_IFCHR 0x10
# define S_IFSOCK 0x20
#else
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/time.h>
# include <fcntl.h>
# include <utime.h>
#endif
#define S_IFHDN 0x40
#define S_IFHDN 0x40
#if defined(QNX) || defined(ANDROID) || defined(FREERTOS)
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# define _stat_struct_ struct stat
# define _stat_call_ stat
# define _stat_link_ lstat
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# define _stat_struct_ struct stat
# define _stat_call_ stat
# define _stat_link_ lstat
#else
# if defined(MAC_OS)
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# else
# ifdef CC_GCC
# define _fopen_call_ fopen64
# define _fseek_call_ fseeko64
# define _ftell_call_ ftello64
# else
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# endif
# ifdef CC_GCC
# define _fopen_call_ fopen64
# define _fseek_call_ fseeko64
# define _ftell_call_ ftello64
# else
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# endif
# endif
# define _stat_struct_ struct stat64
# define _stat_call_ stat64
# define _stat_link_ lstat64
# define _stat_struct_ struct stat64
# define _stat_call_ stat64
# define _stat_link_ lstat64
#endif
@@ -152,10 +153,7 @@ PIString PIFile::FileInfo::dir() const {
}
PIFile::PIFile(): PIIODevice() {
}
PIFile::PIFile(): PIIODevice() {}
PIFile::PIFile(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode) {
@@ -196,7 +194,7 @@ bool PIFile::openDevice() {
}
}
PRIVATE->fd = _fopen_call_(p.data(), strType(mode_).data());
//piCout << "fopen " << path() << ": " << strType(mode_).data() << PRIVATE->fd;
// piCout << "fopen " << path() << ": " << strType(mode_).data() << PRIVATE->fd;
bool opened = (PRIVATE->fd != 0);
if (opened) {
fdi = fileno(PRIVATE->fd);
@@ -210,19 +208,19 @@ bool PIFile::openDevice() {
_fseek_call_(PRIVATE->fd, 0, SEEK_SET);
clearerr(PRIVATE->fd);
}
//piCout << "open file" << PRIVATE->fd << opened_;
// piCout << "open file" << PRIVATE->fd << opened_;
return opened;
}
bool PIFile::closeDevice() {
//piCout << "close file" << PRIVATE->fd << opened_;
// piCout << "close file" << PRIVATE->fd << opened_;
if (isClosed() || PRIVATE->fd == 0) return true;
bool cs = (fclose(PRIVATE->fd) == 0);
if (cs) PRIVATE->fd = 0;
fdi = -1;
fdi = -1;
_size = -1;
//piCout << "closed file" << PRIVATE->fd << opened_;
// piCout << "closed file" << PRIVATE->fd << opened_;
return cs;
}
@@ -232,9 +230,9 @@ llong PIFile::readAll(void * data) {
seekToBegin();
if (s < 0) {
while (!isEnd())
read(&(((char*)data)[++i]), 1);
read(&(((char *)data)[++i]), 1);
} else
read((char * )data, s);
read((char *)data, s);
seek(cp);
return s;
}
@@ -264,9 +262,11 @@ PIByteArray PIFile::readAll(bool forceRead) {
llong PIFile::size() const {
if (isClosed()) return -1;
llong s, cp = pos();
_fseek_call_(PRIVATE->fd, 0, SEEK_END); clearerr(PRIVATE->fd);
_fseek_call_(PRIVATE->fd, 0, SEEK_END);
clearerr(PRIVATE->fd);
s = pos();
_fseek_call_(PRIVATE->fd, cp, SEEK_SET); clearerr(PRIVATE->fd);
_fseek_call_(PRIVATE->fd, cp, SEEK_SET);
clearerr(PRIVATE->fd);
return s;
}
@@ -289,10 +289,9 @@ void PIFile::resize(llong new_size, uchar fill_) {
}
bool PIFile::isExists(const PIString & path) {
FILE * f = _fopen_call_(PIString(path).data(), "r");
bool ok = (f != 0);
bool ok = (f != 0);
if (ok) fclose(f);
return ok;
}
@@ -304,7 +303,7 @@ bool PIFile::remove(const PIString & path) {
return RemoveDirectoryA(path.data()) > 0;
else
#endif
return ::remove(path.data()) == 0;
return ::remove(path.data()) == 0;
}
@@ -378,7 +377,7 @@ void PIFile::seekToLine(llong line) {
if (isClosed()) return;
seekToBegin();
PIIOTextStream ts(this);
piForTimes (line) ts.readLine();
piForTimes(line) ts.readLine();
clearerr(PRIVATE->fd);
}
@@ -410,8 +409,7 @@ bool PIFile::isEnd() const {
if (isClosed()) return true;
bool ret = (feof(PRIVATE->fd) || ferror(PRIVATE->fd));
if (!ret && (_size >= 0)) {
if (pos() > _size)
ret = true;
if (pos() > _size) ret = true;
}
return ret;
}
@@ -455,7 +453,7 @@ void PIFile::clear() {
PRIVATE->fd = fopen(path().data(), "w");
if (PRIVATE->fd != 0) fclose(PRIVATE->fd);
PRIVATE->fd = 0;
opened_ = false;
opened_ = false;
open();
}
@@ -466,14 +464,12 @@ void PIFile::remove() {
}
PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
FileInfo ret;
if (path.isEmpty()) return ret;
ret.path = path.replacedAll("\\", PIDir::separator);
ret.path = path.replacedAll("\\", PIDir::separator);
PIString n = ret.name();
//piCout << "open" << path;
// piCout << "open" << path;
#ifdef WINDOWS
DWORD attr = GetFileAttributesA((LPCSTR)(path.data()));
if (attr == 0xFFFFFFFF) return ret;
@@ -490,51 +486,53 @@ PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
LARGE_INTEGER filesize;
filesize.LowPart = filesize.HighPart = 0;
if (fi.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ret.flags |= FileInfo::Hidden;
if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ret.flags |= FileInfo::Dir;
if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
ret.flags |= FileInfo::Dir;
else {
ret.flags |= FileInfo::File;
filesize.LowPart = fi.nFileSizeLow;
filesize.LowPart = fi.nFileSizeLow;
filesize.HighPart = fi.nFileSizeHigh;
}
PIString ext = ret.extension();
ret.perm_user = FileInfo::Permissions(true, (attr & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY, ext == "bat" || ext == "exe");
ret.perm_user =
FileInfo::Permissions(true, (attr & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY, ext == "bat" || ext == "exe");
ret.perm_group = ret.perm_other = ret.perm_user;
ret.size = filesize.QuadPart;
ret.time_access = FILETIME2PIDateTime(fi.ftLastAccessTime);
ret.time_modification = FILETIME2PIDateTime(fi.ftLastWriteTime);
ret.size = filesize.QuadPart;
ret.time_access = FILETIME2PIDateTime(fi.ftLastAccessTime);
ret.time_modification = FILETIME2PIDateTime(fi.ftLastWriteTime);
}
CloseHandle(hFile);
#else
_stat_struct_ fs;
memset(&fs, 0, sizeof(fs));
_stat_call_(path.data(), &fs);
int mode = fs.st_mode;
ret.size = fs.st_size;
ret.id_user = fs.st_uid;
ret.id_group = fs.st_gid;
#ifdef ANDROID
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.st_atime, fs.st_atime_nsec));
int mode = fs.st_mode;
ret.size = fs.st_size;
ret.id_user = fs.st_uid;
ret.id_group = fs.st_gid;
# ifdef ANDROID
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.st_atime, fs.st_atime_nsec));
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.st_mtime, fs.st_mtime_nsec));
#else
# if defined(QNX) || defined(FREERTOS)
ret.time_access = PIDateTime::fromSecondSinceEpoch(fs.st_atime);
ret.time_modification = PIDateTime::fromSecondSinceEpoch(fs.st_mtime);
# else
# ifdef MAC_OS
# define ATIME st_atimespec
# define MTIME st_ctimespec
# else
# define ATIME st_atim
# define MTIME st_mtim
# endif
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.ATIME.tv_sec, fs.ATIME.tv_nsec));
# if defined(QNX) || defined(FREERTOS)
ret.time_access = PIDateTime::fromSecondSinceEpoch(fs.st_atime);
ret.time_modification = PIDateTime::fromSecondSinceEpoch(fs.st_mtime);
# else
# ifdef MAC_OS
# define ATIME st_atimespec
# define MTIME st_ctimespec
# else
# define ATIME st_atim
# define MTIME st_mtim
# endif
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.ATIME.tv_sec, fs.ATIME.tv_nsec));
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.MTIME.tv_sec, fs.MTIME.tv_nsec));
# endif
# endif
#endif
#ifndef MICRO_PIP
ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR);
ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP);
ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH);
# ifndef MICRO_PIP
ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR);
ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP);
ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH);
memset(&fs, 0, sizeof(fs));
_stat_link_(path.data(), &fs);
mode &= ~S_IFLNK;
@@ -544,7 +542,7 @@ PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
if ((mode & S_IFREG) == S_IFREG) ret.flags |= FileInfo::File;
if ((mode & S_IFLNK) == S_IFLNK) ret.flags |= FileInfo::SymbolicLink;
if ((mode & S_IFHDN) == S_IFHDN) ret.flags |= FileInfo::Hidden;
#endif
# endif
#endif
if (n == ".") ret.flags = FileInfo::Dir | FileInfo::Dot;
if (n == "..") ret.flags = FileInfo::Dir | FileInfo::DotDot;
@@ -567,7 +565,13 @@ bool PIFile::applyFileInfo(const PIString & path, const PIFile::FileInfo & info)
}
HANDLE hFile = 0;
if ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) {
hFile = CreateFileA(path.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
hFile = CreateFileA(path.data(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
0);
} else {
hFile = CreateFileA(path.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
}
@@ -580,15 +584,15 @@ bool PIFile::applyFileInfo(const PIString & path, const PIFile::FileInfo & info)
CloseHandle(hFile);
#else
int mode(0);
if (info.perm_user.read) mode |= S_IRUSR;
if (info.perm_user.write) mode |= S_IWUSR;
if (info.perm_user.exec) mode |= S_IXUSR;
if (info.perm_group.read) mode |= S_IRGRP;
if (info.perm_user.read) mode |= S_IRUSR;
if (info.perm_user.write) mode |= S_IWUSR;
if (info.perm_user.exec) mode |= S_IXUSR;
if (info.perm_group.read) mode |= S_IRGRP;
if (info.perm_group.write) mode |= S_IWGRP;
if (info.perm_group.exec) mode |= S_IXGRP;
if (info.perm_other.read) mode |= S_IROTH;
if (info.perm_group.exec) mode |= S_IXGRP;
if (info.perm_other.read) mode |= S_IROTH;
if (info.perm_other.write) mode |= S_IWOTH;
if (info.perm_other.exec) mode |= S_IXOTH;
if (info.perm_other.exec) mode |= S_IXOTH;
if (chmod(fp.data(), mode) != 0) {
piCout << "[PIFile] applyFileInfo: \"chmod\" error:" << errorString();
}
@@ -597,11 +601,11 @@ bool PIFile::applyFileInfo(const PIString & path, const PIFile::FileInfo & info)
}
struct timeval tm[2];
PISystemTime st = info.time_access.toSystemTime();
tm[0].tv_sec = st.seconds;
tm[0].tv_usec = st.nanoseconds / 1000;
st = info.time_modification.toSystemTime();
tm[1].tv_sec = st.seconds;
tm[1].tv_usec = st.nanoseconds / 1000;
tm[0].tv_sec = st.seconds;
tm[0].tv_usec = st.nanoseconds / 1000;
st = info.time_modification.toSystemTime();
tm[1].tv_sec = st.seconds;
tm[1].tv_usec = st.nanoseconds / 1000;
if (utimes(fp.data(), tm) != 0) {
piCout << "[PIFile] applyFileInfo: \"utimes\" error:" << errorString();
}
+88 -82
View File
@@ -5,22 +5,22 @@
* \~russian Локальный файл
*/
/*
PIP - Platform Independent Primitives
File
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
File
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIFILE_H
@@ -34,11 +34,10 @@
//! \~\brief
//! \~english Local file.
//! \~russian Локальный файл.
class PIP_EXPORT PIFile: public PIIODevice
{
class PIP_EXPORT PIFile: public PIIODevice {
PIIODEVICE(PIFile, "file");
public:
//! \~english Constructs file with empty path
//! \~russian Создает файл с пустым путём
explicit PIFile();
@@ -55,20 +54,23 @@ public:
//! \~english Local file or directory information.
//! \~russian Информация о локальном файле или директории.
struct PIP_EXPORT FileInfo {
//! \~english Constructs %FileInfo with path "path_". No information gathered
//! \~russian Создает %FileInfo с путём "path_". Информация не собирается
FileInfo(const PIString & path_ = PIString()) {path = path_; size = 0; id_group = id_user = 0;}
FileInfo(const PIString & path_ = PIString()) {
path = path_;
size = 0;
id_group = id_user = 0;
}
//! \~english Type flags
//! \~russian Флаги типа
enum Flag {
File /*! \~english File \~russian Файл */ = 0x01,
Dir /*! \~english Directory \~russian Директория */ = 0x02,
Dot /*! \~english '.', current directory \~russian '.', текущая директория */ = 0x04,
DotDot /*! \~english '..', parent directory \~russian '..', родительская директория */ = 0x08,
SymbolicLink /*! \~english Symbolic link \~russian Символическая ссылка */ = 0x10,
Hidden /*! \~english Hidden \~russian Скрытый */ = 0x20
File /*! \~english File \~russian Файл */ = 0x01,
Dir /*! \~english Directory \~russian Директория */ = 0x02,
Dot /*! \~english '.', current directory \~russian '.', текущая директория */ = 0x04,
DotDot /*! \~english '..', parent directory \~russian '..', родительская директория */ = 0x08,
SymbolicLink /*! \~english Symbolic link \~russian Символическая ссылка */ = 0x10,
Hidden /*! \~english Hidden \~russian Скрытый */ = 0x20
};
typedef PIFlags<FileInfo::Flag> Flags;
@@ -78,16 +80,23 @@ public:
//! \~russian Разрешения локального файла или директории.
struct PIP_EXPORT Permissions {
Permissions(uchar r = 0): raw(r) {}
Permissions(bool r, bool w, bool e): raw(0) {read = r; write = w; exec = e;}
Permissions(bool r, bool w, bool e): raw(0) {
read = r;
write = w;
exec = e;
}
//! \~english Returns as string (from "---" to "rwx")
//! \~russian Возвращает как строку (от "---" до "rwx")
PIString toString() const {return PIString(read ? "r" : "-") + PIString(write ? "w" : "-") + PIString(exec ? "x" : "-");}
PIString toString() const { return PIString(read ? "r" : "-") + PIString(write ? "w" : "-") + PIString(exec ? "x" : "-"); }
//! \~english Convertion to \c int
//! \~russian Преобразование в \c int
operator int() const {return raw;}
Permissions & operator =(int v) {raw = v; return *this;}
operator int() const { return raw; }
Permissions & operator=(int v) {
raw = v;
return *this;
}
union {
uchar raw;
struct {
@@ -97,7 +106,7 @@ public:
};
};
};
//! \~english Path
//! \~russian Путь
PIString path;
@@ -137,7 +146,7 @@ public:
//! \~english Permissions for other
//! \~russian Разрешения для остальных
Permissions perm_other;
//! \~english Returns name, without directory
//! \~russian Возвращает имя, без директории
@@ -157,43 +166,42 @@ public:
//! \~english Returns if it`s directory
//! \~russian Возвращает директория ли это
bool isDir() const {return flags[Dir];}
bool isDir() const { return flags[Dir]; }
//! \~english Returns if it`s file
//! \~russian Возвращает файл ли это
bool isFile() const {return flags[File];}
bool isFile() const { return flags[File]; }
//! \~english Returns if it`s symbolic link
//! \~russian Возвращает символическая ссылка ли это
bool isSymbolicLink() const {return flags[SymbolicLink];}
bool isSymbolicLink() const { return flags[SymbolicLink]; }
//! \~english Returns if Hidden flag set
//! \~russian Возвращает установлен ли флаг Hidden
bool isHidden() const {return flags[Hidden];}
bool isHidden() const { return flags[Hidden]; }
};
//! \~english Open temporary file with open mode "mode"
//! \~russian Открывает временный файл с режимом открытия "mode"
bool openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Immediate write all buffered data to disk
//! \~russian Немедленно записывает все буферизированные данные на диск
void flush() override;
//! \~english Move read/write position to "position"
//! \~russian Перемещает позицию чтения/записи на "position"
void seek(llong position);
//! \~english Move read/write position to the begin of the file
//! \~russian Перемещает позицию чтения/записи на начало файла
void seekToBegin();
//! \~english Move read/write position to the end of the file
//! \~russian Перемещает позицию чтения/записи на конец файла
void seekToEnd();
//! \~english Move read/write position to text line number "line" beginning
//! \~russian Перемещает позицию чтения/записи на начало текстовой строки номер "line"
void seekToLine(llong line);
@@ -201,47 +209,47 @@ public:
//! \~english Skip "bytes" bytes (move position next to "bytes" bytes)
//! \~russian Пропускает "bytes" байт (перемещает позицию на "bytes" байт вперёд)
void skip(llong bytes);
//! \~english Read one char and return it
//! \~russian Читает один байт и возвращает его
char readChar();
//! \~english Read all file content to "data" and return readed bytes count. Position leaved unchanged
//! \~russian Читает всё содержимое файла в "data" и возвращает количество прочитанных байт. Позиция остаётся неизменной
llong readAll(void * data);
//! \~english Read all file content to byte array and return it. Position leaved unchanged
//! \~russian Читает всё содержимое файла и возвращает его как массив байтов. Позиция остаётся неизменной
PIByteArray readAll(bool forceRead = false);
//! \~english Set file path to "path" and reopen file if need
//! \~russian Устанавливает путь файла на "path" и переоткрывает его при необходимости
void setPath(const PIString & path);
//! \~english Returns file size in bytes
//! \~russian Возвращает размер файла в байтах
llong size() const;
ssize_t bytesAvailable() const override {return size() - pos();}
ssize_t bytesAvailable() const override { return size() - pos(); }
//! \~english Returns read/write position
//! \~russian Возвращает позицию чтения/записи
llong pos() const;
//! \~english Returns if position is at the end of file
//! \~russian Возвращает достигнут ли конец файла
bool isEnd() const;
//! \~english Returns if file is empty
//! \~russian Возвращает пустой ли файл
bool isEmpty() const {return (size() <= 0);}
bool isEmpty() const { return (size() <= 0); }
//! \~english Returns \a PIFile::FileInfo of current file
//! \~russian Возвращает \a PIFile::FileInfo текущего файла
FileInfo fileInfo() const {return fileInfo(path());}
FileInfo fileInfo() const { return fileInfo(path()); }
//! \~english Write size and content of "v" (serialize)
//! \~russian Пишет в файл размер и содержимое "v" (сериализация)
@@ -250,48 +258,48 @@ public:
//! \~english Read size of byte array and it content (deserialize)
//! \~russian Читает из файла размер байтового массива и его содержимое (десериализация)
PIByteArray get();
EVENT_HANDLER(void, clear);
EVENT_HANDLER(void, remove);
EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);}
EVENT_HANDLER1(void, resize, llong, new_size) { resize(new_size, 0); }
EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill);
//! \~english Returns if file with path "path" exists
//! \~russian Возвращает существует ли файл с путём "path"
static bool isExists(const PIString & path);
//! \~english Remove file with path "path" and returns if remove successful
//! \~russian Удаляет файл с путём "path" и возвращает успешность операции
static bool remove(const PIString & path);
//! \~english Rename file with path "from" to path "to" and returns if rename successful
//! \~russian Переименовывает файл с путём "path" на "to" и возвращает успешность операции
static bool rename(const PIString & from, const PIString & to);
//! \~english Returns \a PIFile::FileInfo of file or dir with path "path"
//! \~russian Возвращает \a PIFile::FileInfo файла или директории с путём "path"
static FileInfo fileInfo(const PIString & path);
//! \~english Apply "info" parameters to file or dir with path "path"
//! \~russian Применяет параметры "info" к файлу или директории с путём "path"
static bool applyFileInfo(const PIString & path, const FileInfo & info);
//! \~english Apply "info" parameters to file or dir with path "info".path
//! \~russian Применяет параметры "info" к файлу или директории с путём "info".path
static bool applyFileInfo(const FileInfo & info) {return applyFileInfo(info.path, info);}
//! \handlers
//! \{
static bool applyFileInfo(const FileInfo & info) { return applyFileInfo(info.path, info); }
//! \handlers
//! \{
//! \fn void clear()
//! \~english Clear content of file
//! \~russian Очищает содержимое файла
//! \fn void resize(llong new_size)
//! \~english Resize file to "new_size" with null-byte fill
//! \~russian Изменяет размер файла на "new_size" с заполнением нулевыми байтами
//! \fn void resize(llong new_size, uchar fill)
//! \~english Resize file to "new_size" with "fill" fill
//! \~russian Изменяет размер файла на "new_size" с заполнением байтами "fill"
@@ -305,7 +313,7 @@ public:
//! \{
#ifdef DOXYGEN
#endif
//! \}
//! \}
protected:
PIString constructFullPathDevice() const override;
@@ -316,28 +324,26 @@ protected:
ssize_t writeDevice(const void * data, ssize_t max_size) override;
bool openDevice() override;
bool closeDevice() override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Sequential | PIIODevice::Reliable;}
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Sequential | PIIODevice::Reliable; }
private:
PIString strType(const PIIODevice::DeviceMode type);
PRIVATE_DECLARATION(PIP_EXPORT)
int fdi = -1;
int fdi = -1;
llong _size = -1;
PIString prec_str;
};
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIFile::FileInfo & v) {
inline PICout operator<<(PICout s, const PIFile::FileInfo & v) {
s.saveAndSetControls(0);
s << "FileInfo(\"" << v.path << "\", " << PIString::readableSize(v.size) << ", "
<< v.perm_user.toString() << " " << v.perm_group.toString() << " " << v.perm_other.toString() << ", "
<< v.time_access.toString() << ", " << v.time_modification.toString()
<< ", 0x" << PICoutManipulators::Hex << v.flags << ")";
s << "FileInfo(\"" << v.path << "\", " << PIString::readableSize(v.size) << ", " << v.perm_user.toString() << " "
<< v.perm_group.toString() << " " << v.perm_other.toString() << ", " << v.time_access.toString() << ", "
<< v.time_modification.toString() << ", 0x" << PICoutManipulators::Hex << v.flags << ")";
s.restoreControls();
return s;
}
@@ -347,8 +353,8 @@ inline PICout operator <<(PICout s, const PIFile::FileInfo & v) {
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIFile::FileInfo) {
s << v.path << v.size << v.time_access << v.time_modification <<
v.flags << v.id_user << v.id_group << v.perm_user.raw << v.perm_group.raw << v.perm_other.raw;
s << v.path << v.size << v.time_access << v.time_modification << v.flags << v.id_user << v.id_group << v.perm_user.raw
<< v.perm_group.raw << v.perm_other.raw;
return s;
}
@@ -356,8 +362,8 @@ BINARY_STREAM_WRITE(PIFile::FileInfo) {
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIFile::FileInfo) {
s >> v.path >> v.size >> v.time_access >> v.time_modification >>
v.flags >> v.id_user >> v.id_group >> v.perm_user.raw >> v.perm_group.raw >> v.perm_other.raw;
s >> v.path >> v.size >> v.time_access >> v.time_modification >> v.flags >> v.id_user >> v.id_group >> v.perm_user.raw >>
v.perm_group.raw >> v.perm_other.raw;
return s;
}
+36 -40
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
GPIO
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
GPIO
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pigpio.h"
@@ -22,9 +22,9 @@
# define GPIO_SYS_CLASS
#endif
#ifdef GPIO_SYS_CLASS
# include <cstdlib>
# include <fcntl.h>
# include <unistd.h>
# include <cstdlib>
#endif
@@ -64,8 +64,7 @@
//!
PIGPIO::PIGPIO(): PIThread() {
}
PIGPIO::PIGPIO(): PIThread() {}
PIGPIO::~PIGPIO() {
@@ -74,7 +73,7 @@ PIGPIO::~PIGPIO() {
PIMutexLocker ml(mutex);
#ifdef GPIO_SYS_CLASS
PIVector<int> ids = gpio_.keys();
for(int i = 0; i < ids.size_s(); i++) {
for (int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.fd != -1) {
::close(g.fd);
@@ -92,7 +91,6 @@ PIGPIO * PIGPIO::instance() {
}
PIString PIGPIO::GPIOName(int gpio_num) {
return PIStringAscii("gpio") + PIString::fromNumber(gpio_num);
}
@@ -101,13 +99,13 @@ PIString PIGPIO::GPIOName(int gpio_num) {
void PIGPIO::exportGPIO(int gpio_num) {
#ifdef GPIO_SYS_CLASS
PIString valfile = "/sys/class/gpio/" + GPIOName(gpio_num) + "/value";
int fd = ::open(valfile.dataAscii(), O_RDONLY);
int fd = ::open(valfile.dataAscii(), O_RDONLY);
if (fd != -1) {
::close(fd);
return;
}
int ret = 0;
ret = system(PIString("echo " + PIString::fromNumber(gpio_num) + " >> /sys/class/gpio/export").dataAscii());
ret = system(PIString("echo " + PIString::fromNumber(gpio_num) + " >> /sys/class/gpio/export").dataAscii());
if (ret == 0) {
PITimeMeasurer tm;
while (tm.elapsed_s() < 1.) {
@@ -130,8 +128,8 @@ void PIGPIO::openGPIO(GPIOData & g) {
g.fd = -1;
}
PIString fp = "/sys/class/gpio/" + g.name + "/value";
g.fd = ::open(fp.dataAscii(), O_RDWR);
//piCoutObj << "initGPIO" << g.num << ":" << fp << g.fd << errorString();
g.fd = ::open(fp.dataAscii(), O_RDWR);
// piCoutObj << "initGPIO" << g.num << ":" << fp << g.fd << errorString();
#endif
}
@@ -139,7 +137,7 @@ void PIGPIO::openGPIO(GPIOData & g) {
bool PIGPIO::getPinState(int gpio_num) {
#ifdef GPIO_SYS_CLASS
GPIOData & g(gpio_[gpio_num]);
char r = 0;
char r = 0;
int ret = 0;
if (g.fd != -1) {
::lseek(g.fd, 0, SEEK_SET);
@@ -149,7 +147,7 @@ bool PIGPIO::getPinState(int gpio_num) {
if (r == '0') return false;
}
}
//piCoutObj << "pinState" << gpio_num << ":" << ret << (int)r << errorString();
// piCoutObj << "pinState" << gpio_num << ":" << ret << (int)r << errorString();
#endif
return false;
}
@@ -159,7 +157,7 @@ void PIGPIO::begin() {
PIMutexLocker ml(mutex);
if (watch_state.isEmpty()) return;
PIVector<int> ids = watch_state.keys();
for(int i = 0; i < ids.size_s(); i++) {
for (int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.num != -1 && !g.name.isEmpty()) {
openGPIO(g);
@@ -181,7 +179,7 @@ void PIGPIO::run() {
GPIOData & g(gpio_[it.key()]);
if (g.num == -1 || g.name.isEmpty()) continue;
bool v = getPinState(g.num);
//piCoutObj << "*** pin state ***" << ids[i] << "=" << v;
// piCoutObj << "*** pin state ***" << ids[i] << "=" << v;
if (watch_state[g.num] != v) {
watch_state[g.num] = v;
changed.push_back({g.num, v});
@@ -197,7 +195,7 @@ void PIGPIO::end() {
PIMutexLocker ml(mutex);
if (watch_state.isEmpty()) return;
PIVector<int> ids = watch_state.keys();
for(int i = 0; i < ids.size_s(); i++) {
for (int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.fd != -1) {
#ifdef GPIO_SYS_CLASS
@@ -214,20 +212,16 @@ void PIGPIO::initPin(int gpio_num, Direction dir) {
PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]);
if (g.num == -1) {
g.num = gpio_num;
g.num = gpio_num;
g.name = GPIOName(gpio_num);
exportGPIO(gpio_num);
}
g.dir = dir;
g.dir = dir;
int ret = 0;
NO_UNUSED(ret);
switch(dir) {
case In:
ret = system(("echo in >> /sys/class/gpio/" + g.name + "/direction").dataAscii());
break;
case Out:
ret = system(("echo out >> /sys/class/gpio/" + g.name + "/direction").dataAscii());
break;
switch (dir) {
case In: ret = system(("echo in >> /sys/class/gpio/" + g.name + "/direction").dataAscii()); break;
case Out: ret = system(("echo out >> /sys/class/gpio/" + g.name + "/direction").dataAscii()); break;
default: break;
}
openGPIO(g);
@@ -242,10 +236,12 @@ void PIGPIO::pinSet(int gpio_num, bool value) {
int ret = 0;
NO_UNUSED(ret);
if (g.fd != -1) {
if (value) ret = ::write(g.fd, "1", 1);
else ret = ::write(g.fd, "0", 1);
if (value)
ret = ::write(g.fd, "1", 1);
else
ret = ::write(g.fd, "0", 1);
}
//piCoutObj << "pinSet" << gpio_num << ":" << ret << errorString();
// piCoutObj << "pinSet" << gpio_num << ":" << ret << errorString();
#endif
}
@@ -306,5 +302,5 @@ void PIGPIO::clearWatch() {
#ifdef __GNUC__
//# pragma GCC diagnostic pop
// # pragma GCC diagnostic pop
#endif
+32 -31
View File
@@ -3,24 +3,24 @@
* \~\brief
* \~english GPIO
* \~russian GPIO
*/
*/
/*
PIP - Platform Independent Primitives
GPIO
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
GPIO
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIGPIO_H
@@ -33,15 +33,14 @@
//! \~\brief
//! \~english GPIO support.
//! \~russian Поддержка GPIO.
class PIP_EXPORT PIGPIO: public PIThread
{
class PIP_EXPORT PIGPIO: public PIThread {
PIOBJECT_SUBCLASS(PIGPIO, PIThread);
public:
public:
//! \~english Work mode for pin
//! \~russian Режим работы пина
enum Direction {
In /** \~english Input direction (read) \~russian Входной (чтение) */,
In /** \~english Input direction (read) \~russian Входной (чтение) */,
Out /** \~english Output direction (write) \~russian Выходной (запись) */
};
@@ -55,15 +54,15 @@ public:
//! \~english Set pin "gpio_num" value to "value"
//! \~russian Устанавливает значение пина "gpio_num" в "value"
void pinSet (int gpio_num, bool value);
void pinSet(int gpio_num, bool value);
//! \~english Set pin "gpio_num" value to \b true
//! \~russian Устанавливает значение пина "gpio_num" в \b true
void pinHigh (int gpio_num) {pinSet(gpio_num, true );}
void pinHigh(int gpio_num) { pinSet(gpio_num, true); }
//! \~english Set pin "gpio_num" value to \b false
//! \~russian Устанавливает значение пина "gpio_num" в \b false
void pinLow (int gpio_num) {pinSet(gpio_num, false);}
void pinLow(int gpio_num) { pinSet(gpio_num, false); }
//!
//! \~english Returns pin "gpio_num" state
@@ -76,7 +75,7 @@ public:
//! \~english End watch for pin "gpio_num"
//! \~russian Заканчивает наблюдение за пином "gpio_num"
void pinEndWatch (int gpio_num);
void pinEndWatch(int gpio_num);
//! \~english End watch for all pins
//! \~russian Заканчивает наблюдение за всеми пинами
@@ -87,13 +86,13 @@ public:
//! \events
//! \{
//! \fn void pinChanged(int gpio_num, bool new_value)
//! \~english Raise on pin "gpio_num" state changes to "new_value"
//! \~russian Вызывается по смене состояния пина "gpio_num" на "new_value"
//! \~\details
//! \~\warning
//! \~english This event raised only when thread started.
//! \~russian Это событие вызывается только при запущенном потоке.
//! \fn void pinChanged(int gpio_num, bool new_value)
//! \~english Raise on pin "gpio_num" state changes to "new_value"
//! \~russian Вызывается по смене состояния пина "gpio_num" на "new_value"
//! \~\details
//! \~\warning
//! \~english This event raised only when thread started.
//! \~russian Это событие вызывается только при запущенном потоке.
//! \}
@@ -103,7 +102,10 @@ private:
NO_COPY_CLASS(PIGPIO);
struct PIP_EXPORT GPIOData {
GPIOData() {dir = PIGPIO::In; num = fd = -1;}
GPIOData() {
dir = PIGPIO::In;
num = fd = -1;
}
PIString name;
int dir;
int num;
@@ -121,7 +123,6 @@ private:
PIMap<int, GPIOData> gpio_;
PIMap<int, bool> watch_state;
PIMutex mutex;
};
+24 -24
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
PIIODevice wrapper around PIByteArray
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PIIODevice wrapper around PIByteArray
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piiobytearray.h"
@@ -31,37 +31,37 @@
//!
PIIOByteArray::PIIOByteArray(PIByteArray *buffer, PIIODevice::DeviceMode mode) {
PIIOByteArray::PIIOByteArray(PIByteArray * buffer, PIIODevice::DeviceMode mode) {
open(buffer, mode);
}
PIIOByteArray::PIIOByteArray(const PIByteArray &buffer) {
PIIOByteArray::PIIOByteArray(const PIByteArray & buffer) {
open(buffer);
}
bool PIIOByteArray::open(PIByteArray *buffer, PIIODevice::DeviceMode mode) {
bool PIIOByteArray::open(PIByteArray * buffer, PIIODevice::DeviceMode mode) {
data_ = buffer;
mode_ = mode;
return PIIODevice::open(mode);
}
bool PIIOByteArray::open(const PIByteArray &buffer) {
data_ = const_cast<PIByteArray*>(&buffer);
bool PIIOByteArray::open(const PIByteArray & buffer) {
data_ = const_cast<PIByteArray *>(&buffer);
mode_ = PIIODevice::ReadOnly;
return PIIODevice::open(PIIODevice::ReadOnly);
}
ssize_t PIIOByteArray::readDevice(void * read_to, ssize_t size) {
// piCout << "PIIOByteArray::read" << data_ << size << canRead();
// piCout << "PIIOByteArray::read" << data_ << size << canRead();
if (!canRead() || !data_) return -1;
int ret = piMini(size, data_->size_s() - pos);
if (ret <= 0) return -1;
memcpy(read_to, data_->data(pos), ret);
// piCout << "readed" << ret;
// piCout << "readed" << ret;
pos += size;
if (pos > data_->size_s()) pos = data_->size_s();
return ret;
@@ -69,19 +69,19 @@ ssize_t PIIOByteArray::readDevice(void * read_to, ssize_t size) {
ssize_t PIIOByteArray::writeDevice(const void * data, ssize_t size) {
// piCout << "PIIOByteArray::write" << data << size << canWrite();
// piCout << "PIIOByteArray::write" << data << size << canWrite();
if (!canWrite() || !data) return -1;
//piCout << "write" << data;
// piCout << "write" << data;
if (pos > data_->size_s()) pos = data_->size_s();
PIByteArray rs = PIByteArray(data, size);
// piCoutObj << rs;
// piCoutObj << rs;
data_->insert(pos, rs);
pos += rs.size_s();
return rs.size_s();
}
int PIIOByteArray::writeByteArray(const PIByteArray &ba) {
int PIIOByteArray::writeByteArray(const PIByteArray & ba) {
if (!canWrite() || !data_) return -1;
if (pos > data_->size_s()) pos = data_->size_s();
data_->insert(pos, ba);
+49 -39
View File
@@ -5,22 +5,22 @@
* \~russian Обертка PIIODevice вокруг PIByteArray
*/
/*
PIP - Platform Independent Primitives
PIIODevice wrapper around PIByteArray
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
PIIODevice wrapper around PIByteArray
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIIOBYTEARRAY_H
@@ -33,71 +33,81 @@
//! \~\brief
//! \~english PIIODevice wrapper around PIByteArray
//! \~russian Обёртка PIIODevice вокруг PIByteArray
class PIP_EXPORT PIIOByteArray: public PIIODevice
{
class PIP_EXPORT PIIOByteArray: public PIIODevice {
PIIODEVICE(PIIOByteArray, "");
public:
//! \~english Contructs %PIIOByteArray with "buffer" content and "mode" open mode
//! \~russian Создает %PIIOByteArray с содержимым "buffer" и режимом открытия "mode"
explicit PIIOByteArray(PIByteArray * buffer = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Contructs %PIIOByteArray with "buffer" content only for read
//! \~russian Создает %PIIOByteArray с содержимым "buffer" только для чтения
explicit PIIOByteArray(const PIByteArray & buffer);
//! \~english Returns content
//! \~russian Возвращает содержимое
PIByteArray * byteArray() const {return data_;}
PIByteArray * byteArray() const { return data_; }
//! \~english Clear content buffer
//! \~russian Очищает содержимое буфера
void clear() {if (data_) data_->clear(); pos = 0;}
void clear() {
if (data_) data_->clear();
pos = 0;
}
//! \~english Open "buffer" content with "mode" open mode
//! \~russian Открывает содержимое "buffer" с режимом открытия "mode"
bool open(PIByteArray * buffer, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Open "buffer" content only for read
//! \~russian Открывает содержимое "buffer" только для чтения
bool open(const PIByteArray & buffer);
//! \~english Returns if position is at the end of content
//! \~russian Возвращает в конце содержимого ли позиция
bool isEnd() const {if (!data_) return true; return pos >= data_->size_s();}
bool isEnd() const {
if (!data_) return true;
return pos >= data_->size_s();
}
//! \~english Move read/write position to "position"
//! \~russian Перемещает позицию чтения/записи на "position"
void seek(llong position) {pos = position;}
void seek(llong position) { pos = position; }
//! \~english Move read/write position to the beginning of the buffer
//! \~russian Перемещает позицию чтения/записи на начало буфера
void seekToBegin() {if (data_) pos = 0;}
void seekToBegin() {
if (data_) pos = 0;
}
//! \~english Move read/write position to the end of the buffer
//! \~russian Перемещает позицию чтения/записи на конец буфера
void seekToEnd() {if (data_) pos = data_->size_s();}
void seekToEnd() {
if (data_) pos = data_->size_s();
}
//! \~english Insert data "ba" into content at current position
//! \~russian Вставляет данные "ba" в содержимое буфера в текущую позицию
int writeByteArray(const PIByteArray & ba);
ssize_t bytesAvailable() const override {
if (data_) return data_->size();
else return 0;
if (data_)
return data_->size();
else
return 0;
}
protected:
bool openDevice() override;
ssize_t readDevice(void * read_to, ssize_t size) override;
ssize_t writeDevice(const void * data_, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Sequential | PIIODevice::Reliable;}
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Sequential | PIIODevice::Reliable; }
ssize_t pos;
PIByteArray * data_;
};
#endif // PIIOBYTEARRAY_H
+70 -48
View File
@@ -1,23 +1,24 @@
/*
PIP - Platform Independent Primitives
Abstract input/output device
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Abstract input/output device
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piiodevice.h"
#include "piconfig.h"
#include "piconnection.h"
#include "pipropertystorage.h"
@@ -235,8 +236,7 @@ bool PIIODevice::isThreadedWrite() const {
void PIIODevice::startThreadedWrite() {
if (!write_thread.isRunning())
write_thread.startOnce();
if (!write_thread.isRunning()) write_thread.startOnce();
}
@@ -313,11 +313,13 @@ void PIIODevice::_init() {
#else
threaded_read_buffer_size = 4096;
#endif
read_thread .setName("__S__.PIIODevice.read_thread" );
read_thread.setName("__S__.PIIODevice.read_thread");
write_thread.setName("__S__.PIIODevice.write_thread");
CONNECT(void, &write_thread, started, this, write_func);
CONNECTL(&read_thread, started, [this](){if (!isOpened()) open();});
read_thread.setSlot([this](void*){read_func();});
CONNECTL(&read_thread, started, [this]() {
if (!isOpened()) open();
});
read_thread.setSlot([this](void *) { read_func(); });
}
@@ -339,8 +341,7 @@ void PIIODevice::write_func() {
PIIODevice * PIIODevice::newDeviceByPrefix(const char * prefix) {
if (!prefix) return nullptr;
auto fi = fabrics().value(prefix);
if (fi.fabricator)
return fi.fabricator();
if (fi.fabricator) return fi.fabricator();
return nullptr;
}
@@ -364,10 +365,10 @@ void PIIODevice::read_func() {
ssize_t readed_ = read(buffer_tr.data(), buffer_tr.size_s());
if (readed_ <= 0) {
piMSleep(10);
//cout << readed_ << ", " << errno << ", " << errorString() << endl;
// cout << readed_ << ", " << errno << ", " << errorString() << endl;
return;
}
//piCoutObj << "readed" << readed_;// << ", " << errno << ", " << errorString();
// piCoutObj << "readed" << readed_;// << ", " << errno << ", " << errorString();
threadedRead(buffer_tr.data(), readed_);
threadedReadEvent(buffer_tr.data(), readed_);
}
@@ -381,8 +382,10 @@ PIByteArray PIIODevice::readForTime(double timeout_ms) {
tm.reset();
while (tm.elapsed_m() < timeout_ms) {
ret = read(td, threaded_read_buffer_size);
if (ret <= 0) piMinSleep();
else str.append(td, ret);
if (ret <= 0)
piMinSleep();
else
str.append(td, ret);
}
delete[] td;
return str;
@@ -442,8 +445,10 @@ bool PIIODevice::configure(const PIString & config_file, const PIString & sectio
if (!conf.isOpened()) return false;
bool ex = true;
PIConfig::Entry em;
if (section.isEmpty()) em = conf.rootEntry();
else em = conf.getValue(section, PIString(), &ex);
if (section.isEmpty())
em = conf.rootEntry();
else
em = conf.getValue(section, PIString(), &ex);
if (!ex) return false;
PIConfig::Entry * ep = 0;
if (parent_section) ep = em.parent();
@@ -470,7 +475,7 @@ PIString PIIODevice::constructFullPath() const {
void PIIODevice::configureFromFullPath(const PIString & full_path) {
PIString fp;
DeviceMode dm = ReadWrite;
DeviceMode dm = ReadWrite;
DeviceOptions op = 0;
splitFullPath(full_path, &fp, &dm, &op);
setMode(dm);
@@ -481,8 +486,8 @@ void PIIODevice::configureFromFullPath(const PIString & full_path) {
PIVariantTypes::IODevice PIIODevice::constructVariant() const {
PIVariantTypes::IODevice ret;
ret.prefix = fullPathPrefix();
ret.mode = mode();
ret.prefix = fullPathPrefix();
ret.mode = mode();
ret.options = options();
ret.set(constructVariantDevice());
return ret;
@@ -497,22 +502,25 @@ void PIIODevice::configureFromVariant(const PIVariantTypes::IODevice & d) {
void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode, DeviceOptions * opts) {
int dm = 0;
int dm = 0;
DeviceOptions op = 0;
if (fpwm.find('(') > 0 && fpwm.find(')') > 0) {
PIString dms(fpwm.right(fpwm.length() - fpwm.findLast('(')).takeRange('(', ')').trim().toLowerCase().removeAll(' '));
PIStringList opts(dms.split(","));
piForeachC (PIString & o, opts) {
//piCout << dms;
piForeachC(PIString & o, opts) {
// piCout << dms;
if (o == PIStringAscii("r") || o == PIStringAscii("ro") || o == PIStringAscii("read") || o == PIStringAscii("readonly"))
dm |= ReadOnly;
if (o == PIStringAscii("w") || o == PIStringAscii("wo") || o == PIStringAscii("write") || o == PIStringAscii("writeonly"))
dm |= WriteOnly;
if (o == PIStringAscii("br") || o == PIStringAscii("blockr") || o == PIStringAscii("blockread") || o == PIStringAscii("blockingread"))
if (o == PIStringAscii("br") || o == PIStringAscii("blockr") || o == PIStringAscii("blockread") ||
o == PIStringAscii("blockingread"))
op |= BlockingRead;
if (o == PIStringAscii("bw") || o == PIStringAscii("blockw") || o == PIStringAscii("blockwrite") || o == PIStringAscii("blockingwrite"))
if (o == PIStringAscii("bw") || o == PIStringAscii("blockw") || o == PIStringAscii("blockwrite") ||
o == PIStringAscii("blockingwrite"))
op |= BlockingWrite;
if (o == PIStringAscii("brw") || o == PIStringAscii("bwr") || o == PIStringAscii("blockrw") || o == PIStringAscii("blockwr") || o == PIStringAscii("blockreadrite") || o == PIStringAscii("blockingreadwrite"))
if (o == PIStringAscii("brw") || o == PIStringAscii("bwr") || o == PIStringAscii("blockrw") || o == PIStringAscii("blockwr") ||
o == PIStringAscii("blockreadrite") || o == PIStringAscii("blockingreadwrite"))
op |= BlockingRead | BlockingWrite;
}
fpwm.cutRight(fpwm.length() - fpwm.findLast('(')).trim();
@@ -542,12 +550,12 @@ PIStringList PIIODevice::availableClasses() {
void PIIODevice::registerDevice(PIConstChars prefix, PIConstChars classname, PIIODevice * (*fabric)()) {
if (prefix.isEmpty()) return;
//printf("registerDevice %s %d %d\n", prefix, p.isEmpty(), fabrics().size());
// printf("registerDevice %s %d %d\n", prefix, p.isEmpty(), fabrics().size());
if (!fabrics().contains(prefix)) {
FabricInfo fi;
fi.prefix = prefix;
fi.classname = classname;
fi.fabricator = fabric;
fi.prefix = prefix;
fi.classname = classname;
fi.fabricator = fabric;
fabrics()[prefix] = fi;
}
}
@@ -557,10 +565,26 @@ PIString PIIODevice::fullPathOptions() const {
if (mode_ == ReadWrite && options_ == 0) return PIString();
PIString ret(" (");
bool f = true;
if (mode_ == ReadOnly) {if (!f) ret += ","; f = false; ret += "ro";}
if (mode_ == WriteOnly) {if (!f) ret += ","; f = false; ret += "wo";}
if (options_[BlockingRead]) {if (!f) ret += ","; f = false; ret += "br";}
if (options_[BlockingWrite]) {if (!f) ret += ","; f = false; ret += "bw";}
if (mode_ == ReadOnly) {
if (!f) ret += ",";
f = false;
ret += "ro";
}
if (mode_ == WriteOnly) {
if (!f) ret += ",";
f = false;
ret += "wo";
}
if (options_[BlockingRead]) {
if (!f) ret += ",";
f = false;
ret += "br";
}
if (options_[BlockingWrite]) {
if (!f) ret += ",";
f = false;
ret += "bw";
}
return ret + ")";
}
@@ -599,7 +623,7 @@ PIString PIIODevice::normalizeFullPath(const PIString & full_path) {
}
nfp_mutex.unlock();
PIIODevice * d = createFromFullPath(full_path);
//piCout << "normalizeFullPath" << d;
// piCout << "normalizeFullPath" << d;
if (d == 0) return PIString();
ret = d->constructFullPath();
delete d;
@@ -619,8 +643,8 @@ PIMap<PIConstChars, PIIODevice::FabricInfo> & PIIODevice::fabrics() {
}
bool PIIODevice::threadedRead(const uchar *readed, ssize_t size) {
// piCout << "iodevice threaded read";
bool PIIODevice::threadedRead(const uchar * readed, ssize_t size) {
// piCout << "iodevice threaded read";
if (func_read) return func_read(readed, size, ret_data_);
return true;
}
@@ -636,5 +660,3 @@ PIPropertyStorage PIIODevice::constructVariantDevice() const {
void PIIODevice::configureFromVariantDevice(const PIPropertyStorage & d) {
setPath(d.propertyValueByName("path").toString());
}
+139 -122
View File
@@ -5,30 +5,30 @@
* \~russian Базовый класс утройств ввода/вывода
*/
/*
PIP - Platform Independent Primitives
Abstract input/output device
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Abstract input/output device
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIIODEVICE_H
#define PIIODEVICE_H
#include "piinit.h"
#include "pitimer.h"
#include "piqueue.h"
#include "pitimer.h"
/// TODO: написать документацию, тут ничего не понятно
// function executed from threaded read, pass readedData, sizeOfData, ThreadedReadData
@@ -56,18 +56,26 @@ typedef std::function<bool(const uchar *, int, void *)> ReadRetFunc;
#else
# define REGISTER_DEVICE(name) \
STATIC_INITIALIZER_BEGIN \
PIIODevice::registerDevice(name::fullPathPrefixS(), #name, []()->PIIODevice*{return new name();});\
STATIC_INITIALIZER_END
# define REGISTER_DEVICE(name) \
STATIC_INITIALIZER_BEGIN \
PIIODevice::registerDevice(name::fullPathPrefixS(), #name, []() -> PIIODevice * { return new name(); }); \
STATIC_INITIALIZER_END
# define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const override {return new name();} \
public: \
PIConstChars fullPathPrefix() const override {return prefix;} \
static PIConstChars fullPathPrefixS() {return prefix;} \
private:
# define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const override { \
return new name(); \
} \
\
public: \
PIConstChars fullPathPrefix() const override { \
return prefix; \
} \
static PIConstChars fullPathPrefixS() { \
return prefix; \
} \
\
private:
#endif
@@ -76,13 +84,13 @@ typedef std::function<bool(const uchar *, int, void *)> ReadRetFunc;
//! \~\brief
//! \~english Base class for input/output devices.
//! \~russian Базовый класс утройств ввода/вывода.
class PIP_EXPORT PIIODevice: public PIObject
{
class PIP_EXPORT PIIODevice: public PIObject {
PIOBJECT_SUBCLASS(PIIODevice, PIObject);
friend void __DevicePool_threadReadDP(void * ddp);
public:
NO_COPY_CLASS(PIIODevice);
//! \~english Constructs a empty %PIIODevice
//! \~russian Создает пустой %PIIODevice
explicit PIIODevice();
@@ -90,29 +98,33 @@ public:
//! \~english Open modes for PIIODevice
//! \~russian Режимы открытия для PIIODevice
enum DeviceMode {
ReadOnly /*! \~english Device can only read \~russian Устройство может только читать */ = 0x01,
WriteOnly /*! \~english Device can only write \~russian Устройство может только писать */ = 0x02,
ReadOnly /*! \~english Device can only read \~russian Устройство может только читать */ = 0x01,
WriteOnly /*! \~english Device can only write \~russian Устройство может только писать */ = 0x02,
ReadWrite /*! \~english Device can both read and write \~russian Устройство может читать и писать */ = 0x03
};
//! \~english Options for PIIODevice, works with some devices
//! \~russian Опции для PIIODevice, работает для некоторых устройств
enum DeviceOption {
BlockingRead /*! \~english \a read() block until data is received, default off \~russian \a read() блокируется, пока данные не поступят, по умолчанию выключено */ = 0x01,
BlockingWrite /*! \~english \a write() block until data is sent, default off \~russian \a write() блокируется, пока данные не запишутся, по умолчанию выключено */ = 0x02
BlockingRead /*! \~english \a read() block until data is received, default off \~russian \a read() блокируется, пока данные не
поступят, по умолчанию выключено */
= 0x01,
BlockingWrite /*! \~english \a write() block until data is sent, default off \~russian \a write() блокируется, пока данные не
запишутся, по умолчанию выключено */
= 0x02
};
//! \~english Characteristics of PIIODevice channel
//! \~russian Характеристики канала PIIODevice
enum DeviceInfoFlag {
Sequential /*! \~english Continuous bytestream without packets \~russian Непрерывный поток байт, без пакетирования */ = 0x01,
Reliable /*! \~english Channel without data errors or corruptions \~russian Канал без ошибок или повреждений данных */ = 0x02
Sequential /*! \~english Continuous bytestream without packets \~russian Непрерывный поток байт, без пакетирования */ = 0x01,
Reliable /*! \~english Channel without data errors or corruptions \~russian Канал без ошибок или повреждений данных */ = 0x02
};
struct FabricInfo {
PIConstChars prefix;
PIConstChars classname;
PIIODevice*(*fabricator)() = nullptr;
PIIODevice * (*fabricator)() = nullptr;
};
typedef PIFlags<DeviceOption> DeviceOptions;
@@ -126,19 +138,19 @@ public:
//! \~english Returns current open mode of device
//! \~russian Возвращает текущий режим открытия устройства
DeviceMode mode() const {return mode_;}
DeviceMode mode() const { return mode_; }
//! \~english Set open mode of device. Don`t reopen device
//! \~russian Устанавливает режим открытия устройства. Не переоткрывает устройство
void setMode(DeviceMode m) {mode_ = m;}
void setMode(DeviceMode m) { mode_ = m; }
//! \~english Returns current device options
//! \~russian Возвращает текущие опции устройства
DeviceOptions options() const {return options_;}
DeviceOptions options() const { return options_; }
//! \~english Returns current device option "o" state
//! \~russian Возвращает текущее состояние опции "o"
bool isOptionSet(DeviceOption o) const {return options_[o];}
bool isOptionSet(DeviceOption o) const { return options_[o]; }
//! \~english Set device options
//! \~russian Устанавливает опции устройства
@@ -150,95 +162,95 @@ public:
//! \~english Returns device characteristic flags
//! \~russian Возвращает характеристики канала
DeviceInfoFlags infoFlags() const {return deviceInfoFlags();}
DeviceInfoFlags infoFlags() const { return deviceInfoFlags(); }
//! \~english Returns current path of device
//! \~russian Возвращает текущий путь устройства
PIString path() const {return property("path").toString();}
PIString path() const { return property("path").toString(); }
//! \~english Set path of device. Don`t reopen device
//! \~russian Устанавливает путь устройства. Не переоткрывает устройство
void setPath(const PIString & path) {setProperty("path", path);}
void setPath(const PIString & path) { setProperty("path", path); }
//! \~english Returns if mode is ReadOnly or ReadWrite
//! \~russian Возвращает равен ли режим открытия ReadOnly или ReadWrite
bool isReadable() const {return (mode_ & ReadOnly);}
bool isReadable() const { return (mode_ & ReadOnly); }
//! \~english Returns if mode is WriteOnly or ReadWrite
//! \~russian Возвращает равен ли режим открытия WriteOnly или ReadWrite
bool isWriteable() const {return (mode_ & WriteOnly);}
bool isWriteable() const { return (mode_ & WriteOnly); }
//! \~english Returns if device is successfully opened
//! \~russian Возвращает успешно ли открыто устройство
bool isOpened() const {return opened_;}
bool isOpened() const { return opened_; }
//! \~english Returns if device is closed
//! \~russian Возвращает закрыто ли устройство
bool isClosed() const {return !opened_;}
bool isClosed() const { return !opened_; }
//! \~english Returns if device can read \b now
//! \~russian Возвращает может ли устройство читать \b сейчас
virtual bool canRead() const {return opened_ && (mode_ & ReadOnly);}
virtual bool canRead() const { return opened_ && (mode_ & ReadOnly); }
//! \~english Returns if device can write \b now
//! \~russian Возвращает может ли устройство писать \b сейчас
virtual bool canWrite() const {return opened_ && (mode_ & WriteOnly);}
virtual bool canWrite() const { return opened_ && (mode_ & WriteOnly); }
//! \~english Set calling of \a open() enabled while threaded read on closed device
//! \~russian Устанавливает возможность вызова \a open() при потоковом чтении на закрытом устройстве
void setReopenEnabled(bool yes = true);
//! \~english Set timeout in milliseconds between \a open() tryings if reopen is enabled
//! \~russian Устанавливает задержку в миллисекундах между вызовами \a open() если переоткрытие активно
void setReopenTimeout(int msecs);
//! \~english Returns reopen enable
//! \~russian Возвращает активно ли переоткрытие
bool isReopenEnabled() const {return property("reopenEnabled").toBool();}
bool isReopenEnabled() const { return property("reopenEnabled").toBool(); }
//! \~english Returns reopen timeout in milliseconds
//! \~russian Возвращает задержку переоткрытия в миллисекундах
int reopenTimeout() {return property("reopenTimeout").toInt();}
int reopenTimeout() { return property("reopenTimeout").toInt(); }
//! \~english Set threaded read callback
//! \~russian Устанавливает callback потокового чтения
void setThreadedReadSlot(ReadRetFunc func);
//! \~english Set custom data that will be passed to threaded read callback
//! \~russian Устанавливает произвольный указатель, который будет передан в callback потокового чтения
void setThreadedReadData(void * d) {ret_data_ = d;}
void setThreadedReadData(void * d) { ret_data_ = d; }
//! \~english Set size of threaded read buffer
//! \~russian Устанавливает размер буфера потокового чтения
void setThreadedReadBufferSize(int new_size);
//! \~english Returns size of threaded read buffer
//! \~russian Возвращает размер буфера потокового чтения
int threadedReadBufferSize() const {return threaded_read_buffer_size;}
int threadedReadBufferSize() const { return threaded_read_buffer_size; }
//! \~english Returns content of threaded read buffer
//! \~russian Возвращает содержимое буфера потокового чтения
const uchar * threadedReadBuffer() const {return buffer_tr.data();}
const uchar * threadedReadBuffer() const { return buffer_tr.data(); }
//! \~english Returns custom data that will be passed to threaded read callback
//! \~russian Возвращает произвольный указатель, который будет передан в callback потокового чтения
void * threadedReadData() const {return ret_data_;}
void * threadedReadData() const { return ret_data_; }
//! \~english Returns if threaded read is started
//! \~russian Возвращает запущен ли поток чтения
bool isThreadedRead() const;
//! \~english Start threaded read
//! \~russian Запускает потоковое чтение
void startThreadedRead();
//! \~english Start threaded read and assign threaded read callback to "func"
//! \~russian Запускает потоковое чтение и устанавливает callback потокового чтения в "func"
void startThreadedRead(ReadRetFunc func);
//! \~english Stop threaded read.
//! \~russian Останавливает потоковое чтение.
void stopThreadedRead();
@@ -246,16 +258,16 @@ public:
//! \~english Wait for threaded read finish no longer than "timeout_ms" milliseconds.
//! \~russian Ожидает завершения потокового чтения в течении не более "timeout_ms" миллисекунд.
bool waitThreadedReadFinished(int timeout_ms = -1);
//! \~english Returns if threaded write is started
//! \~russian Возвращает запущен ли поток записи
bool isThreadedWrite() const;
//! \~english Start threaded write
//! \~russian Запускает потоковую запись
void startThreadedWrite();
//! \~english Stop threaded write.
//! \~russian Останавливает потоковую запись.
void stopThreadedWrite();
@@ -268,11 +280,11 @@ public:
//! \~russian Очищает очередь потоковой записи
void clearThreadedWriteQueue();
//! \~english Start both threaded read and threaded write
//! \~russian Запускает потоковое чтение и запись
void start();
//! \~english Stop both threaded read and threaded write.
//! \~russian Останавливает потоковое чтение и запись.
void stop();
@@ -307,7 +319,7 @@ public:
//! \~russian Эта функция как правило используется чтобы знать какой
//! размер буфера нужен в памяти для чтения.
//! Если функция возвращает -1 это значит что количество байт для чтения не известно.
virtual ssize_t bytesAvailable() const {return -1;}
virtual ssize_t bytesAvailable() const { return -1; }
//! \~english Write maximum "max_size" bytes of "data" to device
//! \~russian Пишет в устройство не более "max_size" байт из "data"
@@ -318,28 +330,28 @@ public:
//! \~russian Читает из устройства в течении "timeout_ms" миллисекунд и возвращает данные как PIByteArray.
//! Таймаут должен быть больше 0
PIByteArray readForTime(double timeout_ms);
//! \~english Add task to threaded write queue and return task ID
//! \~russian Добавляет данные в очередь на потоковую запись и возвращает ID задания
ullong writeThreaded(const void * data, ssize_t max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));}
ullong writeThreaded(const void * data, ssize_t max_size) { return writeThreaded(PIByteArray(data, uint(max_size))); }
//! \~english Add task to threaded write queue and return task ID
//! \~russian Добавляет данные в очередь на потоковую запись и возвращает ID задания
ullong writeThreaded(const PIByteArray & data);
//! \~english Configure device from section "section" of file "config_file", if "parent_section" parent section also will be read
//! \~russian
bool configure(const PIString & config_file, const PIString & section, bool parent_section = false);
//! \~english Returns full unambiguous string prefix. \ref PIIODevice_sec7
//! \~russian Возвращает префикс устройства. \ref PIIODevice_sec7
virtual PIConstChars fullPathPrefix() const {return "";}
virtual PIConstChars fullPathPrefix() const { return ""; }
static PIConstChars fullPathPrefixS() { return ""; }
static PIConstChars fullPathPrefixS() {return "";}
//! \~english Returns full unambiguous string, describes this device, \a fullPathPrefix() + "://" + ...
//! \~russian Возвращает строку полного описания для этого устройства, \a fullPathPrefix() + "://" + ...
PIString constructFullPath() const;
@@ -363,7 +375,7 @@ public:
//! \~english Try to create new device by prefix, configure it with \a configureFromVariant() and returns it.
//! \~russian Пытается создать новое устройство по префиксу, настраивает с помощью \a configureFromVariant() и возвращает его
static PIIODevice * createFromVariant(const PIVariantTypes::IODevice & d);
static PIString normalizeFullPath(const PIString & full_path);
static void splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode = 0, DeviceOptions * opts = 0);
@@ -376,9 +388,9 @@ public:
//! \~russian Возвращает имена классов всех зарегистрированных устройств
static PIStringList availableClasses();
static void registerDevice(PIConstChars prefix, PIConstChars classname, PIIODevice*(*fabric)());
static void registerDevice(PIConstChars prefix, PIConstChars classname, PIIODevice * (*fabric)());
EVENT_HANDLER(bool, open);
EVENT_HANDLER1(bool, open, const PIString &, _path);
bool open(DeviceMode _mode);
@@ -388,17 +400,17 @@ public:
//! \~english Write memory block "mb" to device
//! \~russian Пишет в устройство блок памяти "mb"
ssize_t write(const PIMemoryBlock & mb) {return write(mb.data(), mb.size());}
ssize_t write(const PIMemoryBlock & mb) { return write(mb.data(), mb.size()); }
EVENT_VHANDLER(void, flush) { ; }
EVENT_VHANDLER(void, flush) {;}
EVENT(opened);
EVENT(closed);
EVENT2(threadedReadEvent, const uchar * , readed, ssize_t, size);
EVENT2(threadedReadEvent, const uchar *, readed, ssize_t, size);
EVENT2(threadedWriteEvent, ullong, id, ssize_t, written_size);
//! \handlers
//! \{
//! \handlers
//! \{
//! \fn bool open()
//! \~english Open device
@@ -424,17 +436,17 @@ public:
//! \~english Write "data" to device
//! \~russian Пишет "data" в устройство
//! \}
//! \vhandlers
//! \{
//! \}
//! \vhandlers
//! \{
//! \fn void flush()
//! \~english Immediate write all buffers
//! \~russian Немедленно записать все буферизированные данные
//! \}
//! \events
//! \{
//! \}
//! \events
//! \{
//! \fn void opened()
//! \~english Raise if succesfull open
@@ -459,55 +471,61 @@ public:
//! \~english setReopenEnabled, default "true"
//! \~russian setReopenEnabled, по умолчанию "true"
bool reopenEnabled;
//! \~english setReopenTimeout in milliseconds, default 1000
//! \~russian setReopenTimeout в миллисекундах, по умолчанию 1000
int reopenTimeout;
//! \~english setThreadedReadBufferSize in bytes, default 4096
//! \~russian setThreadedReadBufferSize в байтах, по умолчанию 4096
int threadedReadBufferSize;
#endif
//! \}
//! \}
protected:
//! \~english Reimplement to configure device from entries "e_main" and "e_parent", cast arguments to \a PIConfig::Entry*
//! \~russian
virtual bool configureDevice(const void * e_main, const void * e_parent = 0) {return true;}
virtual bool configureDevice(const void * e_main, const void * e_parent = 0) { return true; }
//! \~english Reimplement to open device, return value will be set to "opened_" variable.
//! Don't call this function in subclass, use \a open()!
//! \~russian Переопределите для открытия устройства, возвращаемое значение будет установлено в
//! переменную "opened_". Не используйте напрямую, только через \a open()!
virtual bool openDevice() = 0; // use path_, type_, opened_, init_ variables
//! \~english Reimplement to close device, inverse return value will be set to "opened_" variable
//! \~russian Переопределите для закрытия устройства, обратное возвращаемое значение будет установлено в переменную "opened_"
virtual bool closeDevice() {return true;} // use path_, type_, opened_, init_ variables
virtual bool closeDevice() { return true; } // use path_, type_, opened_, init_ variables
//! \~english Reimplement this function to read from your device
//! \~russian Переопределите для чтения данных из устройства
virtual ssize_t readDevice(void * read_to, ssize_t max_size) {piCoutObj << "\"read\" is not implemented!"; return -2;}
virtual ssize_t readDevice(void * read_to, ssize_t max_size) {
piCoutObj << "\"read\" is not implemented!";
return -2;
}
//! \~english Reimplement this function to write to your device
//! \~russian Переопределите для записи данных в устройство
virtual ssize_t writeDevice(const void * data, ssize_t max_size) {piCoutObj << "\"write\" is not implemented!"; return -2;}
virtual ssize_t writeDevice(const void * data, ssize_t max_size) {
piCoutObj << "\"write\" is not implemented!";
return -2;
}
//! \~english Function executed when thread read some data, default implementation execute external callback "ret_func_"
//! \~russian Метод вызывается после каждого успешного потокового чтения, по умолчанию вызывает callback "ret_func_"
virtual bool threadedRead(const uchar * readed, ssize_t size);
//! \~english Reimplement to construct full unambiguous string, describes this device.
//! Default implementation returns \a path()
//! \~russian Переопределите для создания строки полного описания устройства.
//! По умолчанию возвращает \a path()
virtual PIString constructFullPathDevice() const {return path();}
virtual PIString constructFullPathDevice() const { return path(); }
//! \~english Reimplement to configure your device with parameters of full unambiguous string.
//! Default implementation call \a setPath()
//! \~russian Переопределите для настройки устройства из строки полного описания.
//! По умолчанию вызывает \a setPath()
virtual void configureFromFullPathDevice(const PIString & full_path) {setPath(full_path);}
virtual void configureFromFullPathDevice(const PIString & full_path) { setPath(full_path); }
//! \~english Reimplement to construct device properties.
//! Default implementation return PIPropertyStorage with \"path\" entry
@@ -523,19 +541,19 @@ protected:
//! \~english Reimplement to apply new device options
//! \~russian Переопределите для применения новых опций устройства
virtual void optionsChanged() {;}
virtual void optionsChanged() { ; }
//! \~english Reimplement to return correct \a DeviceInfoFlags. Default implementation returns 0
//! \~russian Переопределите для возврата правильных \a DeviceInfoFlags. По умолчанию возвращает 0
virtual DeviceInfoFlags deviceInfoFlags() const {return 0;}
virtual DeviceInfoFlags deviceInfoFlags() const { return 0; }
//! \~english Reimplement to apply new \a threadedReadBufferSize()
//! \~russian Переопределите для применения нового \a threadedReadBufferSize()
virtual void threadedReadBufferSizeChanged() {;}
virtual void threadedReadBufferSizeChanged() { ; }
static PIIODevice * newDeviceByPrefix(const char * prefix);
bool isThreadedReadStopping() const {return read_thread.isStopping();}
bool isThreadedReadStopping() const { return read_thread.isStopping(); }
DeviceMode mode_;
DeviceOptions options_;
@@ -547,7 +565,7 @@ private:
EVENT_HANDLER(void, read_func);
EVENT_HANDLER(void, write_func);
virtual PIIODevice * copy() const {return nullptr;}
virtual PIIODevice * copy() const { return nullptr; }
PIString fullPathOptions() const;
void _init();
static void cacheFullPath(const PIString & full_path, const PIIODevice * d);
@@ -556,14 +574,13 @@ private:
PITimeMeasurer tm, reopen_tm;
PIThread read_thread, write_thread;
PIByteArray buffer_in, buffer_tr;
PIQueue<PIPair<PIByteArray, ullong> > write_queue;
PIQueue<PIPair<PIByteArray, ullong>> write_queue;
ullong tri = 0;
uint threaded_read_buffer_size, reopen_timeout = 1000;
bool reopen_enabled = true, destroying = false;
static PIMutex nfp_mutex;
static PIMap<PIString, PIString> nfp_cache;
};
#endif // PIIODEVICE_H
+13 -13
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! \defgroup IO IO
//! \~\brief
+15 -20
View File
@@ -5,22 +5,22 @@
* \~russian Функциональность PIBinaryStream для PIIODevice
*/
/*
PIP - Platform Independent Primitives
PIBinaryStream functionality for PIIODevice
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
PIBinaryStream functionality for PIIODevice
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIIOSTREAM_H
@@ -38,14 +38,13 @@
//! \~russian Подробнее \ref iostream
class PIP_EXPORT PIIOBinaryStream: public PIBinaryStream<PIIOBinaryStream> {
public:
//! \~english Contructs %PIIOBinaryStream for "device" device
//! \~russian Создает %PIIOBinaryStream для устройства "device"
PIIOBinaryStream(PIIODevice * device = nullptr): dev(device) {}
//! \~english Assign "device" device
//! \~russian Назначает устройство "device"
void setDevice(PIIODevice * device) {dev = device;}
void setDevice(PIIODevice * device) { dev = device; }
bool binaryStreamAppendImp(const void * d, size_t s) {
if (!dev) return false;
@@ -64,7 +63,6 @@ public:
private:
PIIODevice * dev;
};
@@ -74,7 +72,6 @@ private:
//! \~russian Функциональность PITextStream для PIIODevice.
class PIP_EXPORT PIIOTextStream: public PITextStream<PIIOBinaryStream> {
public:
//! \~english Contructs %PIIOTextStream for "device" device
//! \~russian Создает %PIIOTextStream для устройства "device"
PIIOTextStream(PIIODevice * device): PITextStream<PIIOBinaryStream>(&bin_stream), bin_stream(device) {}
@@ -87,8 +84,7 @@ public:
}
~PIIOTextStream() {
if (io_string)
delete io_string;
if (io_string) delete io_string;
}
void setDevice(PIIODevice * device) {
@@ -99,7 +95,6 @@ public:
private:
PIIOString * io_string = nullptr;
PIIOBinaryStream bin_stream;
};
+17 -17
View File
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
PIIODevice wrapper around PIString
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
PIIODevice wrapper around PIString
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piiostring.h"
@@ -48,7 +48,7 @@ bool PIIOString::open(PIString * string, PIIODevice::DeviceMode mode) {
bool PIIOString::open(const PIString & string) {
str = const_cast<PIString*>(&string);
str = const_cast<PIString *>(&string);
return PIIODevice::open(PIIODevice::ReadOnly);
}
@@ -60,7 +60,7 @@ PIString PIIOString::readLine() {
if ((*str)[np] == '\n') break;
}
PIString ret = str->mid(pos, np - pos);
pos = piMini(np + 1, str->size_s());
pos = piMini(np + 1, str->size_s());
return ret;
}
@@ -71,7 +71,7 @@ ssize_t PIIOString::readDevice(void * read_to, ssize_t max_size) {
pos += max_size;
if (pos > str->size_s()) pos = str->size_s();
const char * cc = rs.data();
int ret = strlen(cc);
int ret = strlen(cc);
memcpy(read_to, cc, ret);
return ret;
}
@@ -79,7 +79,7 @@ ssize_t PIIOString::readDevice(void * read_to, ssize_t max_size) {
ssize_t PIIOString::writeDevice(const void * data, ssize_t max_size) {
if (!canWrite() || !str) return -1;
//piCout << "write" << data;
// piCout << "write" << data;
if (pos > str->size_s()) pos = str->size_s();
PIString rs = PIString::fromUTF8((const char *)data);
if (rs.size_s() > max_size) rs.resize(max_size);
+50 -40
View File
@@ -5,22 +5,22 @@
* \~russian Обертка PIIODevice вокруг PIString
*/
/*
PIP - Platform Independent Primitives
PIIODevice wrapper around PIString
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
PIIODevice wrapper around PIString
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIIOSTRING_H
@@ -33,75 +33,85 @@
//! \~\brief
//! \~english PIIODevice wrapper around PIString.
//! \~russian Обёртка PIIODevice вокруг PIString.
class PIP_EXPORT PIIOString: public PIIODevice
{
class PIP_EXPORT PIIOString: public PIIODevice {
PIIODEVICE(PIIOString, "");
public:
//! \~english Contructs %PIIOString with "string" content and "mode" open mode
//! \~russian Создает %PIIOString с содержимым "string" и режимом открытия "mode"
explicit PIIOString(PIString * string = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Contructs %PIIOString with "string" content only for read
//! \~russian Создает %PIIOString с содержимым "string" только для чтения
explicit PIIOString(const PIString & string);
//! \~english Returns content
//! \~russian Возвращает содержимое
PIString * string() const {return str;}
PIString * string() const { return str; }
//! \~english Clear content string
//! \~russian Очищает содержимое строки
void clear() {if (str) str->clear(); pos = 0;}
void clear() {
if (str) str->clear();
pos = 0;
}
//! \~english Open "string" content with "mode" open mode
//! \~russian Открывает содержимое "string" с режимом открытия "mode"
bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Open "string" content only for read
//! \~russian Открывает содержимое "string" только для чтения
bool open(const PIString & string);
//! \~english Returns if position is at the end of content
//! \~russian Возвращает в конце содержимого ли позиция
bool isEnd() const {if (!str) return true; return pos >= str->size_s();}
bool isEnd() const {
if (!str) return true;
return pos >= str->size_s();
}
//! \~english Move read/write position to "position"
//! \~russian Перемещает позицию чтения/записи на "position"
void seek(llong position) {pos = position;}
void seek(llong position) { pos = position; }
//! \~english Move read/write position to the beginning of the string
//! \~russian Перемещает позицию чтения/записи на начало строки
void seekToBegin() {if (str) pos = 0;}
void seekToBegin() {
if (str) pos = 0;
}
//! \~english Move read/write position to the end of the string
//! \~russian Перемещает позицию чтения/записи на конец строки
void seekToEnd() {if (str) pos = str->size_s();}
void seekToEnd() {
if (str) pos = str->size_s();
}
//! \~english Read one text line and return it
//! \~russian Читает одну строку и возвращает её
PIString readLine();
//! \~english Insert string "string" into content at current position
//! \~russian Вставляет строку "string" в содержимое буфера в текущую позицию
int writeString(const PIString & string);
ssize_t bytesAvailable() const override {
if (str) return str->size() - pos;
else return 0;
if (str)
return str->size() - pos;
else
return 0;
}
protected:
bool openDevice() override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t max_size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Sequential | PIIODevice::Reliable;}
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Sequential | PIIODevice::Reliable; }
ssize_t pos;
PIString * str;
};
#endif // PIIOSTRING_H
+224 -215
View File
@@ -1,49 +1,61 @@
/*
PIP - Platform Independent Primitives
Peer - named I/O ethernet node
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Peer - named I/O ethernet node
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pipeer.h"
#include "piconfig.h"
#include "pidatatransfer.h"
#include "pipropertystorage.h"
#define _PIPEER_MSG_SIZE 4000
#define _PIPEER_MSG_TTL 100
#define _PIPEER_MULTICAST_TTL 4
#define _PIPEER_MULTICAST_IP "232.13.3.12"
#define _PIPEER_LOOPBACK_PORT_S 13313
#define _PIPEER_LOOPBACK_PORT_E (13313+32)
#define _PIPEER_MULTICAST_PORT 13360
#define _PIPEER_TCP_PORT _PIPEER_MULTICAST_PORT
#define _PIPEER_BROADCAST_PORT 13361
#define _PIPEER_TRAFFIC_PORT_S 13400
#define _PIPEER_TRAFFIC_PORT_E 14000
#define _PIPEER_PING_TIMEOUT 5.0
#define _PIPEER_MSG_SIZE 4000
#define _PIPEER_MSG_TTL 100
#define _PIPEER_MULTICAST_TTL 4
#define _PIPEER_MULTICAST_IP "232.13.3.12"
#define _PIPEER_LOOPBACK_PORT_S 13313
#define _PIPEER_LOOPBACK_PORT_E (13313 + 32)
#define _PIPEER_MULTICAST_PORT 13360
#define _PIPEER_TCP_PORT _PIPEER_MULTICAST_PORT
#define _PIPEER_BROADCAST_PORT 13361
#define _PIPEER_TRAFFIC_PORT_S 13400
#define _PIPEER_TRAFFIC_PORT_E 14000
#define _PIPEER_PING_TIMEOUT 5.0
class PIPeer::PeerData: public PIObject {
PIOBJECT_SUBCLASS(PeerData, PIObject);
public:
PeerData(const PIString & n);
~PeerData();
EVENT_HANDLER1(void, dtSendRequestIn, PIByteArray &, data) {data.push_front(uchar(2)); sendRequest(name(), data);}
EVENT_HANDLER1(void, dtSendRequestOut, PIByteArray &, data) {data.push_front(uchar(3)); sendRequest(name(), data);}
EVENT_HANDLER1(void, dtReceiveFinishedIn, bool, ok) {if (ok) received(name(), dt_in.data());}
EVENT_HANDLER1(void, dtReceiveFinishedOut, bool, ok) {if (ok) received(name(), dt_out.data());}
EVENT_HANDLER1(void, dtSendRequestIn, PIByteArray &, data) {
data.push_front(uchar(2));
sendRequest(name(), data);
}
EVENT_HANDLER1(void, dtSendRequestOut, PIByteArray &, data) {
data.push_front(uchar(3));
sendRequest(name(), data);
}
EVENT_HANDLER1(void, dtReceiveFinishedIn, bool, ok) {
if (ok) received(name(), dt_in.data());
}
EVENT_HANDLER1(void, dtReceiveFinishedOut, bool, ok) {
if (ok) received(name(), dt_out.data());
}
EVENT_HANDLER(void, dtThread);
EVENT2(received, const PIString &, from, const PIByteArray &, data);
EVENT2(sendRequest, const PIString &, to, const PIByteArray &, data);
@@ -73,19 +85,18 @@ PIPeer::PeerData::~PeerData() {
dt_in.stop();
dt_out.stop();
t.stop();
if (!t.waitForFinish(1000))
t.terminate();
if (!t.waitForFinish(1000)) t.terminate();
}
void PIPeer::PeerData::dtThread() {
dt_out.send(data);
//piCoutObj << "send DT done";
// piCoutObj << "send DT done";
}
bool PIPeer::PeerData::send(const PIByteArray & d) {
//piCout << "send ..." << t.isRunning();
// piCout << "send ..." << t.isRunning();
if (t.isRunning()) return false;
data = d;
t.startOnce();
@@ -95,13 +106,11 @@ bool PIPeer::PeerData::send(const PIByteArray & d) {
void PIPeer::PeerData::receivedPacket(uchar type, const PIByteArray & d) {
PIDataTransfer * dt = 0;
if (type == 3)
dt = &dt_in;
if (type == 2)
dt = &dt_out;
//piCoutObj << "DT received" << int(type) << d.size_s() << "...";
if (type == 3) dt = &dt_in;
if (type == 2) dt = &dt_out;
// piCoutObj << "DT received" << int(type) << d.size_s() << "...";
if (dt) dt->received(d);
//piCoutObj << "DT received" << int(type) << d.size_s() << "done";
// piCoutObj << "DT received" << int(type) << d.size_s() << "done";
}
@@ -110,10 +119,8 @@ void PIPeer::PeerData::setDist(int dist) {
}
PIPeer::PeerInfo::PeerAddress::PeerAddress(const PIEthernet::Address & a, const PIEthernet::Address & m): address(a), netmask(m) {
ping = -1.;
ping = -1.;
wait_ping = false;
last_ping = PISystemTime::current(true);
}
@@ -121,10 +128,12 @@ PIPeer::PeerInfo::PeerAddress::PeerAddress(const PIEthernet::Address & a, const
int PIPeer::PeerInfo::ping() const {
int ret = -1;
piForeachC (PeerAddress & a, addresses)
piForeachC(PeerAddress & a, addresses)
if (a.ping > 0.) {
if (ret < 0) ret = piRoundd(a.ping);
else ret = piMini(ret, piRoundd(a.ping));
if (ret < 0)
ret = piRoundd(a.ping);
else
ret = piMini(ret, piRoundd(a.ping));
}
return ret;
}
@@ -144,10 +153,10 @@ void PIPeer::PeerInfo::destroy() {
PIEthernet::Address PIPeer::PeerInfo::fastestAddress() const {
double mp = -1.;
PIEthernet::Address ret;
piForeachC (PeerAddress & a, addresses) {
piForeachC(PeerAddress & a, addresses) {
if (a.ping <= 0.) continue;
if ((mp < 0) || (mp > a.ping)) {
mp = a.ping;
mp = a.ping;
ret = a.address;
}
}
@@ -157,9 +166,15 @@ PIEthernet::Address PIPeer::PeerInfo::fastestAddress() const {
REGISTER_DEVICE(PIPeer)
PIPeer::PIPeer(const PIString & n): PIIODevice(), inited__(false), eth_tcp_srv(PIEthernet::TCP_Server), eth_tcp_cli(PIEthernet::TCP_Client), diag_s(false), diag_d(false) {
PIPeer::PIPeer(const PIString & n)
: PIIODevice()
, inited__(false)
, eth_tcp_srv(PIEthernet::TCP_Server)
, eth_tcp_cli(PIEthernet::TCP_Client)
, diag_s(false)
, diag_d(false) {
sync_timer.setName("__S__.PIPeer.sync_timer");
//piCout << " PIPeer" << uint(this);
// piCout << " PIPeer" << uint(this);
destroyed = false;
setDebug(false);
PIMutexLocker mbl(mc_mutex);
@@ -169,18 +184,18 @@ PIPeer::PIPeer(const PIString & n): PIIODevice(), inited__(false), eth_tcp_srv(P
changeName(n);
setReopenTimeout(100);
read_buffer_size = 128;
self_info.dist = 0;
self_info.time = PISystemTime::current();
self_info.dist = 0;
self_info.time = PISystemTime::current();
randomize();
CONNECT2(void, void *, int, &sync_timer, tickEvent, this, timerEvent);
prev_ifaces = PIEthernet::interfaces();
no_timer = false;
no_timer = false;
sync_timer.addDelimiter(5);
}
PIPeer::~PIPeer() {
//piCout << "~PIPeer" << uint(this);
// piCout << "~PIPeer" << uint(this);
stop();
if (destroyed) return;
destroyed = true;
@@ -188,18 +203,18 @@ PIPeer::~PIPeer() {
diag_s.stop();
diag_d.stop();
PIMutexLocker ml(peers_mutex);
piForeach (PeerInfo & p, peers)
piForeach(PeerInfo & p, peers)
if (p._data) {
p._data->dt_in.stop();
p._data->dt_out.stop();
p._data->t.stopAndWait();
}
destroyEths();
piForeach (PIEthernet * i, eths_mcast) {
piForeach(PIEthernet * i, eths_mcast) {
if (!i) continue;
i->stopThreadedRead();
}
piForeach (PIEthernet * i, eths_bcast) {
piForeach(PIEthernet * i, eths_bcast) {
if (!i) continue;
i->stopThreadedRead();
}
@@ -209,20 +224,20 @@ PIPeer::~PIPeer() {
sendSelfRemove();
destroyMBcasts();
eth_send.close();
piForeach (PeerInfo & p, peers)
piForeach(PeerInfo & p, peers)
p.destroy();
}
void PIPeer::timerEvent(void * data, int delim) {
// piCoutObj << "timerEvent" << delim;
// piCoutObj << "timerEvent" << delim;
if (no_timer) return;
switch (delim) {
case 1: // every 1 s
syncPeers();
piMSleep(100);
pingNeighbours();
//piCoutObj << "isOpened" << isOpened();
// piCoutObj << "isOpened" << isOpened();
break;
case 5: // every 5 s
checkNetwork();
@@ -232,10 +247,10 @@ void PIPeer::timerEvent(void * data, int delim) {
void PIPeer::initEths(PIStringList al) {
// piCoutObj << "initEths start";
// piCoutObj << "initEths start";
PIEthernet * ce;
const PIEthernet::Interface * cint = 0;
piForeachC (PIString & a, al) {
piForeachC(PIString & a, al) {
ce = new PIEthernet();
ce->setDebug(false);
ce->setName("__S__PIPeer_traffic_eth_rec_" + a);
@@ -249,8 +264,8 @@ void PIPeer::initEths(PIStringList al) {
self_info.addresses << PeerInfo::PeerAddress(ce->path(), cint == 0 ? "255.255.255.0" : cint->netmask);
CONNECT2(void, const uchar *, ssize_t, ce, threadedReadEvent, this, dataRead);
ce->startThreadedRead();
// piCoutObj << "dc binded to" << ce->path();
// piCoutObj << "add eth" << a;
// piCoutObj << "dc binded to" << ce->path();
// piCoutObj << "add eth" << a;
ok = true;
break;
}
@@ -260,7 +275,7 @@ void PIPeer::initEths(PIStringList al) {
eth_send.setDebug(false);
eth_send.setName("__S__PIPeer_traffic_eth_send");
eth_send.setParameters(0);
// piCoutObj << "initEths ok";
// piCoutObj << "initEths ok";
}
@@ -269,9 +284,9 @@ void PIPeer::initMBcasts(PIStringList al) {
const PIEthernet::Interface * cint;
PIString nm;
al << _PIPEER_MULTICAST_IP;
// piCoutObj << "initMBcasts start" << al;
piForeachC (PIString & a, al) {
//piCout << "mcast try" << a;
// piCoutObj << "initMBcasts start" << al;
piForeachC(PIString & a, al) {
// piCout << "mcast try" << a;
ce = new PIEthernet();
ce->setDebug(false);
ce->setName("__S__PIPeer_mcast_eth_" + a);
@@ -284,31 +299,31 @@ void PIPeer::initMBcasts(PIStringList al) {
eths_mcast << ce;
CONNECT2(void, const uchar *, ssize_t, ce, threadedReadEvent, this, mbcastRead);
ce->startThreadedRead();
// piCout << "mcast bind to" << a << ce->sendIP();
// piCout << "mcast bind to" << a << ce->sendIP();
} else {
delete ce;
//piCoutObj << "invalid address for mcast" << a;
// piCoutObj << "invalid address for mcast" << a;
}
}
al.removeAll(_PIPEER_MULTICAST_IP);
piForeachC (PIString & a, al) {
piForeachC(PIString & a, al) {
ce = new PIEthernet();
ce->setDebug(false);
ce->setName("__S__PIPeer_bcast_eth_" + a);
ce->setParameters(PIEthernet::Broadcast);
cint = prev_ifaces.getByAddress(a);
nm = (cint == 0) ? "255.255.255.0" : cint->netmask;
nm = (cint == 0) ? "255.255.255.0" : cint->netmask;
ce->setSendAddress(PIEthernet::getBroadcast(a, nm), _PIPEER_BROADCAST_PORT);
ce->setReadAddress(a, _PIPEER_BROADCAST_PORT);
if (ce->open()) {
eths_bcast << ce;
CONNECT2(void, const uchar *, ssize_t, ce, threadedReadEvent, this, mbcastRead);
ce->startThreadedRead();
// piCout << "mc BC try" << a << nm << ce->sendIP();
// piCout << "bcast bind to" << a << nm;
// piCout << "mc BC try" << a << nm << ce->sendIP();
// piCout << "bcast bind to" << a << nm;
} else {
delete ce;
//piCoutObj << "invalid address for bcast" << a;
// piCoutObj << "invalid address for bcast" << a;
}
}
eth_lo.setName("__S__PIPeer_eth_loopback");
@@ -321,8 +336,8 @@ void PIPeer::initMBcasts(PIStringList al) {
eth_lo.setSendIP("127.0.0.1");
CONNECT2(void, const uchar *, ssize_t, &eth_lo, threadedReadEvent, this, mbcastRead);
eth_lo.startThreadedRead();
// piCout << "lo binded to" << eth_lo.readAddress() << eth_lo.sendAddress();
//piCout << "add eth" << ta;
// piCout << "lo binded to" << eth_lo.readAddress() << eth_lo.sendAddress();
// piCout << "add eth" << ta;
break;
}
}
@@ -339,16 +354,18 @@ void PIPeer::initMBcasts(PIStringList al) {
CONNECT2(void, const uchar *, ssize_t, &eth_tcp_cli, threadedReadEvent, this, mbcastRead);
CONNECTU(&eth_tcp_cli, disconnected, this, tcpClientReconnect);
eth_tcp_cli.startThreadedRead();
if (eths_mcast.isEmpty() && eths_bcast.isEmpty() && !eth_lo.isOpened()) piCoutObj << "Warning! Can`t find suitable network interface for multicast receive, check for exists at least one interface with multicasting enabled!";
// piCoutObj << "initMBcasts ok";
if (eths_mcast.isEmpty() && eths_bcast.isEmpty() && !eth_lo.isOpened())
piCoutObj << "Warning! Can`t find suitable network interface for multicast receive, check for exists at least one interface with "
"multicasting enabled!";
// piCoutObj << "initMBcasts ok";
}
void PIPeer::destroyEths() {
piForeach (PIEthernet * i, eths_traffic) {
piForeach(PIEthernet * i, eths_traffic) {
if (!i) continue;
((PIThread*)i)->stop();
((PIThread*)i)->waitForFinish(100);
((PIThread *)i)->stop();
((PIThread *)i)->waitForFinish(100);
i->stopThreadedRead();
i->close();
delete i;
@@ -359,10 +376,10 @@ void PIPeer::destroyEths() {
void PIPeer::destroyMBcasts() {
piForeach (PIEthernet * i, eths_mcast) {
piForeach(PIEthernet * i, eths_mcast) {
if (!i) continue;
((PIThread*)i)->stop();
((PIThread*)i)->waitForFinish(100);
((PIThread *)i)->stop();
((PIThread *)i)->waitForFinish(100);
i->stopThreadedRead();
i->leaveMulticastGroup(_PIPEER_MULTICAST_IP);
i->close();
@@ -370,18 +387,18 @@ void PIPeer::destroyMBcasts() {
i = 0;
}
eths_mcast.clear();
piForeach (PIEthernet * i, eths_bcast) {
piForeach(PIEthernet * i, eths_bcast) {
if (!i) continue;
((PIThread*)i)->stop();
((PIThread*)i)->waitForFinish(100);
((PIThread *)i)->stop();
((PIThread *)i)->waitForFinish(100);
i->stopThreadedRead();
i->close();
delete i;
i = 0;
}
eths_bcast.clear();
((PIThread*)&eth_lo)->stop();
((PIThread*)&eth_lo)->waitForFinish(100);
((PIThread *)&eth_lo)->stop();
((PIThread *)&eth_lo)->waitForFinish(100);
eth_lo.stopThreadedRead();
eth_lo.close();
eth_tcp_srv.stop();
@@ -390,8 +407,8 @@ void PIPeer::destroyMBcasts() {
PIPeer::PeerInfo * PIPeer::quickestPeer(const PIString & to) {
if (!peers_map.contains(to)) return 0;
//piCout << "*** search quickest peer" << to;
PIVector<PeerInfo * > tp = addresses_map.value(to);
// piCout << "*** search quickest peer" << to;
PIVector<PeerInfo *> tp = addresses_map.value(to);
if (tp.isEmpty()) return 0;
return tp.back();
}
@@ -399,12 +416,12 @@ PIPeer::PeerInfo * PIPeer::quickestPeer(const PIString & to) {
bool PIPeer::send(const PIString & to, const void * data, int size) {
PIByteArray ba(data, size);
// piCoutObj << "send" << ba.size_s() << "bytes" << _PIPEER_MSG_SIZE;
// piCoutObj << "send" << ba.size_s() << "bytes" << _PIPEER_MSG_SIZE;
if (ba.size_s() <= _PIPEER_MSG_SIZE) {
ba.insert(0, uchar(1));
return sendInternal(to, ba);
} else {
//ba.insert(0, uchar(2));
// ba.insert(0, uchar(2));
PIMutexLocker mlocker(peers_mutex);
PeerInfo * dp = const_cast<PeerInfo *>(getPeerByName(to));
if (!dp) return false;
@@ -418,14 +435,14 @@ bool PIPeer::sendInternal(const PIString & to, const PIByteArray & data) {
PIMutexLocker mlocker(peers_mutex);
PeerInfo * dp = quickestPeer(to);
if (dp == 0) {
//piCoutObj << "Can`t find peer \"" << to << "\"!";
// piCoutObj << "Can`t find peer \"" << to << "\"!";
return false;
}
PIByteArray ba;
ba << int(4) << self_info.name << to << int(0) << data;
// piCoutObj << "sendInternal to" << to << data.size_s() << int(data.front());
// piCoutObj << "sendInternal to" << to << data.size_s() << int(data.front());
if (!sendToNeighbour(dp, ba)) {
//piCoutObj << "send error";
// piCoutObj << "send error";
return false;
}
return true;
@@ -446,7 +463,7 @@ void PIPeer::dtReceived(const PIString & from, const PIByteArray & data) {
bool PIPeer::dataRead(const uchar * readed, ssize_t size) {
if (destroyed) {
//piCout << "[PIPeer] SegFault";
// piCout << "[PIPeer] SegFault";
return true;
}
if (size < 16) return true;
@@ -455,23 +472,22 @@ bool PIPeer::dataRead(const uchar * readed, ssize_t size) {
PIString from, to;
ba >> type;
eth_mutex.lock();
// piCout << "dataRead lock";
// piCout << "dataRead lock";
if (type == 5) { // ping request
PIEthernet::Address addr;
PISystemTime time;
ba >> to >> from >> addr >> time;
// piCout << "ping request" << to << from << addr;
// piCout << "ping request" << to << from << addr;
PIMutexLocker plocker(peers_mutex);
if (from == self_info.name) { // send ping back
const PeerInfo * pi = getPeerByName(to);
if (pi) {
if (pi->isNeighbour()) {
sba << int(6) << to << from << addr << time;
// piCout << " ping from" << from << addr << ", send back to" << pi->name;
// piCout << " ping from" << from << addr << ", send back to" << pi->name;
send_mutex.lock();
piForeachC (PeerInfo::PeerAddress & a, pi->addresses) {
if (eth_send.send(a.address, sba))
diag_s.received(sba.size_s());
piForeachC(PeerInfo::PeerAddress & a, pi->addresses) {
if (eth_send.send(a.address, sba)) diag_s.received(sba.size_s());
}
send_mutex.unlock();
}
@@ -484,21 +500,23 @@ bool PIPeer::dataRead(const uchar * readed, ssize_t size) {
PIEthernet::Address addr;
PISystemTime time, ptime, ctime = PISystemTime::current(true);
ba >> to >> from >> addr >> time;
// piCout << "ping reply" << to << from << addr;
// piCout << "ping reply" << to << from << addr;
PIMutexLocker plocker(peers_mutex);
if (to == self_info.name) { // ping echo
piForeach (PeerInfo & p, peers) {
piForeach(PeerInfo & p, peers) {
if (!p.isNeighbour()) continue;
if (p.name != from) continue;
piForeach (PeerInfo::PeerAddress & a, p.addresses) {
piForeach(PeerInfo::PeerAddress & a, p.addresses) {
if (a.address != addr) continue;
if (a.last_ping >= time) break;
ptime = ctime - time;
ptime = ctime - time;
a.last_ping = time;
a.wait_ping = false;
if (a.ping < 0) a.ping = ptime.toMilliseconds();
else a.ping = 0.6 * a.ping + 0.4 * ptime.toMilliseconds();
// piCout << " ping echo" << p.name << a.address << a.ping;
if (a.ping < 0)
a.ping = ptime.toMilliseconds();
else
a.ping = 0.6 * a.ping + 0.4 * ptime.toMilliseconds();
// piCout << " ping echo" << p.name << a.address << a.ping;
eth_mutex.unlock();
return true;
}
@@ -507,20 +525,20 @@ bool PIPeer::dataRead(const uchar * readed, ssize_t size) {
eth_mutex.unlock();
return true;
}
// piCoutObj << "received data from" << from << "packet" << type;
// piCoutObj << "received data from" << from << "packet" << type;
if (type != 4) {
eth_mutex.unlock();
return true;
}
diag_d.received(size);
ba >> from >> to >> cnt >> pba;
//piCoutObj << "Received packet" << type << from << to << pba.size_s();
if (type == 4) { // data packet
// piCoutObj << "Received packet" << type << from << to << pba.size_s();
if (type == 4) { // data packet
if (to == self_info.name) { // my packet
uchar pt = pba.take_front();
//piCoutObj << "Received packet" << type << from << to << int(pt) << pba.size_s();
// piCoutObj << "Received packet" << type << from << to << int(pt) << pba.size_s();
peers_mutex.lock();
PeerInfo * fp = const_cast<PeerInfo * >(getPeerByName(from));
PeerInfo * fp = const_cast<PeerInfo *>(getPeerByName(from));
if (fp == 0) {
peers_mutex.unlock();
eth_mutex.unlock();
@@ -535,8 +553,7 @@ bool PIPeer::dataRead(const uchar * readed, ssize_t size) {
if (pt == 2 || pt == 3) {
peers_mutex.unlock();
eth_mutex.unlock();
if (fp->_data)
fp->_data->receivedPacket(pt, pba);
if (fp->_data) fp->_data->receivedPacket(pt, pba);
return true;
}
peers_mutex.unlock();
@@ -546,14 +563,14 @@ bool PIPeer::dataRead(const uchar * readed, ssize_t size) {
PIMutexLocker plocker(peers_mutex);
PeerInfo * dp = quickestPeer(to);
if (dp == 0) {
//piCoutObj << "Can`t find peer \"" << to << "\"!";
// piCoutObj << "Can`t find peer \"" << to << "\"!";
eth_mutex.unlock();
return true;
}
cnt++;
if (cnt > _PIPEER_MSG_TTL || from == dp->name) return true;
sba << type << from << to << cnt << pba;
//piCout << "translate packet" << from << "->" << to << ", ttl =" << cnt;
// piCout << "translate packet" << from << "->" << to << ", ttl =" << cnt;
sendToNeighbour(dp, sba);
}
eth_mutex.unlock();
@@ -563,7 +580,7 @@ bool PIPeer::dataRead(const uchar * readed, ssize_t size) {
bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
if (destroyed) {
//piCout << "[PIPeer] SegFault";
// piCout << "[PIPeer] SegFault";
return true;
}
if (size < 8) return true;
@@ -573,17 +590,17 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
if (type <= 0 || type >= 4) return true;
PeerInfo pi;
ba >> pi.name;
//piCout << "received mb from" << pi.name << "packet" << type;
// piCout << "received mb from" << pi.name << "packet" << type;
if (pi.name == self_info.name) return true;
PIMutexLocker locker(mc_mutex);
diag_s.received(size);
const PeerInfo * rpi = 0;
bool ch = false;
bool ch = false;
PIVector<PeerInfo> rpeers;
//piCout << "analyz ...";
// piCout << "analyz ...";
switch (type) {
case 1: // new peer
//piCout << "new peer packet ...";
// piCout << "new peer packet ...";
peers_mutex.lock();
if (!hasPeer(pi.name)) {
ba >> pi;
@@ -595,13 +612,13 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
pi.resetPing();
addPeer(pi);
buildMap();
// piCoutObj << "new peer \"" << pi.name << "\"" << " dist " << pi.dist;
// piCoutObj << mode() << opened_;
// piCoutObj << "new peer \"" << pi.name << "\"" << " dist " << pi.dist;
// piCoutObj << mode() << opened_;
pi.dist++;
sendSelfInfo();
sendPeerInfo(pi);
ch = true;
//piCout << "new peer packet ok";
// piCout << "new peer packet ok";
}
peers_mutex.unlock();
if (ch) {
@@ -610,7 +627,7 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
}
break;
case 2: // remove peer
//piCout << "remove peer packet ..." << pi.name;
// piCout << "remove peer packet ..." << pi.name;
peers_mutex.lock();
removeNeighbour(pi.name);
rpi = getPeerByName(pi.name);
@@ -618,13 +635,12 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
dist = rpi->dist;
addToRemoved(*rpi);
removePeer(pi.name);
//piCoutObj << "remove peer \"" << pi.name << "\"";
if (dist == 0)
self_info.removeNeighbour(pi.name);
// piCoutObj << "remove peer \"" << pi.name << "\"";
if (dist == 0) self_info.removeNeighbour(pi.name);
sendPeerRemove(pi.name);
buildMap();
ch = true;
//piCout << "remove peer packet ok";
// piCout << "remove peer packet ok";
}
peers_mutex.unlock();
if (ch) {
@@ -633,13 +649,13 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
}
break;
case 3: // sync peers
//piCout << "sync packet ...";
// piCout << "sync packet ...";
ba >> pi >> rpeers;
rpeers << pi;
//piCoutObj << "rec sync " << rpeers.size_s() << " peers";
// piCoutObj << "rec sync " << rpeers.size_s() << " peers";
peers_mutex.lock();
if (!self_info.neighbours.contains(pi.name)) {
//piCoutObj << "add new nei to me" << pi.name;
// piCoutObj << "add new nei to me" << pi.name;
self_info.addNeighbour(pi.name);
PeerInfo * np = peers_map.value(pi.name);
if (np) {
@@ -648,21 +664,21 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
}
ch = true;
}
piForeach (PeerInfo & rpeer, rpeers) {
//piCout << " to sync " << rpeer.name;
piForeach(PeerInfo & rpeer, rpeers) {
// piCout << " to sync " << rpeer.name;
if (rpeer.name == self_info.name) continue;
bool exist = false;
piForeach (PeerInfo & peer, peers) {
piForeach(PeerInfo & peer, peers) {
if (peer.name == rpeer.name) {
exist = true;
if (isPeerRecent(peer, rpeer)) {
//piCout << "synced " << peer.name;
// piCout << "synced " << peer.name;
for (int z = 0; z < rpeer.addresses.size_s(); ++z) {
PeerInfo::PeerAddress & ra(rpeer.addresses[z]);
for (int k = 0; k < peer.addresses.size_s(); ++k) {
PeerInfo::PeerAddress & a(peer.addresses[k]);
if (ra.address == a.address) {
ra.ping = a.ping;
ra.ping = a.ping;
ra.wait_ping = a.wait_ping;
ra.last_ping = a.last_ping;
break;
@@ -670,9 +686,9 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
}
}
peer.was_update = true;
peer.addresses = rpeer.addresses;
peer.cnt = rpeer.cnt;
peer.time = rpeer.time;
peer.addresses = rpeer.addresses;
peer.cnt = rpeer.cnt;
peer.time = rpeer.time;
peer.addNeighbours(rpeer.neighbours);
rpeer.neighbours = peer.neighbours;
if (peer.name == pi.name) peer.sync = 0;
@@ -690,19 +706,18 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
peerConnected(rpeer.name);
peerConnectedEvent(rpeer.name);
}
//piCout << "***";
//piCout << self_info.name << self_info.neighbours;
piForeach (PeerInfo & i, peers) {
// piCout << "***";
// piCout << self_info.name << self_info.neighbours;
piForeach(PeerInfo & i, peers) {
if (i.dist == 0) {
self_info.addNeighbour(i.name);
i.addNeighbour(self_info.name);
}
//piCout << i.name << i.neighbours;
// piCout << i.name << i.neighbours;
}
if (ch)
buildMap();
if (ch) buildMap();
peers_mutex.unlock();
//piCoutObj << "after sync " << peers.size_s() << " peers";
// piCoutObj << "after sync " << peers.size_s() << " peers";
break;
}
return true;
@@ -711,10 +726,10 @@ bool PIPeer::mbcastRead(const uchar * data, ssize_t size) {
bool PIPeer::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) {
PIEthernet::Address addr = peer->fastestAddress();
//piCout << "[PIPeer] sendToNeighbour" << peer->name << addr << ba.size_s() << "bytes ...";
// piCout << "[PIPeer] sendToNeighbour" << peer->name << addr << ba.size_s() << "bytes ...";
send_mutex.lock();
bool ok = eth_send.send(addr, ba);
//piCout << "[PIPeer] sendToNeighbour" << (ok ? "ok" : "fail");
// piCout << "[PIPeer] sendToNeighbour" << (ok ? "ok" : "fail");
if (ok) diag_d.sended(ba.size_s());
send_mutex.unlock();
return ok;
@@ -723,39 +738,34 @@ bool PIPeer::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) {
void PIPeer::sendMBcast(const PIByteArray & ba) {
send_mc_mutex.lock();
// piCout << "sendMBcast" << ba.size() << "bytes ...";
piForeach (PIEthernet * e, eths_mcast) {
// piCout << "sendMBcast" << ba.size() << "bytes ...";
piForeach(PIEthernet * e, eths_mcast) {
if (e->isOpened())
if (e->send(ba))
diag_s.sended(ba.size_s());
if (e->send(ba)) diag_s.sended(ba.size_s());
}
piForeach (PIEthernet * e, eths_bcast) {
piForeach(PIEthernet * e, eths_bcast) {
if (e->isOpened())
if (e->send(ba))
diag_s.sended(ba.size_s());
if (e->send(ba)) diag_s.sended(ba.size_s());
}
for (int p = _PIPEER_LOOPBACK_PORT_S; p <= _PIPEER_LOOPBACK_PORT_E; ++p) {
eth_lo.setSendPort(p);
if (eth_lo.send(ba))
diag_s.sended(ba.size_s());
if (eth_lo.send(ba)) diag_s.sended(ba.size_s());
}
PIVector<PIEthernet * > cl = eth_tcp_srv.clients();
piForeach (PIEthernet * e, cl) {
PIVector<PIEthernet *> cl = eth_tcp_srv.clients();
piForeach(PIEthernet * e, cl) {
if (e->isOpened() && e->isConnected())
if (e->send(ba))
diag_s.sended(ba.size_s());
if (e->send(ba)) diag_s.sended(ba.size_s());
}
if (eth_tcp_cli.isOpened() && eth_tcp_cli.isConnected()) {
if (eth_tcp_cli.send(ba))
diag_s.sended(ba.size_s());
if (eth_tcp_cli.send(ba)) diag_s.sended(ba.size_s());
}
// piCout << "sendMBcast ok";
// piCout << "sendMBcast ok";
send_mc_mutex.unlock();
}
void PIPeer::removeNeighbour(const PIString & name) {
piForeach (PeerInfo & p, peers)
piForeach(PeerInfo & p, peers)
p.neighbours.removeOne(name);
self_info.removeNeighbour(name);
}
@@ -789,7 +799,7 @@ void PIPeer::sendPeerInfo(const PeerInfo & info) {
void PIPeer::sendPeerRemove(const PIString & peer) {
//piCout << name() << "sendPeerRemove" << peer;
// piCout << name() << "sendPeerRemove" << peer;
PIByteArray ba;
ba << int(2) << peer;
sendMBcast(ba);
@@ -800,28 +810,26 @@ void PIPeer::pingNeighbours() {
PIMutexLocker ml(peers_mutex);
PIByteArray ba, sba;
ba << int(5) << self_info.name;
// piCoutObj << "*** pingNeighbours" << peers.size() << "...";
piForeach (PeerInfo & p, peers) {
// piCoutObj << "*** pingNeighbours" << peers.size() << "...";
piForeach(PeerInfo & p, peers) {
if (!p.isNeighbour()) continue;
//piCout << " ping neighbour" << p.name << p.ping();
// piCout << " ping neighbour" << p.name << p.ping();
send_mutex.lock();
piForeach (PeerInfo::PeerAddress & a, p.addresses) {
// piCout << " address" << a.address << a.wait_ping;
piForeach(PeerInfo::PeerAddress & a, p.addresses) {
// piCout << " address" << a.address << a.wait_ping;
if (a.wait_ping) {
if ((PISystemTime::current(true) - a.last_ping).abs().toSeconds() <= _PIPEER_PING_TIMEOUT)
continue;
if ((PISystemTime::current(true) - a.last_ping).abs().toSeconds() <= _PIPEER_PING_TIMEOUT) continue;
a.ping = -1.;
}
a.wait_ping = true;
sba = ba;
sba = ba;
sba << p.name << a.address << PISystemTime::current(true);
// piCout << "ping" << p.name << a.address << a.last_ping;
if (eth_send.send(a.address, sba))
diag_s.sended(sba.size_s());
// piCout << "ping" << p.name << a.address << a.last_ping;
if (eth_send.send(a.address, sba)) diag_s.sended(sba.size_s());
}
send_mutex.unlock();
}
//piCout << "*** pingNeighbours" << peers.size() << "done";
// piCout << "*** pingNeighbours" << peers.size() << "done";
}
@@ -832,12 +840,13 @@ bool PIPeer::openDevice() {
#else
"pip.conf"
#endif
, PIIODevice::ReadOnly);
,
PIIODevice::ReadOnly);
server_ip = conf.getValue("peer_server_ip", "").toString();
reinit();
diag_d.reset();
diag_s.reset();
//piCoutObj << "open...";
// piCoutObj << "open...";
return true;
}
@@ -848,9 +857,9 @@ bool PIPeer::closeDevice() {
void PIPeer::syncPeers() {
//piCout << "[PIPeer \"" + self_info.name + "\"] sync " << peers.size_s() << " peers";
// piCout << "[PIPeer \"" + self_info.name + "\"] sync " << peers.size_s() << " peers";
PIMutexLocker locker(eth_mutex);
// piCout << "syncPeers lock";
// piCout << "syncPeers lock";
PIString pn;
bool change = false;
PIStringList dpeers;
@@ -859,7 +868,7 @@ void PIPeer::syncPeers() {
PeerInfo & cp(peers[i]);
if (cp.sync > 3) {
pn = cp.name;
//piCout << "sync: remove " << pn;
// piCout << "sync: remove " << pn;
cp.destroy();
addToRemoved(cp);
peers.remove(i);
@@ -874,8 +883,7 @@ void PIPeer::syncPeers() {
cp.sync = 0;
else
cp.sync++;
if (cp._data)
cp._data->setDist(cp.dist + 1);
if (cp._data) cp._data->setDist(cp.dist + 1);
cp.was_update = false;
}
if (change) buildMap();
@@ -885,7 +893,7 @@ void PIPeer::syncPeers() {
ba << int(3) << self_info.name << self_info << peers;
peers_mutex.unlock();
sendMBcast(ba);
piForeachC (PIString & p, dpeers) {
piForeachC(PIString & p, dpeers) {
peerDisconnected(p);
peerDisconnectedEvent(p);
}
@@ -904,7 +912,7 @@ void PIPeer::reinit() {
no_timer = true;
PIMutexLocker mbl(mc_mutex);
PIMutexLocker ethl(eth_mutex);
// piCout << "reinit lock";
// piCout << "reinit lock";
PIMutexLocker pl(peers_mutex);
PIMutexLocker sl(send_mutex);
initNetwork();
@@ -914,13 +922,13 @@ void PIPeer::reinit() {
}
void PIPeer::changeName(const PIString &new_name) {
void PIPeer::changeName(const PIString & new_name) {
PIString name_ = new_name;
if (name_.isEmpty()) name_ = "rnd_" + PIString::fromNumber(randomi() % 1000);
setName(name_);
self_info.name = name_;
diag_d.setName(name_+"_data");
diag_s.setName(name_+"_service");
diag_d.setName(name_ + "_data");
diag_s.setName(name_ + "_service");
}
@@ -933,7 +941,7 @@ ssize_t PIPeer::bytesAvailable() const {
}
ssize_t PIPeer::readDevice(void *read_to, ssize_t max_size) {
ssize_t PIPeer::readDevice(void * read_to, ssize_t max_size) {
read_buffer_mutex.lock();
bool empty = read_buffer.isEmpty();
read_buffer_mutex.unlock();
@@ -956,18 +964,19 @@ ssize_t PIPeer::readDevice(void *read_to, ssize_t max_size) {
}
ssize_t PIPeer::writeDevice(const void *data, ssize_t size) {
ssize_t PIPeer::writeDevice(const void * data, ssize_t size) {
if (trust_peer.isEmpty()) {
sendToAll(data, size);
return size;
}
if (send(trust_peer, data, size))
return size;
else return -1;
else
return -1;
}
void PIPeer::newTcpClient(PIEthernet *client) {
void PIPeer::newTcpClient(PIEthernet * client) {
client->setName("__S__PIPeer_eth_TCP_ServerClient" + client->path());
piCoutObj << "client" << client->path();
CONNECT2(void, const uchar *, ssize_t, client, threadedReadEvent, this, mbcastRead);
@@ -1009,45 +1018,45 @@ void PIPeer::configureFromVariantDevice(const PIPropertyStorage & d) {
void PIPeer::initNetwork() {
// piCoutObj << "initNetwork ...";
// piCoutObj << "initNetwork ...";
eth_send.init();
destroyEths();
destroyMBcasts();
piMSleep(100);
// piCoutObj << self_info.addresses.size();
// piCoutObj << self_info.addresses.size();
self_info.addresses.clear();
PIVector<PIEthernet::Address> al = PIEthernet::allAddresses();
PIStringList sl;
for (const PIEthernet::Address & a : al) {
for (const PIEthernet::Address & a: al) {
sl << a.ipString();
}
initEths(sl);
// piCoutObj << sl << self_info.addresses.size();
// piCoutObj << sl << self_info.addresses.size();
sl.removeAll("127.0.0.1");
initMBcasts(sl);
diag_d.start();
diag_s.start();
// piCoutObj << "initNetwork done";
// piCoutObj << "initNetwork done";
}
void PIPeer::buildMap() {
//piCout << "[PIPeer \"" + name_ + "\"] buildMap";
// piCout << "[PIPeer \"" + name_ + "\"] buildMap";
peers_map.clear();
addresses_map.clear();
piForeach (PeerInfo & i, peers) {
i.trace = -1;
piForeach(PeerInfo & i, peers) {
i.trace = -1;
peers_map[i.name] = &i;
}
PIVector<PeerInfo * > cwave, nwave;
int cwi = 0;
PIVector<PeerInfo *> cwave, nwave;
int cwi = 0;
self_info.trace = 0;
cwave << &self_info;
while (!cwave.isEmpty()) {
nwave.clear();
++cwi;
piForeachC (PeerInfo * p, cwave) {
piForeachC (PIString & nn, p->neighbours) {
piForeachC(PeerInfo * p, cwave) {
piForeachC(PIString & nn, p->neighbours) {
PeerInfo * np = peers_map.value(nn);
if (!np) continue;
if (np->trace >= 0) continue;
@@ -1057,15 +1066,15 @@ void PIPeer::buildMap() {
}
cwave = nwave;
}
PIVector<PeerInfo * > cpath;
piForeach (PeerInfo & c, peers) {
PIVector<PeerInfo *> cpath;
piForeach(PeerInfo & c, peers) {
cpath.clear();
cpath << &c;
cwave << &c;
for (int w = c.trace - 1; w >= 0; --w) {
nwave.clear();
piForeachC (PeerInfo * p, cwave) {
piForeachC (PIString & nn, p->neighbours) {
piForeachC(PeerInfo * p, cwave) {
piForeachC(PIString & nn, p->neighbours) {
PeerInfo * np = peers_map.value(nn);
if (!np) continue;
if (np->trace != w) continue;
@@ -1076,7 +1085,7 @@ void PIPeer::buildMap() {
cwave = nwave;
}
addresses_map[c.name] = cpath;
//piCout << "map" << c.name << "=" << cpath;
// piCout << "map" << c.name << "=" << cpath;
}
}
+154 -93
View File
@@ -5,36 +5,36 @@
* \~russian Элемент пиринговой сети
*/
/*
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIPEER_H
#define PIPEER_H
#include "piethernet.h"
#include "pidiagnostics.h"
#include "piethernet.h"
class PIP_EXPORT PIPeer: public PIIODevice
{
class PIP_EXPORT PIPeer: public PIIODevice {
PIIODEVICE(PIPeer, "peer");
private:
class PeerData;
public:
explicit PIPeer(const PIString & name = PIString());
virtual ~PIPeer();
@@ -42,117 +42,156 @@ public:
class PIP_EXPORT PeerInfo {
friend class PIPeer;
BINARY_STREAM_FRIEND(PIPeer::PeerInfo);
public:
PeerInfo() {dist = sync = cnt = 0; trace = -1; was_update = false; _data = 0;}
PeerInfo() {
dist = sync = cnt = 0;
trace = -1;
was_update = false;
_data = 0;
}
~PeerInfo() {}
struct PIP_EXPORT PeerAddress {
PeerAddress(const PIEthernet::Address & a = PIEthernet::Address(), const PIEthernet::Address & m = PIEthernet::Address("255.255.255.0"));
bool isAvailable() const {return ping > 0;}
PeerAddress(const PIEthernet::Address & a = PIEthernet::Address(),
const PIEthernet::Address & m = PIEthernet::Address("255.255.255.0"));
bool isAvailable() const { return ping > 0; }
PIEthernet::Address address;
PIEthernet::Address netmask;
double ping; // ms
bool wait_ping;
PISystemTime last_ping;
};
PIString name;
PIVector<PeerAddress> addresses;
int dist;
PIStringList neighbours;
bool isNeighbour() const {return dist == 0;}
bool isNeighbour() const { return dist == 0; }
int ping() const;
PIEthernet::Address fastestAddress() const;
protected:
void addNeighbour(const PIString & n) {if (!neighbours.contains(n)) neighbours << n;}
void addNeighbours(const PIStringList & l) {piForeachC (PIString & n, l) if (!neighbours.contains(n)) neighbours << n;}
void removeNeighbour(const PIString & n) {neighbours.removeAll(n);}
void resetPing() {for (int i = 0; i < addresses.size_s(); ++i) addresses[i].ping = -1;}
void addNeighbour(const PIString & n) {
if (!neighbours.contains(n)) neighbours << n;
}
void addNeighbours(const PIStringList & l) {
piForeachC(PIString & n, l)
if (!neighbours.contains(n)) neighbours << n;
}
void removeNeighbour(const PIString & n) { neighbours.removeAll(n); }
void resetPing() {
for (int i = 0; i < addresses.size_s(); ++i)
addresses[i].ping = -1;
}
void init();
void destroy();
int sync, cnt, trace;
bool was_update;
PISystemTime time;
PeerData * _data;
};
BINARY_STREAM_FRIEND(PIPeer::PeerInfo);
bool send(const PIString & to, const PIByteArray & data) {return send(to, data.data(), data.size_s());}
bool send(const PIString & to, const PIString & data) {return send(to, data.data(), data.size_s());}
bool send(const PIString & to, const PIByteArray & data) { return send(to, data.data(), data.size_s()); }
bool send(const PIString & to, const PIString & data) { return send(to, data.data(), data.size_s()); }
bool send(const PIString & to, const void * data, int size);
bool send(const PeerInfo & to, const PIByteArray & data) {return send(to.name, data.data(), data.size_s());}
bool send(const PeerInfo & to, const PIString & data) {return send(to.name, data.data(), data.size_s());}
bool send(const PeerInfo & to, const void * data, int size) {return send(to.name, data, size);}
bool send(const PeerInfo * to, const PIByteArray & data) {if (to == 0) return false; return send(to->name, data.data(), data.size_s());}
bool send(const PeerInfo * to, const PIString & data) {if (to == 0) return false; return send(to->name, data.data(), data.size_s());}
bool send(const PeerInfo * to, const void * data, int size) {if (to == 0) return false; return send(to->name, data, size);}
void sendToAll(const PIByteArray & data) {piForeachC (PeerInfo & i, peers) send(i.name, data.data(), data.size_s());}
void sendToAll(const PIString & data) {piForeachC (PeerInfo & i, peers) send(i.name, data.data(), data.size_s());}
void sendToAll(const void * data, int size) {piForeachC (PeerInfo & i, peers) send(i.name, data, size);}
bool isMulticastReceive() const {return !eths_mcast.isEmpty();}
bool isBroadcastReceive() const {return !eths_bcast.isEmpty();}
PIDiagnostics & diagnosticService() {return diag_s;}
PIDiagnostics & diagnosticData() {return diag_d;}
const PIVector<PIPeer::PeerInfo> & allPeers() const {return peers;}
bool isPeerExists(const PIString & name) const {return getPeerByName(name) != 0;}
const PeerInfo * getPeerByName(const PIString & name) const {return peers_map.value(name, 0);}
const PeerInfo & selfInfo() const {return self_info;}
const PIMap<PIString, PIVector<PeerInfo * > > & _peerMap() const {return addresses_map;}
bool send(const PeerInfo & to, const PIByteArray & data) { return send(to.name, data.data(), data.size_s()); }
bool send(const PeerInfo & to, const PIString & data) { return send(to.name, data.data(), data.size_s()); }
bool send(const PeerInfo & to, const void * data, int size) { return send(to.name, data, size); }
bool send(const PeerInfo * to, const PIByteArray & data) {
if (to == 0) return false;
return send(to->name, data.data(), data.size_s());
}
bool send(const PeerInfo * to, const PIString & data) {
if (to == 0) return false;
return send(to->name, data.data(), data.size_s());
}
bool send(const PeerInfo * to, const void * data, int size) {
if (to == 0) return false;
return send(to->name, data, size);
}
void sendToAll(const PIByteArray & data) {
piForeachC(PeerInfo & i, peers)
send(i.name, data.data(), data.size_s());
}
void sendToAll(const PIString & data) {
piForeachC(PeerInfo & i, peers)
send(i.name, data.data(), data.size_s());
}
void sendToAll(const void * data, int size) {
piForeachC(PeerInfo & i, peers)
send(i.name, data, size);
}
bool isMulticastReceive() const { return !eths_mcast.isEmpty(); }
bool isBroadcastReceive() const { return !eths_bcast.isEmpty(); }
PIDiagnostics & diagnosticService() { return diag_s; }
PIDiagnostics & diagnosticData() { return diag_d; }
const PIVector<PIPeer::PeerInfo> & allPeers() const { return peers; }
bool isPeerExists(const PIString & name) const { return getPeerByName(name) != 0; }
const PeerInfo * getPeerByName(const PIString & name) const { return peers_map.value(name, 0); }
const PeerInfo & selfInfo() const { return self_info; }
const PIMap<PIString, PIVector<PeerInfo *>> & _peerMap() const { return addresses_map; }
void reinit();
void lock() {peers_mutex.lock();}
void unlock() {peers_mutex.unlock();}
void lock() { peers_mutex.lock(); }
void unlock() { peers_mutex.unlock(); }
void changeName(const PIString & new_name);
const PIString & trustPeerName() const {return trust_peer;}
void setTrustPeerName(const PIString & peer_name) {trust_peer = peer_name;}
void setTcpServerIP(const PIString & ip) {server_ip = ip; tcpClientReconnect();}
const PIString & trustPeerName() const { return trust_peer; }
void setTrustPeerName(const PIString & peer_name) { trust_peer = peer_name; }
void setTcpServerIP(const PIString & ip) {
server_ip = ip;
tcpClientReconnect();
}
ssize_t bytesAvailable() const override;
EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data);
EVENT1(peerConnectedEvent, const PIString &, name);
EVENT1(peerDisconnectedEvent, const PIString &, name);
// bool lockedEth() const {return eth_mutex.isLocked();}
// bool lockedPeers() const {return peers_mutex.isLocked();}
// bool lockedMBcasts() const {return mc_mutex.isLocked();}
// bool lockedSends() const {return send_mutex.isLocked();}
// bool lockedMCSends() const {return send_mc_mutex.isLocked();}
// bool lockedEth() const {return eth_mutex.isLocked();}
// bool lockedPeers() const {return peers_mutex.isLocked();}
// bool lockedMBcasts() const {return mc_mutex.isLocked();}
// bool lockedSends() const {return send_mutex.isLocked();}
// bool lockedMCSends() const {return send_mc_mutex.isLocked();}
protected:
virtual void dataReceived(const PIString & from, const PIByteArray & data) {;}
virtual void peerConnected(const PIString & name) {;}
virtual void peerDisconnected(const PIString & name) {;}
virtual void dataReceived(const PIString & from, const PIByteArray & data) { ; }
virtual void peerConnected(const PIString & name) { ; }
virtual void peerDisconnected(const PIString & name) { ; }
EVENT_HANDLER2(bool, dataRead, const uchar *, readed, ssize_t, size);
EVENT_HANDLER2(bool, mbcastRead, const uchar *, readed, ssize_t, size);
private:
EVENT_HANDLER2(void, timerEvent, void * , data, int, delim);
EVENT_HANDLER2(void, timerEvent, void *, data, int, delim);
EVENT_HANDLER2(bool, sendInternal, const PIString &, to, const PIByteArray &, data);
EVENT_HANDLER2(void, dtReceived, const PIString &, from, const PIByteArray &, data);
EVENT_HANDLER1(void, newTcpClient, PIEthernet * , client);
EVENT_HANDLER1(void, newTcpClient, PIEthernet *, client);
EVENT_HANDLER(void, tcpClientReconnect);
bool hasPeer(const PIString & name) {piForeachC (PeerInfo & i, peers) if (i.name == name) return true; return false;}
bool hasPeer(const PIString & name) {
piForeachC(PeerInfo & i, peers)
if (i.name == name) return true;
return false;
}
bool removePeer(const PIString & name);
void removeNeighbour(const PIString & name);
void addPeer(const PeerInfo & pd);
void sendPeerInfo(const PeerInfo & info);
void sendPeerRemove(const PIString & peer);
void sendSelfInfo() {sendPeerInfo(self_info);}
void sendSelfRemove() {sendPeerRemove(self_info.name);}
void sendSelfInfo() { sendPeerInfo(self_info); }
void sendSelfRemove() { sendPeerRemove(self_info.name); }
void syncPeers();
void checkNetwork();
void initNetwork();
@@ -163,39 +202,41 @@ private:
void destroyMBcasts();
void sendMBcast(const PIByteArray & ba);
void pingNeighbours();
void addToRemoved(const PeerInfo & pi) {removed[pi.name] = PIPair<int, PISystemTime>(pi.cnt, pi.time);}
bool isRemoved(const PeerInfo & pi) const {return (removed.value(pi.name) == PIPair<int, PISystemTime>(pi.cnt, pi.time));}
void addToRemoved(const PeerInfo & pi) { removed[pi.name] = PIPair<int, PISystemTime>(pi.cnt, pi.time); }
bool isRemoved(const PeerInfo & pi) const { return (removed.value(pi.name) == PIPair<int, PISystemTime>(pi.cnt, pi.time)); }
bool openDevice() override;
bool closeDevice() override;
PIString constructFullPathDevice() const override;
void configureFromFullPathDevice(const PIString &full_path) override;
void configureFromFullPathDevice(const PIString & full_path) override;
PIPropertyStorage constructVariantDevice() const override;
void configureFromVariantDevice(const PIPropertyStorage & d) override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
PeerInfo * quickestPeer(const PIString & to);
bool sendToNeighbour(PeerInfo * peer, const PIByteArray & ba);
inline static bool isPeerRecent(const PeerInfo & my, const PeerInfo & income) {return (my.cnt < income.cnt) || (my.time < income.time);}
inline static bool isPeerRecent(const PeerInfo & my, const PeerInfo & income) {
return (my.cnt < income.cnt) || (my.time < income.time);
}
// 1 - new peer, 2 - remove peer, 3 - sync peers, 4 - data, 5 - ping request, 6 - ping reply
// Data packet: 4, from, to, ticks, data_size, data
protected:
bool inited__; //for internal use
bool inited__; // for internal use
private:
PIVector<PIEthernet * > eths_traffic, eths_mcast, eths_bcast;
PIVector<PIEthernet *> eths_traffic, eths_mcast, eths_bcast;
PIEthernet::InterfaceList prev_ifaces;
PIEthernet eth_send, eth_lo, eth_tcp_srv, eth_tcp_cli;
PITimer sync_timer;
PeerInfo self_info;
PIVector<PeerInfo> peers;
PIMap<PIString, PeerInfo * > peers_map;
PIMap<PIString, PIVector<PeerInfo * > > addresses_map; // map {"to" = list of nearest peers}
PIMap<PIString, PIPair<int, PISystemTime> > removed;
PIMap<PIString, PeerInfo *> peers_map;
PIMap<PIString, PIVector<PeerInfo *>> addresses_map; // map {"to" = list of nearest peers}
PIMap<PIString, PIPair<int, PISystemTime>> removed;
PIDiagnostics diag_s, diag_d;
bool destroyed, no_timer;
PIString trust_peer;
@@ -206,30 +247,50 @@ private:
PIMutex mc_mutex, eth_mutex, peers_mutex, send_mutex, send_mc_mutex;
};
inline PICout operator <<(PICout c, const PIPeer::PeerInfo::PeerAddress & v) {c.space(); c << "PeerAddress(" << v.address << ", " << v.netmask << ", " << v.ping << ")"; return c;}
inline PICout operator <<(PICout c, const PIPeer::PeerInfo & v) {c.space(); c << "PeerInfo(" << v.name << ", " << v.dist << ", " << v.addresses << ")"; return c;}
inline PICout operator<<(PICout c, const PIPeer::PeerInfo::PeerAddress & v) {
c.space();
c << "PeerAddress(" << v.address << ", " << v.netmask << ", " << v.ping << ")";
return c;
}
inline PICout operator<<(PICout c, const PIPeer::PeerInfo & v) {
c.space();
c << "PeerInfo(" << v.name << ", " << v.dist << ", " << v.addresses << ")";
return c;
}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIPeer::PeerInfo::PeerAddress) {s << v.address << v.netmask << v.ping; return s;}
BINARY_STREAM_WRITE(PIPeer::PeerInfo::PeerAddress) {
s << v.address << v.netmask << v.ping;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIPeer::PeerInfo::PeerAddress) {s >> v.address >> v.netmask >> v.ping; return s;}
BINARY_STREAM_READ(PIPeer::PeerInfo::PeerAddress) {
s >> v.address >> v.netmask >> v.ping;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIPeer::PeerInfo) {s << v.name << v.addresses << v.dist << v.neighbours << v.cnt << v.time; return s;}
BINARY_STREAM_WRITE(PIPeer::PeerInfo) {
s << v.name << v.addresses << v.dist << v.neighbours << v.cnt << v.time;
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIPeer::PeerInfo) {s >> v.name >> v.addresses >> v.dist >> v.neighbours >> v.cnt >> v.time; return s;}
BINARY_STREAM_READ(PIPeer::PeerInfo) {
s >> v.name >> v.addresses >> v.dist >> v.neighbours >> v.cnt >> v.time;
return s;
}
#endif // PIPEER_H
+340 -268
View File
@@ -1,133 +1,137 @@
/*
PIP - Platform Independent Primitives
COM
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
COM
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "piserial.h"
#include "piconfig.h"
#include "pidir.h"
#include "piincludes_p.h"
#include "pipropertystorage.h"
#include "piwaitevent_p.h"
#include <errno.h>
#if defined(MICRO_PIP)
# define PISERIAL_NO_PINS
#endif
#if defined(PISERIAL_NO_PINS) || defined(WINDOWS)
# define TIOCM_LE 1
# define TIOCM_DTR 4
# define TIOCM_RTS 7
# define TIOCM_CTS 8
# define TIOCM_ST 3
# define TIOCM_SR 2
# define TIOCM_CAR 1
# define TIOCM_RNG 9
# define TIOCM_DSR 6
# define TIOCM_LE 1
# define TIOCM_DTR 4
# define TIOCM_RTS 7
# define TIOCM_CTS 8
# define TIOCM_ST 3
# define TIOCM_SR 2
# define TIOCM_CAR 1
# define TIOCM_RNG 9
# define TIOCM_DSR 6
#endif
#ifdef WINDOWS
# ifndef INITGUID
# define INITGUID
# include <guiddef.h>
# undef INITGUID
# define INITGUID
# include <guiddef.h>
# undef INITGUID
# else
# include <guiddef.h>
# include <guiddef.h>
# endif
// clang-format off
# include <ntddmodm.h>
# include <winreg.h>
# include <windows.h>
# include <winioctl.h>
# include <cfgmgr32.h>
# include <setupapi.h>
# define B50 50
# define B75 75
# define B110 110
# define B300 300
# define B600 600
# define B1200 1200
# define B2400 2400
# define B4800 4800
# define B9600 9600
# define B14400 14400
# define B19200 19200
# define B38400 38400
# define B57600 57600
# define B115200 115200
# define B230400 230400
# define B460800 460800
# define B500000 500000
# define B576000 576000
# define B921600 921600
# define B1000000 1000000
# define B1152000 1152000
# define B1500000 1500000
# define B2000000 2000000
# define B2500000 2500000
# define B3000000 3000000
# define B3500000 3500000
# define B4000000 4000000
// clang-format on
# define B50 50
# define B75 75
# define B110 110
# define B300 300
# define B600 600
# define B1200 1200
# define B2400 2400
# define B4800 4800
# define B9600 9600
# define B14400 14400
# define B19200 19200
# define B38400 38400
# define B57600 57600
# define B115200 115200
# define B230400 230400
# define B460800 460800
# define B500000 500000
# define B576000 576000
# define B921600 921600
# define B1000000 1000000
# define B1152000 1152000
# define B1500000 1500000
# define B2000000 2000000
# define B2500000 2500000
# define B3000000 3000000
# define B3500000 3500000
# define B4000000 4000000
#else
# include <termios.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <termios.h>
# ifndef B50
# define B50 0000001
# define B50 0000001
# endif
# ifndef B75
# define B75 0000002
# define B75 0000002
# endif
# ifndef B230400
# define B230400 0010003
# define B230400 0010003
# endif
# ifndef B460800
# define B460800 0010004
# define B460800 0010004
# endif
# ifndef B500000
# define B500000 0010005
# define B500000 0010005
# endif
# ifndef B576000
# define B576000 0010006
# define B576000 0010006
# endif
# ifndef B921600
# define B921600 0010007
# define B921600 0010007
# endif
# ifndef B1000000
# define B1000000 0010010
# define B1000000 0010010
# endif
# ifndef B1152000
# define B1152000 0010011
# define B1152000 0010011
# endif
# ifndef B1500000
# define B1500000 0010012
# define B1500000 0010012
# endif
# ifndef B2000000
# define B2000000 0010013
# define B2000000 0010013
# endif
# ifndef B2500000
# define B2500000 0010014
# define B2500000 0010014
# endif
# ifndef B3000000
# define B3000000 0010015
# define B3000000 0010015
# endif
# ifndef B3500000
# define B3500000 0010016
# define B3500000 0010016
# endif
# ifndef B4000000
# define B4000000 0010017
# define B4000000 0010017
# endif
#endif
#ifndef CRTSCTS
@@ -174,7 +178,7 @@ PRIVATE_DEFINITION_START(PISerial)
#ifdef WINDOWS
PIWaitEvent event_write;
DCB desc, sdesc;
HANDLE hCom = nullptr;
HANDLE hCom = nullptr;
DWORD readed = 0, mask = 0;
OVERLAPPED overlap, overlap_write;
#else
@@ -184,22 +188,19 @@ PRIVATE_DEFINITION_START(PISerial)
PRIVATE_DEFINITION_END(PISerial)
PIString PISerial::DeviceInfo::id() const {
return PIString::fromNumber(vID, 16).toLowerCase().expandLeftTo(4, '0') + ":" +
PIString::fromNumber(pID, 16).toLowerCase().expandLeftTo(4, '0');
PIString::fromNumber(pID, 16).toLowerCase().expandLeftTo(4, '0');
}
PISerial::PISerial(): PIIODevice("", ReadWrite) {
construct();
}
PISerial::PISerial(const PIString & device_, PISerial::Speed speed_, PIFlags<PISerial::Parameters> params_): PIIODevice(device_, ReadWrite) {
PISerial::PISerial(const PIString & device_, PISerial::Speed speed_, PIFlags<PISerial::Parameters> params_)
: PIIODevice(device_, ReadWrite) {
construct();
setPath(device_);
setSpeed(speed_);
@@ -219,7 +220,7 @@ PISerial::~PISerial() {
void PISerial::construct() {
sending = false;
//setPriority(piHigh);
// setPriority(piHigh);
setParameters(0);
setSpeed(S115200);
setDataBitsCount(8);
@@ -245,16 +246,12 @@ bool PISerial::setPin(int number, bool on) {
case 2: return setSR(on); break;
case 3: return setST(on); break;
case 4: return setDTR(on); break;
case 5:
piCoutObj << "Pin number 5 is ground";
return false;
case 5: piCoutObj << "Pin number 5 is ground"; return false;
case 6: return setDSR(on); break;
case 7: return setRTS(on); break;
case 8: return setCTS(on); break;
case 9: return setRNG(on); break;
default:
piCoutObj << "Pin number " << number << " doesn`t exists!";
return false;
default: piCoutObj << "Pin number " << number << " doesn`t exists!"; return false;
}
return false;
}
@@ -271,32 +268,66 @@ bool PISerial::isPin(int number) const {
case 7: return isRTS(); break;
case 8: return isCTS(); break;
case 9: return isRNG(); break;
default:
piCoutObj << "Pin number " << number << " doesn`t exists!";
return false;
default: piCoutObj << "Pin number " << number << " doesn`t exists!"; return false;
}
return false;
}
bool PISerial::setLE(bool on) {return setBit(TIOCM_LE, on, "LE");}
bool PISerial::setDTR(bool on) {return setBit(TIOCM_DTR, on, "DTR");}
bool PISerial::setRTS(bool on) {return setBit(TIOCM_RTS, on, "RTS");}
bool PISerial::setCTS(bool on) {return setBit(TIOCM_CTS, on, "CTS");}
bool PISerial::setST(bool on) {return setBit(TIOCM_ST, on, "ST");}
bool PISerial::setSR(bool on) {return setBit(TIOCM_SR, on, "SR");}
bool PISerial::setCAR(bool on) {return setBit(TIOCM_CAR, on, "CAR");}
bool PISerial::setRNG(bool on) {return setBit(TIOCM_RNG, on, "RNG");}
bool PISerial::setDSR(bool on) {return setBit(TIOCM_DSR, on, "DSR");}
bool PISerial::setLE(bool on) {
return setBit(TIOCM_LE, on, "LE");
}
bool PISerial::setDTR(bool on) {
return setBit(TIOCM_DTR, on, "DTR");
}
bool PISerial::setRTS(bool on) {
return setBit(TIOCM_RTS, on, "RTS");
}
bool PISerial::setCTS(bool on) {
return setBit(TIOCM_CTS, on, "CTS");
}
bool PISerial::setST(bool on) {
return setBit(TIOCM_ST, on, "ST");
}
bool PISerial::setSR(bool on) {
return setBit(TIOCM_SR, on, "SR");
}
bool PISerial::setCAR(bool on) {
return setBit(TIOCM_CAR, on, "CAR");
}
bool PISerial::setRNG(bool on) {
return setBit(TIOCM_RNG, on, "RNG");
}
bool PISerial::setDSR(bool on) {
return setBit(TIOCM_DSR, on, "DSR");
}
bool PISerial::isLE() const {return isBit(TIOCM_LE, "LE");}
bool PISerial::isDTR() const {return isBit(TIOCM_DTR, "DTR");}
bool PISerial::isRTS() const {return isBit(TIOCM_RTS, "RTS");}
bool PISerial::isCTS() const {return isBit(TIOCM_CTS, "CTS");}
bool PISerial::isST() const {return isBit(TIOCM_ST, "ST");}
bool PISerial::isSR() const {return isBit(TIOCM_SR, "SR");}
bool PISerial::isCAR() const {return isBit(TIOCM_CAR, "CAR");}
bool PISerial::isRNG() const {return isBit(TIOCM_RNG, "RNG");}
bool PISerial::isDSR() const {return isBit(TIOCM_DSR, "DSR");}
bool PISerial::isLE() const {
return isBit(TIOCM_LE, "LE");
}
bool PISerial::isDTR() const {
return isBit(TIOCM_DTR, "DTR");
}
bool PISerial::isRTS() const {
return isBit(TIOCM_RTS, "RTS");
}
bool PISerial::isCTS() const {
return isBit(TIOCM_CTS, "CTS");
}
bool PISerial::isST() const {
return isBit(TIOCM_ST, "ST");
}
bool PISerial::isSR() const {
return isBit(TIOCM_SR, "SR");
}
bool PISerial::isCAR() const {
return isBit(TIOCM_CAR, "CAR");
}
bool PISerial::isRNG() const {
return isBit(TIOCM_RNG, "RNG");
}
bool PISerial::isDSR() const {
return isBit(TIOCM_DSR, "DSR");
}
//! \~\details
@@ -349,9 +380,9 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) {
}
#ifndef PISERIAL_NO_PINS
# ifdef WINDOWS
static int bit_map_on [] = {0, 0, 0, 0, SETDTR, 0, 0, SETRTS, 0, 0, 0};
static int bit_map_on[] = {0, 0, 0, 0, SETDTR, 0, 0, SETRTS, 0, 0, 0};
static int bit_map_off[] = {0, 0, 0, 0, CLRDTR, 0, 0, CLRRTS, 0, 0, 0};
int action = (on ? bit_map_on : bit_map_off)[bit];
int action = (on ? bit_map_on : bit_map_off)[bit];
if (action > 0) {
if (EscapeCommFunction(PRIVATE->hCom, action) == 0) {
piCoutObj << "setBit" << bname << " error: " << errorString();
@@ -381,8 +412,7 @@ bool PISerial::isBit(int bit, const PIString & bname) const {
# ifdef WINDOWS
# else
int ret = 0;
if (ioctl(fd, TIOCMGET, &ret) < 0)
piCoutObj << "isBit" << bname << " error: " << errorString();
if (ioctl(fd, TIOCMGET, &ret) < 0) piCoutObj << "isBit" << bname << " error: " << errorString();
return ret & bit;
# endif
#endif
@@ -464,21 +494,23 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
int ret, all = 0;
if (timeout_ms > 0.) {
bool br = setOption(BlockingRead, false);
all = readDevice(data, 1);
all = readDevice(data, 1);
tm_.reset();
while (all < size && tm_.elapsed_m() < timeout_ms) {
ret = readDevice(&((uchar * )data)[all], size - all);
if (ret > 0) all += ret;
else piMinSleep();
ret = readDevice(&((uchar *)data)[all], size - all);
if (ret > 0)
all += ret;
else
piMinSleep();
}
setOption(BlockingRead, br);
received(data, all);
return (all == size);
} else {
bool br = setOption(BlockingRead, true);
all = readDevice(data, 1);
all = readDevice(data, 1);
while (all < size) {
ret = readDevice(&((uchar * )data)[all], size - all);
ret = readDevice(&((uchar *)data)[all], size - all);
if (ret > 0) all += ret;
}
setOption(BlockingRead, br);
@@ -518,15 +550,18 @@ PIString PISerial::readString(int size, double timeout_ms) {
if (size <= 0) {
while (tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, 1024);
if (ret <= 0) piMinSleep();
else str += PIString((char*)td, ret);
if (ret <= 0)
piMinSleep();
else
str += PIString((char *)td, ret);
}
} else {
while (all < size && tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, size - all);
if (ret <= 0) piMinSleep();
if (ret <= 0)
piMinSleep();
else {
str += PIString((char*)td, ret);
str += PIString((char *)td, ret);
all += ret;
}
}
@@ -534,13 +569,14 @@ PIString PISerial::readString(int size, double timeout_ms) {
setOption(BlockingRead, br);
} else {
bool br = setOption(BlockingRead, true);
all = readDevice(td, 1);
str += PIString((char*)td, all);
all = readDevice(td, 1);
str += PIString((char *)td, all);
while (all < size) {
ret = readDevice(td, size - all);
if (ret <= 0) piMinSleep();
if (ret <= 0)
piMinSleep();
else {
str += PIString((char*)td, ret);
str += PIString((char *)td, ret);
all += ret;
}
}
@@ -580,13 +616,16 @@ PIByteArray PISerial::readData(int size, double timeout_ms) {
if (size <= 0) {
while (tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, 1024);
if (ret <= 0) piMinSleep();
else str.append(td, ret);
if (ret <= 0)
piMinSleep();
else
str.append(td, ret);
}
} else {
while (all < size && tm_.elapsed_m() < timeout_ms) {
ret = readDevice(td, size - all);
if (ret <= 0) piMinSleep();
if (ret <= 0)
piMinSleep();
else {
str.append(td, ret);
all += ret;
@@ -596,11 +635,12 @@ PIByteArray PISerial::readData(int size, double timeout_ms) {
setOption(BlockingRead, br);
} else {
bool br = setOption(BlockingRead, true);
all = readDevice(td, 1);
all = readDevice(td, 1);
str.append(td, all);
while (all < size) {
ret = readDevice(td, size - all);
if (ret <= 0) piMinSleep();
if (ret <= 0)
piMinSleep();
else {
str.append(td, ret);
all += ret;
@@ -617,17 +657,18 @@ bool PISerial::send(const void * data, int size) {
int ret = 0;
int wsz = 0;
do {
ret = write(&(((uchar*)data)[wsz]), size - wsz);
ret = write(&(((uchar *)data)[wsz]), size - wsz);
if (ret > 0) wsz += ret;
//piCout << ret << wsz;
else return false;
// piCout << ret << wsz;
else
return false;
} while (wsz < size);
return (wsz == size);
}
void PISerial::interrupt() {
//piCoutObj << "interrupt";
// piCoutObj << "interrupt";
PRIVATE->event.interrupt();
#ifdef WINDOWS
PRIVATE->event_write.interrupt();
@@ -636,13 +677,13 @@ void PISerial::interrupt() {
bool PISerial::openDevice() {
PIString p = path();
//piCout << "ser open" << p;
PIString p = path();
// piCout << "ser open" << p;
PIString pl = p.toLowerCase().removeAll(' ');
if (!pl.startsWith("/") && !pl.startsWith("com")) {
p.clear();
PIVector<DeviceInfo> devs = availableDevicesInfo();
piForeachC (DeviceInfo & d, devs) {
piForeachC(DeviceInfo & d, devs) {
if (d.id() == pl) {
p = d.path;
break;
@@ -655,9 +696,15 @@ bool PISerial::openDevice() {
if (p.isEmpty()) return false;
#ifdef WINDOWS
DWORD ds = 0, sm = 0;
if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;}
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
PIString wp = "//./" + p;
if (isReadable()) {
ds |= GENERIC_READ;
sm |= FILE_SHARE_READ;
}
if (isWriteable()) {
ds |= GENERIC_WRITE;
sm |= FILE_SHARE_WRITE;
}
PIString wp = "//./" + p;
PRIVATE->hCom = CreateFileA(wp.dataAscii(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
if (PRIVATE->hCom == INVALID_HANDLE_VALUE) {
piCoutObj << "Unable to open \"" << p << "\"";
@@ -679,7 +726,7 @@ bool PISerial::openDevice() {
}
tcgetattr(fd, &PRIVATE->desc);
PRIVATE->sdesc = PRIVATE->desc;
//piCoutObj << "Initialized " << p;
// piCoutObj << "Initialized " << p;
#endif
applySettings();
PRIVATE->event.create();
@@ -699,7 +746,7 @@ bool PISerial::closeDevice() {
#ifdef WINDOWS
SetCommState(PRIVATE->hCom, &PRIVATE->sdesc);
SetCommMask(PRIVATE->hCom, PRIVATE->mask);
// piCoutObj << "close" <<
// piCoutObj << "close" <<
CloseHandle(PRIVATE->hCom);
PRIVATE->hCom = 0;
#else
@@ -723,10 +770,11 @@ void PISerial::applySettings() {
GetCommMask(PRIVATE->hCom, &PRIVATE->mask);
SetCommMask(PRIVATE->hCom, EV_RXCHAR);
GetCommState(PRIVATE->hCom, &PRIVATE->sdesc);
// piCoutObj << PRIVATE->sdesc.fBinary << PRIVATE->sdesc.fAbortOnError << PRIVATE->sdesc.fDsrSensitivity << PRIVATE->sdesc.fDtrControl << PRIVATE->sdesc.fDummy2 << PRIVATE->sdesc.fErrorChar;
PRIVATE->desc = PRIVATE->sdesc;
// piCoutObj << PRIVATE->sdesc.fBinary << PRIVATE->sdesc.fAbortOnError << PRIVATE->sdesc.fDsrSensitivity << PRIVATE->sdesc.fDtrControl
//<< PRIVATE->sdesc.fDummy2 << PRIVATE->sdesc.fErrorChar;
PRIVATE->desc = PRIVATE->sdesc;
PRIVATE->desc.DCBlength = sizeof(PRIVATE->desc);
PRIVATE->desc.BaudRate = convertSpeed(outSpeed());
PRIVATE->desc.BaudRate = convertSpeed(outSpeed());
if (dataBitsCount() >= 5 && dataBitsCount() <= 8)
PRIVATE->desc.ByteSize = dataBitsCount();
else
@@ -734,7 +782,7 @@ void PISerial::applySettings() {
PIFlags<Parameters> params = parameters();
if (params[PISerial::ParityControl]) {
PRIVATE->desc.fParity = 1;
PRIVATE->desc.Parity = params[PISerial::ParityOdd] ? 1 : 2;
PRIVATE->desc.Parity = params[PISerial::ParityOdd] ? 1 : 2;
}
PRIVATE->desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
if (SetCommState(PRIVATE->hCom, &PRIVATE->desc) == -1) {
@@ -745,13 +793,14 @@ void PISerial::applySettings() {
if (fd == -1) return;
tcgetattr(fd, &PRIVATE->desc);
PRIVATE->desc.c_oflag = PRIVATE->desc.c_lflag = PRIVATE->desc.c_cflag = 0;
PRIVATE->desc.c_iflag = IGNBRK;
PRIVATE->desc.c_cflag = CLOCAL | HUPCL;
PRIVATE->desc.c_iflag = IGNBRK;
PRIVATE->desc.c_cflag = CLOCAL | HUPCL;
switch (dataBitsCount()) {
case 5: PRIVATE->desc.c_cflag |= (CSIZE & CS5); break;
case 6: PRIVATE->desc.c_cflag |= (CSIZE & CS6); break;
case 7: PRIVATE->desc.c_cflag |= (CSIZE & CS7); break;
case 8: default: PRIVATE->desc.c_cflag |= (CSIZE & CS8); break;
case 8:
default: PRIVATE->desc.c_cflag |= (CSIZE & CS8); break;
};
if (isReadable()) PRIVATE->desc.c_cflag |= CREAD;
PIFlags<Parameters> params = parameters();
@@ -761,7 +810,7 @@ void PISerial::applySettings() {
PRIVATE->desc.c_cflag |= PARENB;
if (params[PISerial::ParityOdd]) PRIVATE->desc.c_cflag |= PARODD;
}
PRIVATE->desc.c_cc[VMIN] = 1;
PRIVATE->desc.c_cc[VMIN] = 1;
PRIVATE->desc.c_cc[VTIME] = vtime;
cfsetispeed(&PRIVATE->desc, convertSpeed(inSpeed()));
@@ -781,13 +830,12 @@ void PISerial::applySettings() {
void PISerial::setTimeouts() {
#ifdef WINDOWS
COMMTIMEOUTS times;
times.ReadIntervalTimeout = isOptionSet(BlockingRead) ? vtime : MAXDWORD;
times.ReadTotalTimeoutConstant = isOptionSet(BlockingRead) ? 0 : 1;
times.ReadTotalTimeoutMultiplier = isOptionSet(BlockingRead) ? 0 : MAXDWORD;
times.WriteTotalTimeoutConstant = isOptionSet(BlockingWrite) ? 0 : 1;
times.ReadIntervalTimeout = isOptionSet(BlockingRead) ? vtime : MAXDWORD;
times.ReadTotalTimeoutConstant = isOptionSet(BlockingRead) ? 0 : 1;
times.ReadTotalTimeoutMultiplier = isOptionSet(BlockingRead) ? 0 : MAXDWORD;
times.WriteTotalTimeoutConstant = isOptionSet(BlockingWrite) ? 0 : 1;
times.WriteTotalTimeoutMultiplier = 0;
if (SetCommTimeouts(PRIVATE->hCom, &times) == -1)
piCoutObj << "Unable to set timeouts for \"" << path() << "\"";
if (SetCommTimeouts(PRIVATE->hCom, &times) == -1) piCoutObj << "Unable to set timeouts for \"" << path() << "\"";
#else
fcntl(fd, F_SETFL, isOptionSet(BlockingRead) ? 0 : O_NONBLOCK);
#endif
@@ -810,54 +858,53 @@ void PISerial::setTimeouts() {
//! \~\sa \a readData(), \a readString()
ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
#ifdef WINDOWS
if (!canRead()) return -1;
if (sending) return -1;
//piCoutObj << "read ..." << PRIVATE->hCom;
memset(&(PRIVATE->overlap), 0, sizeof(PRIVATE->overlap));
PRIVATE->overlap.hEvent = PRIVATE->event.getEvent();
ReadFile(PRIVATE->hCom, read_to, max_size, NULL, &(PRIVATE->overlap));
PRIVATE->readed = 0;
if (PRIVATE->event.wait()) {
GetOverlappedResult(PRIVATE->hCom, &(PRIVATE->overlap), &(PRIVATE->readed), FALSE);
} else
return -1;
//piCoutObj << "read done" << PRIVATE->readed;
DWORD err = GetLastError();
if (err == ERROR_TIMEOUT && PRIVATE->readed == 0)
return 0;
if (err == ERROR_BAD_COMMAND || err == ERROR_ACCESS_DENIED) {
piCoutObj << "read error" << (PRIVATE->readed) << errorString();
stop();
if (!canRead()) return -1;
if (sending) return -1;
// piCoutObj << "read ..." << PRIVATE->hCom;
memset(&(PRIVATE->overlap), 0, sizeof(PRIVATE->overlap));
PRIVATE->overlap.hEvent = PRIVATE->event.getEvent();
ReadFile(PRIVATE->hCom, read_to, max_size, NULL, &(PRIVATE->overlap));
PRIVATE->readed = 0;
if (PRIVATE->event.wait()) {
GetOverlappedResult(PRIVATE->hCom, &(PRIVATE->overlap), &(PRIVATE->readed), FALSE);
} else
return -1;
// piCoutObj << "read done" << PRIVATE->readed;
DWORD err = GetLastError();
if (err == ERROR_TIMEOUT && PRIVATE->readed == 0) return 0;
if (err == ERROR_BAD_COMMAND || err == ERROR_ACCESS_DENIED) {
piCoutObj << "read error" << (PRIVATE->readed) << errorString();
stop();
close();
return 0;
}
// piCoutObj << "read" << (PRIVATE->readed) << errorString();
return PRIVATE->readed;
#else
if (!canRead()) return -1;
if (!PRIVATE->event.wait(fd)) return -1;
ssize_t ret = ::read(fd, read_to, max_size);
if (ret < 0) {
int err = errno;
if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) {
stopThreadedRead();
close();
return 0;
}
//piCoutObj << "read" << (PRIVATE->readed) << errorString();
return PRIVATE->readed;
#else
if (!canRead()) return -1;
if (!PRIVATE->event.wait(fd)) return -1;
ssize_t ret = ::read(fd, read_to, max_size);
if (ret < 0) {
int err = errno;
if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) {
stopThreadedRead();
close();
return 0;
}
}
return ret;
}
return ret;
#endif
}
ssize_t PISerial::writeDevice(const void * data, ssize_t max_size) {
if (fd == -1 || !canWrite()) {
//piCoutObj << "Can`t write to uninitialized COM";
// piCoutObj << "Can`t write to uninitialized COM";
return -1;
}
#ifdef WINDOWS
DWORD wrote(0);
//piCoutObj << "send ..." << max_size;// << ": " << PIString((char*)data, max_size);
// piCoutObj << "send ..." << max_size;// << ": " << PIString((char*)data, max_size);
sending = true;
memset(&(PRIVATE->overlap_write), 0, sizeof(PRIVATE->overlap_write));
PRIVATE->overlap_write.hEvent = PRIVATE->event_write.getEvent();
@@ -866,20 +913,20 @@ ssize_t PISerial::writeDevice(const void * data, ssize_t max_size) {
GetOverlappedResult(PRIVATE->hCom, &(PRIVATE->overlap_write), &wrote, FALSE);
}
sending = false;
//piCoutObj << "send ok" << wrote;// << " bytes in " << path();
// piCoutObj << "send ok" << wrote;// << " bytes in " << path();
#else
ssize_t wrote;
wrote = ::write(fd, data, max_size);
if (isOptionSet(BlockingWrite)) tcdrain(fd);
#endif
return (ssize_t)wrote;
//piCoutObj << "Error while sending";
// piCoutObj << "Error while sending";
}
bool PISerial::configureDevice(const void * e_main, const void * e_parent) {
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
PIConfig::Entry * em = (PIConfig::Entry *)e_main;
PIConfig::Entry * ep = (PIConfig::Entry *)e_parent;
setDevice(readDeviceSetting<PIString>("device", device(), em, ep));
setSpeed((PISerial::Speed)(readDeviceSetting<int>("speed", (int)outSpeed(), em, ep)));
setDataBitsCount(readDeviceSetting<int>("dataBitsCount", dataBitsCount(), em, ep));
@@ -894,11 +941,16 @@ PIString PISerial::constructFullPathDevice() const {
PIString ret;
ret += path() + ":" + PIString::fromNumber(int(inSpeed())) + ":" + PIString::fromNumber(dataBitsCount());
if (parameters()[ParityControl]) {
if (parameters()[ParityOdd]) ret += ":O";
else ret += ":E";
} else ret += ":N";
if (parameters()[TwoStopBits]) ret += ":2";
else ret += ":1";
if (parameters()[ParityOdd])
ret += ":O";
else
ret += ":E";
} else
ret += ":N";
if (parameters()[TwoStopBits])
ret += ":2";
else
ret += ":1";
return ret;
}
@@ -916,14 +968,19 @@ void PISerial::configureFromFullPathDevice(const PIString & full_path) {
PIString p(pl[i]);
switch (i) {
case 0: setProperty("path", p); break;
case 1: setProperty("outSpeed", p.toInt()); setProperty("inSpeed", p.toInt()); break;
case 1:
setProperty("outSpeed", p.toInt());
setProperty("inSpeed", p.toInt());
break;
case 2: setProperty("dataBitsCount", p.toInt()); break;
case 3:
p = p.left(1).toLowerCase();
if (p != "n") setParameter(ParityControl);
if (p == "o") setParameter(ParityOdd);
break;
case 4: if (p.toInt() == 2) setParameter(TwoStopBits); break;
case 4:
if (p.toInt() == 2) setParameter(TwoStopBits);
break;
}
}
applySettings();
@@ -936,17 +993,23 @@ PIPropertyStorage PISerial::constructVariantDevice() const {
PIVariantTypes::Enum e;
PIVector<int> as = availableSpeeds();
piForeachC (int s, as) {e << PIVariantTypes::Enumerator(s, PIString::fromNumber(s));}
piForeachC(int s, as) {
e << PIVariantTypes::Enumerator(s, PIString::fromNumber(s));
}
e.selectValue((int)inSpeed());
ret.addProperty("speed", e);
e = PIVariantTypes::Enum();
for (int i = 5; i <= 8; ++i) {e << PIVariantTypes::Enumerator(i, PIString::fromNumber(i));}
for (int i = 5; i <= 8; ++i) {
e << PIVariantTypes::Enumerator(i, PIString::fromNumber(i));
}
e.selectValue(dataBitsCount());
ret.addProperty("dataBits", e);
e = PIVariantTypes::Enum();
e << "None" << "Odd" << "Even";
e << "None"
<< "Odd"
<< "Even";
if (parameters()[ParityControl]) {
if (parameters()[ParityOdd])
e.selectValue(1);
@@ -957,7 +1020,9 @@ PIPropertyStorage PISerial::constructVariantDevice() const {
ret.addProperty("parity", e);
e = PIVariantTypes::Enum();
for (int i = 1; i <= 2; ++i) {e << PIVariantTypes::Enumerator(i, PIString::fromNumber(i));}
for (int i = 1; i <= 2; ++i) {
e << PIVariantTypes::Enumerator(i, PIString::fromNumber(i));
}
e.selectValue(parameters()[TwoStopBits] ? 2 : 1);
ret.addProperty("stopBits", e);
return ret;
@@ -970,21 +1035,19 @@ void PISerial::configureFromVariantDevice(const PIPropertyStorage & d) {
setDataBitsCount(d.propertyValueByName("dataBits").toEnum().selectedValue());
PIVariantTypes::Enum e = d.propertyValueByName("parity").toEnum();
setParameter(ParityControl, e.selectedValue() > 0);
setParameter(ParityOdd , e.selectedValue() == 1);
setParameter(TwoStopBits , d.propertyValueByName("stopBits").toEnum().selectedValue() == 2);
setParameter(ParityOdd, e.selectedValue() == 1);
setParameter(TwoStopBits, d.propertyValueByName("stopBits").toEnum().selectedValue() == 2);
}
PIVector<int> PISerial::availableSpeeds() {
PIVector<int> spds;
spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 <<
9600 <<
spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 << 9600 <<
#ifdef WINDOWS
14400 <<
14400 <<
#endif
19200 << 38400 << 57600 << 115200 << 230400 <<
460800 << 500000 << 576000 << 921600 << 1000000 << 1152000 <<
1500000 << 2000000 << 2500000 << 3000000 << 3500000 << 4000000;
19200 << 38400 << 57600 << 115200 << 230400 << 460800 << 500000 << 576000 << 921600 << 1000000 << 1152000 << 1500000 << 2000000
<< 2500000 << 3000000 << 3500000 << 4000000;
return spds;
}
@@ -992,7 +1055,7 @@ PIVector<int> PISerial::availableSpeeds() {
PIStringList PISerial::availableDevices(bool test) {
PIVector<DeviceInfo> devs = availableDevicesInfo(test);
PIStringList ret;
piForeachC (DeviceInfo & d, devs)
piForeachC(DeviceInfo & d, devs)
ret << d.path;
return ret;
}
@@ -1002,15 +1065,11 @@ PIStringList PISerial::availableDevices(bool test) {
PIString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData) {
PIString ret;
const HKEY key = SetupDiOpenDevRegKey(deviceInfoSet, deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
if (key == INVALID_HANDLE_VALUE)
return ret;
static const wchar_t * const keyTokens[] = {
L"PortName\0",
L"PortNumber\0"
};
static const int keys_count = sizeof(keyTokens) / sizeof(keyTokens[0]);
if (key == INVALID_HANDLE_VALUE) return ret;
static const wchar_t * const keyTokens[] = {L"PortName\0", L"PortNumber\0"};
static const int keys_count = sizeof(keyTokens) / sizeof(keyTokens[0]);
for (int i = 0; i < keys_count; ++i) {
DWORD dataType = 0;
DWORD dataType = 0;
DWORD bytesRequired = MAX_PATH;
PIVector<wchar_t> outputBuffer(MAX_PATH + 1);
for (;;) {
@@ -1026,8 +1085,7 @@ PIString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData)
}
break;
}
if (!ret.isEmpty())
break;
if (!ret.isEmpty()) break;
}
RegCloseKey(key);
return ret;
@@ -1035,14 +1093,19 @@ PIString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData)
PIString deviceRegistryProperty(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData, DWORD property) {
DWORD dataType = 0;
DWORD dataType = 0;
DWORD bytesRequired = MAX_PATH;
PIVector<wchar_t> outputBuffer(MAX_PATH + 1);
for (;;) {
if (SetupDiGetDeviceRegistryPropertyW(deviceInfoSet, deviceInfoData, property, &dataType, (PBYTE)outputBuffer.data(), bytesRequired, &bytesRequired))
if (SetupDiGetDeviceRegistryPropertyW(deviceInfoSet,
deviceInfoData,
property,
&dataType,
(PBYTE)outputBuffer.data(),
bytesRequired,
&bytesRequired))
break;
if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dataType != REG_SZ && dataType != REG_EXPAND_SZ))
return PIString();
if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dataType != REG_SZ && dataType != REG_EXPAND_SZ)) return PIString();
outputBuffer.resize(bytesRequired / sizeof(wchar_t) + 2, 0);
}
return PIString(outputBuffer.data());
@@ -1073,20 +1136,20 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
PIVector<DeviceInfo> ret;
DeviceInfo di;
#ifdef WINDOWS
static const GUID guids[] = {GUID_DEVINTERFACE_MODEM, GUID_DEVINTERFACE_COMPORT};
static const GUID guids[] = {GUID_DEVINTERFACE_MODEM, GUID_DEVINTERFACE_COMPORT};
static const int guids_cnt = sizeof(guids) / sizeof(GUID);
for (int i = 0; i < guids_cnt; ++i) {
const HDEVINFO dis = SetupDiGetClassDevs(&(guids[i]), NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (dis == INVALID_HANDLE_VALUE) continue;
SP_DEVINFO_DATA did;
memset(&did, 0, sizeof(did));
did.cbSize = sizeof(did);
did.cbSize = sizeof(did);
DWORD index = 0;
while (SetupDiEnumDeviceInfo(dis, index++, &did)) {
di = DeviceInfo();
di = DeviceInfo();
di.path = devicePortName(dis, &did);
if (!di.path.startsWith("COM")) continue;
di.description = deviceRegistryProperty(dis, &did, SPDRP_DEVICEDESC);
di.description = deviceRegistryProperty(dis, &did, SPDRP_DEVICEDESC);
di.manufacturer = deviceRegistryProperty(dis, &did, SPDRP_MFG);
PIString id_str = deviceInstanceIdentifier(did.DevInst);
if (!parseID(id_str, di)) {
@@ -1097,25 +1160,34 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
}
}
ret << di;
//piCout << "dev" << did.DevInst << di;
// piCout << "dev" << did.DevInst << di;
}
SetupDiDestroyDeviceInfoList(dis);
}
#else
# ifndef ANDROID
PIStringList prefixes;
# ifdef QNX
# ifdef QNX
prefixes << "ser";
# else
prefixes << "ttyS" << "ttyO" << "ttyUSB" << "ttyACM" << "ttyGS"
<< "ttyMI" << "ttymxc" << "ttyAMA" << "rfcomm" << "ircomm";
# ifdef FREE_BSD
# else
prefixes << "ttyS"
<< "ttyO"
<< "ttyUSB"
<< "ttyACM"
<< "ttyGS"
<< "ttyMI"
<< "ttymxc"
<< "ttyAMA"
<< "rfcomm"
<< "ircomm";
# ifdef FREE_BSD
prefixes << "cu";
# endif
# ifdef MAC_OS
# endif
# ifdef MAC_OS
prefixes.clear();
prefixes << "cu." << "tty.";
# endif
prefixes << "cu."
<< "tty.";
# endif
PIFile file_prefixes("/proc/tty/drivers", PIIODevice::ReadOnly);
if (file_prefixes.open()) {
PIString fc = file_prefixes.readAll(true), line, cpref;
@@ -1129,45 +1201,40 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
words << line.takeWord();
if (words.size_s() < 2) break;
if (words.back() != "serial") continue;
cpref = words[1];
cpref = words[1];
int li = cpref.findLast("/");
if (li > 0) cpref.cutLeft(li + 1);
prefixes << cpref;
}
prefixes.removeDuplicates();
}
# endif
# endif
PIDir dir("/dev");
PIVector<PIFile::FileInfo> de = dir.entries();
# ifdef LINUX
# ifdef LINUX
char linkbuf[1024];
# endif
piForeachC (PIFile::FileInfo & e, de) { // TODO changes in FileInfo
piForeachC (PIString & p, prefixes) {
# endif
piForeachC(PIFile::FileInfo & e, de) { // TODO changes in FileInfo
piForeachC(PIString & p, prefixes) {
if (e.name().startsWith(p)) {
di = DeviceInfo();
di.path = e.path;
# ifdef LINUX
di = DeviceInfo();
di.path = e.path;
# ifdef LINUX
ssize_t lsz = readlink(("/sys/class/tty/" + e.name()).dataAscii(), linkbuf, 1024);
if (lsz > 0) {
PIString fpath = "/sys/class/tty/" + PIString(linkbuf, lsz) + "/";
PIFile _f;
for (int i = 0; i < 5; ++i) {
fpath += "../";
//piCout << "try" << fpath;
if (_f.open(fpath + "idVendor", PIIODevice::ReadOnly))
di.vID = PIString(_f.readAll()).trim().toInt(16);
if (_f.open(fpath + "idProduct", PIIODevice::ReadOnly))
di.pID = PIString(_f.readAll()).trim().toInt(16);
if (_f.open(fpath + "product", PIIODevice::ReadOnly))
di.description = PIString(_f.readAll()).trim();
if (_f.open(fpath + "manufacturer", PIIODevice::ReadOnly))
di.manufacturer = PIString(_f.readAll()).trim();
if (di.pID > 0)
break;
// piCout << "try" << fpath;
if (_f.open(fpath + "idVendor", PIIODevice::ReadOnly)) di.vID = PIString(_f.readAll()).trim().toInt(16);
if (_f.open(fpath + "idProduct", PIIODevice::ReadOnly)) di.pID = PIString(_f.readAll()).trim().toInt(16);
if (_f.open(fpath + "product", PIIODevice::ReadOnly)) di.description = PIString(_f.readAll()).trim();
if (_f.open(fpath + "manufacturer", PIIODevice::ReadOnly)) di.manufacturer = PIString(_f.readAll()).trim();
if (di.pID > 0) break;
}
}
# endif
# endif
ret << di;
}
}
@@ -1177,7 +1244,13 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
if (test) {
for (int i = 0; i < ret.size_s(); ++i) {
#ifdef WINDOWS
void * hComm = CreateFileA(ret[i].path.dataAscii(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
void * hComm = CreateFileA(ret[i].path.dataAscii(),
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE) {
#else
int fd = ::open(ret[i].path.dataAscii(), O_NOCTTY | O_RDONLY);
@@ -1191,9 +1264,8 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
#ifndef WINDOWS
int void_ = 0;
fcntl(fd, F_SETFL, O_NONBLOCK);
if (::read(fd, &void_, 1) == -1)
rok = errno != EIO;
if (::read(fd, &void_, 1) == -1) rok = errno != EIO;
#endif
if (!rok) {
ret.remove(i);
@@ -1221,9 +1293,9 @@ void PISerial::threadedReadBufferSizeChanged() {
#if defined(LINUX)
serial_struct ss;
ioctl(fd, TIOCGSERIAL, &ss);
//piCoutObj << "b" << ss.xmit_fifo_size;
// piCoutObj << "b" << ss.xmit_fifo_size;
ss.xmit_fifo_size = piMaxi(threadedReadBufferSize(), 4096);
ioctl(fd, TIOCSSERIAL, &ss);
//piCoutObj << "a" << ss.xmit_fifo_size;
// piCoutObj << "a" << ss.xmit_fifo_size;
#endif
}
+13 -13
View File
@@ -5,22 +5,22 @@
* \~russian Последовательный порт
*/
/*
PIP - Platform Independent Primitives
COM
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
COM
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISERIAL_H
+38 -39
View File
@@ -1,24 +1,25 @@
/*
PIP - Platform Independent Primitives
File
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
File
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "pisharedmemory.h"
#include "piincludes_p.h"
#include "pipropertystorage.h"
#if defined(LINUX) || defined(MAC_OS)
# define SHM_POSIX
@@ -30,13 +31,13 @@
#endif
#ifdef MAC_OS
//# include <fcntl.h>
// # include <fcntl.h>
#endif
#ifdef SHM_POSIX
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/mman.h>
# include <sys/stat.h>
#endif
@@ -83,8 +84,7 @@ PISharedMemory::PISharedMemory(): PIIODevice() {
PISharedMemory::PISharedMemory(const PIString & shm_name, int size, PIIODevice::DeviceMode mode): PIIODevice(shm_name, mode) {
initPrivate();
dsize = size;
if (!shm_name.isEmpty())
open();
if (!shm_name.isEmpty()) open();
}
@@ -96,16 +96,16 @@ PISharedMemory::~PISharedMemory() {
bool PISharedMemory::openDevice() {
close();
//piCoutObj << "try open" << path() << dsize;
// piCoutObj << "try open" << path() << dsize;
#ifdef WINDOWS
PRIVATE->name = ("PIP_SHM_" + path()).toByteArray();
PRIVATE->name.push_back(0);
const char * nm = (const char *)PRIVATE->name.data();
PRIVATE->map = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, nm);
//piCoutObj << "open map =" << ullong(PRIVATE->map);
PRIVATE->map = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, nm);
// piCoutObj << "open map =" << ullong(PRIVATE->map);
if (!PRIVATE->map) {
PRIVATE->map = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)dsize, nm);
//piCoutObj << "create map =" << ullong(PRIVATE->map);
// piCoutObj << "create map =" << ullong(PRIVATE->map);
if (!PRIVATE->map) {
piCoutObj << "CreateFileMapping error," << errorString();
return false;
@@ -117,33 +117,32 @@ bool PISharedMemory::openDevice() {
piCoutObj << "MapViewOfFile error," << errorString();
return false;
}
//piCout << PRIVATE->map << PRIVATE->data;
// piCout << PRIVATE->map << PRIVATE->data;
#endif
#ifdef SHM_POSIX
PRIVATE->name = ("/pip_shm_" + path()).toByteArray();
PRIVATE->name.push_back(0);
int fd = shm_open((const char *)PRIVATE->name.data(), O_RDWR, 0777);
//piCoutObj << "try open" << PICoutManipulators::Hex << fd;
// piCoutObj << "try open" << PICoutManipulators::Hex << fd;
if (fd < 0) {
//piCoutObj << "shm_open error," << errorString();
// piCoutObj << "shm_open error," << errorString();
fd = shm_open((const char *)PRIVATE->name.data(), O_RDWR | O_CREAT, 0777);
//piCoutObj << "try create" << PICoutManipulators::Hex << (m | O_CREAT) << fd;
// piCoutObj << "try create" << PICoutManipulators::Hex << (m | O_CREAT) << fd;
if (fd < 0) {
piCoutObj << "shm_open error," << errorString();
return false;
}
PRIVATE->owner = true;
//piCoutObj << "created" << fd;
// piCoutObj << "created" << fd;
}
if (fd >= 0)
ftruncate(fd, dsize);
if (fd >= 0) ftruncate(fd, dsize);
PRIVATE->data = mmap(0, dsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
::close(fd);
if (PRIVATE->data == MAP_FAILED) {
piCoutObj << "mmap error," << errorString();
return false;
}
//piCoutObj << "opened" << PRIVATE->data;
// piCoutObj << "opened" << PRIVATE->data;
#endif
return true;
}
@@ -155,13 +154,13 @@ bool PISharedMemory::closeDevice() {
if (PRIVATE->map) CloseHandle(PRIVATE->map);
#endif
#ifdef SHM_POSIX
//piCoutObj << "close" << PIString(PRIVATE->name) << PRIVATE->data;
// piCoutObj << "close" << PIString(PRIVATE->name) << PRIVATE->data;
if (PRIVATE->data) munmap(PRIVATE->data, dsize);
if (PRIVATE->owner) {
//piCout << "unlink" << PIString(PRIVATE->name);
// piCout << "unlink" << PIString(PRIVATE->name);
shm_unlink((const char *)PRIVATE->name.data());
}
//if (fd > 0)
// if (fd > 0)
#endif
initPrivate();
return true;
@@ -204,11 +203,11 @@ void PISharedMemory::configureFromVariantDevice(const PIPropertyStorage & d) {
void PISharedMemory::initPrivate() {
#ifdef WINDOWS
PRIVATE->map = 0;
PRIVATE->map = 0;
PRIVATE->data = 0;
#endif
#ifdef SHM_POSIX
PRIVATE->data = 0;
PRIVATE->data = 0;
PRIVATE->owner = false;
#endif
}
@@ -250,12 +249,12 @@ int PISharedMemory::read(void * read_to, int max_size) {
int PISharedMemory::read(void * read_to, int max_size, int offset) {
#ifdef WINDOWS
if (!PRIVATE->data) return -1;
CopyMemory(read_to, &(((char*)(PRIVATE->data))[offset]), max_size);
CopyMemory(read_to, &(((char *)(PRIVATE->data))[offset]), max_size);
return max_size;
#endif
#ifdef SHM_POSIX
if (!PRIVATE->data) return -1;
memcpy(read_to, &(((char*)(PRIVATE->data))[offset]), max_size);
memcpy(read_to, &(((char *)(PRIVATE->data))[offset]), max_size);
return max_size;
#endif
return -1;
@@ -270,12 +269,12 @@ int PISharedMemory::write(const void * data, int max_size) {
int PISharedMemory::write(const void * data, int max_size, int offset) {
#ifdef WINDOWS
if (!PRIVATE->data) return -1;
CopyMemory(&(((char*)(PRIVATE->data))[offset]), data, max_size);
CopyMemory(&(((char *)(PRIVATE->data))[offset]), data, max_size);
return max_size;
#endif
#ifdef SHM_POSIX
if (!PRIVATE->data) return -1;
memcpy(&(((char*)(PRIVATE->data))[offset]), data, max_size);
memcpy(&(((char *)(PRIVATE->data))[offset]), data, max_size);
return max_size;
#endif
return -1;
+29 -31
View File
@@ -5,22 +5,22 @@
* \~russian Разделяемая память
*/
/*
PIP - Platform Independent Primitives
Shared Memory
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Shared Memory
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISHAREDMEMORY_H
@@ -33,26 +33,25 @@
//! \~\brief
//! \~english Shared memory.
//! \~russian Разделяемая память.
class PIP_EXPORT PISharedMemory: public PIIODevice
{
class PIP_EXPORT PISharedMemory: public PIIODevice {
PIIODEVICE(PISharedMemory, "shm");
public:
//! \~english Constructs empty %PISharedMemory
//! \~russian Создает пустой %PISharedMemory
explicit PISharedMemory();
//! \~english Constructs a shared memory object with name "shm_name", size "size" and open mode "mode"
//! \~russian Создает объект разделяемой памяти с именем "shm_name", размером "size" и режимом открытия "mode"
explicit PISharedMemory(const PIString & shm_name, int size, DeviceMode mode = ReadWrite);
virtual ~PISharedMemory();
//! \~english Read all shared memory content and return it as byte array
//! \~russian Читает всю разделяемую память и возвращает её как байтовый массив
PIByteArray readAll();
//! \~english Returns shared memory size
//! \~russian Возвращает размер разделяемой памяти
llong size() const;
@@ -60,11 +59,11 @@ public:
//! \~english Set shared memory size
//! \~russian Устанавливает размер разделяемой памяти
void setSize(llong s);
//! \~english Returns if shared memory object is empty (by size)
//! \~russian Возвращает пустой ли объект разделяемой памяти (по размеру)
bool isEmpty() const {return (size() <= 0);}
bool isEmpty() const { return (size() <= 0); }
//! \~english Read from shared memory to "read_to" no more than "max_size" and return readed bytes count
//! \~russian Читает из разделяемой памяти в "read_to" не более "max_size" и возвращает количество прочитанных байт
int read(void * read_to, int max_size);
@@ -72,7 +71,7 @@ public:
//! \~english Read from shared memory started from "offset" to "read_to" no more than "max_size" and return readed bytes count
//! \~russian Читает из разделяемой памяти с начала "offset" в "read_to" не более "max_size" и возвращает количество прочитанных байт
int read(void * read_to, int max_size, int offset);
//! \~english Write to shared memory "data" with size "max_size" and return written bytes count
//! \~russian Пишет в разделяемую память "data" размером "max_size" и возвращает количество записанных байт
int write(const void * data, int max_size);
@@ -83,12 +82,12 @@ public:
//! \~english Write "data" to shared memory
//! \~russian Пишет в разделяемую память "data"
int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
int write(const PIByteArray & data) { return write(data.data(), data.size_s()); }
//! \~english Write "data" to shared memory
//! \~russian Пишет в разделяемую память "data"
int write(const PIByteArray & data, int offset) {return write(data.data(), data.size_s(), offset);}
int write(const PIByteArray & data, int offset) { return write(data.data(), data.size_s(), offset); }
protected:
bool openDevice() override;
@@ -97,16 +96,15 @@ protected:
void configureFromFullPathDevice(const PIString & full_path) override;
PIPropertyStorage constructVariantDevice() const override;
void configureFromVariantDevice(const PIPropertyStorage & d) override;
ssize_t readDevice(void * read_to, ssize_t max_size) override {return read(read_to, max_size, 0);}
ssize_t writeDevice(const void * data, ssize_t max_size) override {return write(data, max_size, 0);}
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
ssize_t readDevice(void * read_to, ssize_t max_size) override { return read(read_to, max_size, 0); }
ssize_t writeDevice(const void * data, ssize_t max_size) override { return write(data, max_size, 0); }
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
private:
void initPrivate();
int dsize;
PRIVATE_DECLARATION(PIP_EXPORT)
};

Some files were not shown because too many files have changed in this diff Show More