Compare commits
32 Commits
pimap
...
16c12a2756
| Author | SHA1 | Date | |
|---|---|---|---|
| 16c12a2756 | |||
|
|
1b09ad5c27 | ||
|
|
00d06f71ba | ||
|
|
3873f0b03b | ||
| 6ae6e9a540 | |||
|
|
d13e68c206 | ||
| a4882dc054 | |||
|
|
a1b9b7e1d6 | ||
|
|
e1b89aeca8 | ||
| 242abaaf59 | |||
|
|
0116387fe3 | ||
|
|
f5953a0ba7 | ||
|
|
7aa407264f | ||
|
|
59c7896577 | ||
|
|
a69de63db0 | ||
| e96b399da7 | |||
| 33eefd7453 | |||
| c7fffe1280 | |||
| 1b04d7ecce | |||
| b66272a68a | |||
| f67e3030b9 | |||
| 1028233553 | |||
| ef8ffcd02f | |||
| 0897a8369f | |||
| fa19ad1093 | |||
| 8c6b3613b6 | |||
| a23eb341e2 | |||
| b2bc385397 | |||
| 0f9e592273 | |||
| cf4f58ed95 | |||
| 0243f588bc | |||
| af77974e91 |
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lapi_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lcode_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lctype_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define ldebug_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define ldo_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define ldump_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lfunc_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lgc_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define llex_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lmem_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lobject_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lopcodes_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lparser_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lstate_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lstring_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define ltable_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define ltm_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lundump_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lvm_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#define lzio_c
|
||||
#define LUA_CORE
|
||||
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
|
||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||
project(pip)
|
||||
set(pip_MAJOR 2)
|
||||
set(pip_MINOR 39)
|
||||
set(pip_MINOR 97)
|
||||
set(pip_REVISION 0)
|
||||
set(pip_SUFFIX )
|
||||
set(pip_COMPANY SHS)
|
||||
|
||||
@@ -7,19 +7,19 @@ class SomeIO: public PIIODevice {
|
||||
public:
|
||||
SomeIO(): PIIODevice() {}
|
||||
protected:
|
||||
bool openDevice() {
|
||||
bool openDevice() override {
|
||||
// open your device here
|
||||
return if_success;
|
||||
}
|
||||
int read(void * read_to, int max_size) {
|
||||
int readDevice(void * read_to, int max_size) override {
|
||||
// read from your device here
|
||||
return readed_bytes;
|
||||
}
|
||||
int write(const void * data, int max_size) {
|
||||
int writeDevice(const void * data, int max_size) override {
|
||||
// write to your device here
|
||||
return written_bytes;
|
||||
}
|
||||
void configureFromFullPath(const PIString & full_path) {
|
||||
void configureFromFullPathDevice(const PIString & full_path) override {
|
||||
// parse full_path and configure device here
|
||||
}
|
||||
};
|
||||
@@ -38,7 +38,7 @@ ser.configure("example.conf", "dev");
|
||||
//! [configureDevice]
|
||||
class SomeIO: public PIIODevice {
|
||||
...
|
||||
bool configureDevice(const void * e_main, const void * e_parent) {
|
||||
bool configureDevice(const void * e_main, const void * e_parent) override {
|
||||
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
|
||||
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
|
||||
setStringParam(readDeviceSetting<PIString>("stringParam", stringParam(), em, ep));
|
||||
|
||||
@@ -28,7 +28,7 @@ PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode)
|
||||
is_deleted = false;
|
||||
// setReopenEnabled(false);
|
||||
CONNECTL(ð, connected, [this](){opened_ = true; tcp.sendStart();});
|
||||
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
|
||||
CONNECT1(void, PIByteArray, &streampacker, packetReceiveEvent, this, _readed);
|
||||
CONNECTL(ð, disconnected, [this](bool){
|
||||
if (is_deleted) return;
|
||||
bool need_disconn = is_connected;
|
||||
|
||||
@@ -25,7 +25,7 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode)
|
||||
tcp.setRole(PICloud::TCP::Server);
|
||||
tcp.setServerName(server_name);
|
||||
setName("cloud_server__" + server_name);
|
||||
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
|
||||
CONNECT1(void, PIByteArray, &streampacker, packetReceiveEvent, this, _readed);
|
||||
CONNECTL(ð, connected, [this](){opened_ = true; piCoutObj << "connected"; tcp.sendStart();});
|
||||
CONNECTL(ð, disconnected, [this](bool){
|
||||
piCoutObj << "disconnected";
|
||||
@@ -189,7 +189,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
|
||||
} else {
|
||||
//piCoutObj << "new Client" << id;
|
||||
Client * c = new Client(this, id);
|
||||
CONNECTU(c, deleted, this, clientDeleted);
|
||||
CONNECT1(void, PIObject *, c, deleted, this, clientDeleted);
|
||||
clients_mutex.lock();
|
||||
clients_ << c;
|
||||
index_clients.insert(id, c);
|
||||
|
||||
@@ -168,14 +168,14 @@ PIByteArray PICloud::TCP::parseConnect_d(PIByteArray & ba) {
|
||||
|
||||
|
||||
uint PICloud::TCP::parseConnect(PIByteArray & ba) {
|
||||
uint ret;
|
||||
uint ret = 0;
|
||||
ba >> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint PICloud::TCP::parseDisconnect(PIByteArray & ba) {
|
||||
uint ret;
|
||||
uint ret = 0;
|
||||
ba >> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ PIByteArray piCompress(const PIByteArray & ba, int level) {
|
||||
|
||||
PIByteArray piDecompress(const PIByteArray & zba) {
|
||||
#ifdef PIP_COMPRESS
|
||||
ullong sz;
|
||||
ullong sz = 0;
|
||||
if (zba.size() < sizeof(ullong)) {
|
||||
piCout << "[PICompress]" << "Error: invalid input";
|
||||
return zba;
|
||||
|
||||
@@ -51,6 +51,18 @@ PRIVATE_DEFINITION_END(PIScreen::SystemConsole)
|
||||
PIScreen::SystemConsole::SystemConsole() {
|
||||
width = height = pwidth = pheight = 0;
|
||||
mouse_x = mouse_y = -1;
|
||||
}
|
||||
|
||||
|
||||
PIScreen::SystemConsole::~SystemConsole() {
|
||||
#ifdef WINDOWS
|
||||
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
|
||||
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PIScreen::SystemConsole::begin() {
|
||||
int w, h;
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->ulcoord.X = 0;
|
||||
@@ -74,18 +86,6 @@ PIScreen::SystemConsole::SystemConsole() {
|
||||
# endif
|
||||
#endif
|
||||
resize(w, h);
|
||||
}
|
||||
|
||||
|
||||
PIScreen::SystemConsole::~SystemConsole() {
|
||||
#ifdef WINDOWS
|
||||
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
|
||||
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PIScreen::SystemConsole::begin() {
|
||||
#ifdef WINDOWS
|
||||
SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
|
||||
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
||||
@@ -93,6 +93,7 @@ void PIScreen::SystemConsole::begin() {
|
||||
PRIVATE->bc.Y = 0;
|
||||
#endif
|
||||
clear();
|
||||
clearScreen();
|
||||
hideCursor();
|
||||
}
|
||||
|
||||
@@ -391,18 +392,17 @@ PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawe
|
||||
needLockRun(true);
|
||||
mouse_ = false;
|
||||
ret_func = slot;
|
||||
tile_focus = tile_dialog = 0;
|
||||
tile_focus = tile_dialog = nullptr;
|
||||
root.screen = this;
|
||||
listener = new PIKbdListener(key_eventS, this, startNow);
|
||||
CONNECTU(listener, mouseEvent, this, mouse_event);
|
||||
CONNECTU(listener, wheelEvent, this, wheel_event);
|
||||
CONNECT1(void, PIKbdListener::MouseEvent, listener, mouseEvent, this, mouse_event);
|
||||
CONNECT1(void, PIKbdListener::WheelEvent, listener, wheelEvent, this, wheel_event);
|
||||
if (startNow) start();
|
||||
}
|
||||
|
||||
|
||||
PIScreen::~PIScreen() {
|
||||
if (isRunning())
|
||||
stop();
|
||||
if (isRunning()) stop();
|
||||
PIThread::waitForFinish(10);
|
||||
listener->waitForFinish(10);
|
||||
delete listener;
|
||||
|
||||
@@ -151,7 +151,7 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
|
||||
//piCout << "mcast " << ce->readAddress() << ce->sendAddress();
|
||||
if (ce->open()) {
|
||||
eth_mcast << ce;
|
||||
CONNECTU(ce, threadedReadEvent, this, mcastRead);
|
||||
CONNECT2(void, const uchar *, int, ce, threadedReadEvent, this, mcastRead);
|
||||
} else {
|
||||
delete ce;
|
||||
}
|
||||
@@ -173,7 +173,7 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
|
||||
//piCout << "bcast " << ce->readAddress() << ce->sendAddress();
|
||||
if (ce->open()) {
|
||||
eth_mcast << ce;
|
||||
CONNECTU(ce, threadedReadEvent, this, mcastRead);
|
||||
CONNECT2(void, const uchar *, int, ce, threadedReadEvent, this, mcastRead);
|
||||
} else {
|
||||
delete ce;
|
||||
}
|
||||
@@ -189,7 +189,7 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
|
||||
eth_lo->setName("PIMulticast_loopback");
|
||||
if (!_send_only) {
|
||||
eth_lo->setParameter(PIEthernet::ReuseAddress, false);
|
||||
CONNECTU(eth_lo, threadedReadEvent, this, mcastRead);
|
||||
CONNECT2(void, const uchar *, int, eth_lo, threadedReadEvent, this, mcastRead);
|
||||
for (int i = 0; i < lo_pcnt; ++i) {
|
||||
eth_lo->setReadAddress("127.0.0.1", lo_port + i);
|
||||
if (eth_lo->open()) {
|
||||
@@ -248,7 +248,7 @@ void PIBroadcast::reinit() {
|
||||
}
|
||||
|
||||
|
||||
void PIBroadcast::mcastRead(uchar * data, int size) {
|
||||
void PIBroadcast::mcastRead(const uchar * data, int size) {
|
||||
PIByteArray cd = decryptData(PIByteArray(data, size));
|
||||
if (cd.isEmpty()) return;
|
||||
received(cd);
|
||||
|
||||
@@ -111,7 +111,7 @@ void PIStreamPacker::send(const PIByteArray & data) {
|
||||
}
|
||||
|
||||
|
||||
void PIStreamPacker::received(uchar * readed, int size) {
|
||||
void PIStreamPacker::received(const uchar * readed, int size) {
|
||||
received(PIByteArray(readed, size));
|
||||
}
|
||||
|
||||
@@ -195,8 +195,9 @@ void PIStreamPacker::received(const PIByteArray & data) {
|
||||
|
||||
void PIStreamPacker::assignDevice(PIIODevice * dev) {
|
||||
if (!dev) return;
|
||||
if (!dev->infoFlags()[PIIODevice::Reliable])
|
||||
if (!dev->infoFlags()[PIIODevice::Reliable]) {
|
||||
piCoutObj << "Warning! Not recommended to use with non-reliable" << dev;
|
||||
CONNECTU(dev, threadedReadEvent, this, received);
|
||||
CONNECTU(this, sendRequest, dev, write);
|
||||
}
|
||||
CONNECT2(void, const uchar *, int, dev, threadedReadEvent, this, received);
|
||||
CONNECT1(void, PIByteArray, this, sendRequest, dev, write);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase
|
||||
{
|
||||
PIIODEVICE(PICloudClient, "")
|
||||
PIIODEVICE(PICloudClient, "");
|
||||
public:
|
||||
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
||||
virtual ~PICloudClient();
|
||||
@@ -42,16 +42,17 @@ public:
|
||||
void setServerName(const PIString & server_name);
|
||||
void setKeepConnection(bool on);
|
||||
bool isConnected() const {return is_connected;}
|
||||
ssize_t bytesAvailable() const override {return buff.size();}
|
||||
|
||||
EVENT(connected)
|
||||
EVENT(disconnected)
|
||||
EVENT(connected);
|
||||
EVENT(disconnected);
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int size);
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
|
||||
|
||||
private:
|
||||
EVENT_HANDLER1(void, _readed, PIByteArray &, data);
|
||||
|
||||
@@ -32,24 +32,25 @@
|
||||
|
||||
class PIP_CLOUD_EXPORT PICloudServer: public PIIODevice, public PICloudBase
|
||||
{
|
||||
PIIODEVICE(PICloudServer, "")
|
||||
PIIODEVICE(PICloudServer, "");
|
||||
public:
|
||||
//! PICloudServer
|
||||
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
||||
virtual ~PICloudServer();
|
||||
|
||||
class Client : public PIIODevice {
|
||||
PIIODEVICE(PICloudServer::Client, "")
|
||||
PIIODEVICE(PICloudServer::Client, "");
|
||||
friend class PICloudServer;
|
||||
public:
|
||||
Client(PICloudServer * srv = nullptr, uint id = 0);
|
||||
virtual ~Client();
|
||||
protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int size);
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
|
||||
ssize_t bytesAvailable() const override {return buff.size();}
|
||||
|
||||
private:
|
||||
void pushBuffer(const PIByteArray & ba);
|
||||
@@ -65,13 +66,13 @@ public:
|
||||
|
||||
PIVector<PICloudServer::Client *> clients() const;
|
||||
|
||||
EVENT1(newConnection, PICloudServer::Client * , client)
|
||||
EVENT1(newConnection, PICloudServer::Client * , client);
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int max_size);
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int max_size) override;
|
||||
|
||||
private:
|
||||
EVENT_HANDLER1(void, _readed, PIByteArray &, ba);
|
||||
|
||||
@@ -1050,7 +1050,7 @@ PIString PICodeParser::procMacros(PIString fc) {
|
||||
if (ifcnt > 0) ifcnt--;
|
||||
else {
|
||||
//piCout << "main endif" << skip << grab;
|
||||
if (grab) pfc << procMacros(nfc);
|
||||
if (grab) pfc += procMacros(nfc);
|
||||
skip = grab = false;
|
||||
continue;
|
||||
}
|
||||
@@ -1059,7 +1059,7 @@ PIString PICodeParser::procMacros(PIString fc) {
|
||||
//piCout << "main elif" << skip << grab << cond_ok;
|
||||
if (cond_ok) {
|
||||
if (grab) {
|
||||
pfc << procMacros(nfc);
|
||||
pfc += procMacros(nfc);
|
||||
skip = true; grab = false;
|
||||
}
|
||||
continue;
|
||||
@@ -1075,12 +1075,12 @@ PIString PICodeParser::procMacros(PIString fc) {
|
||||
}
|
||||
if (mif.left(4) == s_else && ifcnt == 0) {
|
||||
//piCout << "main else" << skip << grab;
|
||||
if (grab) pfc << procMacros(nfc);
|
||||
if (grab) pfc += procMacros(nfc);
|
||||
if (skip && !cond_ok) {skip = false; grab = true;}
|
||||
else {skip = true; grab = false;}
|
||||
continue;
|
||||
}
|
||||
if (grab) nfc << line << '\n';
|
||||
if (grab) nfc += line + '\n';
|
||||
continue;
|
||||
}
|
||||
if (mif.left(2) == s_if) {
|
||||
@@ -1095,8 +1095,8 @@ PIString PICodeParser::procMacros(PIString fc) {
|
||||
//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;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
class PIP_EXPORT PIKbdListener: public PIThread
|
||||
{
|
||||
PIOBJECT_SUBCLASS(PIKbdListener, PIThread)
|
||||
PIOBJECT_SUBCLASS(PIKbdListener, PIThread);
|
||||
friend class PIConsole;
|
||||
friend class PITerminal;
|
||||
public:
|
||||
@@ -176,9 +176,9 @@ public:
|
||||
EVENT_HANDLER(void, setActive) {setActive(true);}
|
||||
EVENT_HANDLER1(void, setActive, bool, yes);
|
||||
|
||||
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
|
||||
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void * , data)
|
||||
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void * , data)
|
||||
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data);
|
||||
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void * , data);
|
||||
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void * , data);
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
@@ -205,9 +205,9 @@ public:
|
||||
static PIKbdListener * instance() {return _object;}
|
||||
|
||||
private:
|
||||
void begin();
|
||||
void run() {readKeyboard();}
|
||||
void end();
|
||||
void begin() override;
|
||||
void run() override {readKeyboard();}
|
||||
void end() override;
|
||||
|
||||
#ifndef WINDOWS
|
||||
struct PIP_EXPORT EscSeq {
|
||||
@@ -247,13 +247,11 @@ private:
|
||||
};
|
||||
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::KeyEvent & v) {s << v.key << v.modifiers; return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::MouseEvent & v) {s << v.x << v.y << (int)v.action << v.buttons << v.modifiers; return s;}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::WheelEvent & v) {s << (*(PIKbdListener::MouseEvent*)&v) << (uchar)v.direction; return s;}
|
||||
BINARY_STREAM_WRITE(PIKbdListener::MouseEvent) {s << v.x << v.y << v.action << v.buttons << v.modifiers; return s;}
|
||||
BINARY_STREAM_READ (PIKbdListener::MouseEvent) {s >> v.x >> v.y >> v.action >> v.buttons >> v.modifiers; return s;}
|
||||
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::KeyEvent & v) {s >> v.key >> v.modifiers; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::MouseEvent & v) {int a(0); s >> v.x >> v.y >> a >> v.buttons >> v.modifiers; v.action = (PIKbdListener::MouseAction)a; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::WheelEvent & v) {uchar d(0); s >> (*(PIKbdListener::MouseEvent*)&v) >> d; v.direction = d; return s;}
|
||||
BINARY_STREAM_WRITE(PIKbdListener::WheelEvent) {s << (*(PIKbdListener::MouseEvent*)&v) << v.direction; return s;}
|
||||
BINARY_STREAM_READ (PIKbdListener::WheelEvent) {s >> (*(PIKbdListener::MouseEvent*)&v) >> v.direction; return s;}
|
||||
|
||||
REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent)
|
||||
REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
class PIP_CONSOLE_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
|
||||
{
|
||||
PIOBJECT_SUBCLASS(PIScreen, PIThread)
|
||||
PIOBJECT_SUBCLASS(PIScreen, PIThread);
|
||||
class SystemConsole;
|
||||
public:
|
||||
|
||||
@@ -76,8 +76,8 @@ public:
|
||||
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)
|
||||
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data);
|
||||
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e);
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
@@ -134,9 +134,9 @@ private:
|
||||
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
|
||||
};
|
||||
|
||||
void begin();
|
||||
void run();
|
||||
void end();
|
||||
void begin() override;
|
||||
void run() override;
|
||||
void end() override;
|
||||
void key_event(PIKbdListener::KeyEvent key);
|
||||
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
|
||||
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
|
||||
@@ -145,9 +145,9 @@ private:
|
||||
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);
|
||||
void tileRemovedInternal(PIScreenTile * t);
|
||||
void tileSetFocusInternal(PIScreenTile * t);
|
||||
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e) override;
|
||||
void tileRemovedInternal(PIScreenTile * t) override;
|
||||
void tileSetFocusInternal(PIScreenTile * t) override;
|
||||
|
||||
bool mouse_;
|
||||
SystemConsole console;
|
||||
|
||||
@@ -64,8 +64,8 @@ protected:
|
||||
};
|
||||
PIVector<Variable> variables;
|
||||
PIScreenTypes::Alignment alignment;
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class PIScreenDrawer;
|
||||
|
||||
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
|
||||
friend class PIScreen;
|
||||
PIOBJECT_SUBCLASS(PIScreenTile, PIObject)
|
||||
PIOBJECT_SUBCLASS(PIScreenTile, PIObject);
|
||||
public:
|
||||
PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
|
||||
virtual ~PIScreenTile();
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile);
|
||||
public:
|
||||
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
|
||||
TileSimple(const PIString & n = PIString());
|
||||
@@ -40,15 +40,15 @@ public:
|
||||
PIVector<Row> content;
|
||||
PIScreenTypes::Alignment alignment;
|
||||
protected:
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
};
|
||||
|
||||
|
||||
class TileList;
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile);
|
||||
friend class TileList;
|
||||
public:
|
||||
TileScrollBar(const PIString & n = PIString());
|
||||
@@ -62,16 +62,16 @@ public:
|
||||
int thickness;
|
||||
protected:
|
||||
void _check();
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool mouseEvent(PIKbdListener::MouseEvent me) override;
|
||||
int minimum_, maximum_, value_;
|
||||
PIChar line_char;
|
||||
};
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileList, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileList, PIScreenTile);
|
||||
public:
|
||||
enum SelectionMode {
|
||||
NoSelection,
|
||||
@@ -93,19 +93,19 @@ public:
|
||||
PISet<int> selected;
|
||||
int lhei, cur, offset;
|
||||
protected:
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void resizeEvent(int w, int h);
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||
bool wheelEvent(PIKbdListener::WheelEvent we);
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void resizeEvent(int w, int h) override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
||||
bool mouseEvent(PIKbdListener::MouseEvent me) override;
|
||||
bool wheelEvent(PIKbdListener::WheelEvent we) override;
|
||||
TileScrollBar * scroll;
|
||||
bool mouse_sel;
|
||||
};
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileButton, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileButton, PIScreenTile);
|
||||
public:
|
||||
TileButton(const PIString & n = PIString());
|
||||
virtual ~TileButton() {}
|
||||
@@ -115,17 +115,17 @@ public:
|
||||
PIScreenTypes::CellFormat format;
|
||||
PIString text;
|
||||
protected:
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile);
|
||||
public:
|
||||
TileButtons(const PIString & n = PIString());
|
||||
virtual ~TileButtons() {}
|
||||
@@ -137,10 +137,10 @@ public:
|
||||
PIVector<Button> content;
|
||||
int cur;
|
||||
protected:
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||
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;
|
||||
@@ -150,7 +150,7 @@ protected:
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile);
|
||||
public:
|
||||
TileCheck(const PIString & n = PIString());
|
||||
virtual ~TileCheck() {}
|
||||
@@ -161,15 +161,15 @@ public:
|
||||
PIString text;
|
||||
bool toggled;
|
||||
protected:
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile);
|
||||
public:
|
||||
TileProgress(const PIString & n = PIString());
|
||||
virtual ~TileProgress() {}
|
||||
@@ -179,26 +179,26 @@ public:
|
||||
double maximum;
|
||||
double value;
|
||||
protected:
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
};
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
|
||||
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);
|
||||
public:
|
||||
TilePICout(const PIString & n = PIString());
|
||||
virtual ~TilePICout() {}
|
||||
PIScreenTypes::CellFormat format;
|
||||
int max_lines;
|
||||
protected:
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
||||
};
|
||||
|
||||
|
||||
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileInput, PIScreenTile)
|
||||
PIOBJECT_SUBCLASS(TileInput, PIScreenTile);
|
||||
public:
|
||||
TileInput(const PIString & n = PIString());
|
||||
virtual ~TileInput() {}
|
||||
@@ -206,9 +206,9 @@ public:
|
||||
PIString text;
|
||||
int max_length;
|
||||
protected:
|
||||
void sizeHint(int & w, int & h) const;
|
||||
void drawEvent(PIScreenDrawer * d);
|
||||
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
||||
void reserCursor();
|
||||
int cur, offset;
|
||||
bool inv;
|
||||
|
||||
@@ -143,11 +143,14 @@ 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;}
|
||||
//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;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::TileEvent & v) {s << v.type << v.data; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::TileEvent & v) {s >> v.type >> v.data; return s;}
|
||||
BINARY_STREAM_WRITE(PIScreenTypes::Cell) {s << v.format.raw_format << v.symbol; return s;}
|
||||
BINARY_STREAM_READ (PIScreenTypes::Cell) {s >> v.format.raw_format >> v.symbol; return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(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)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
class PIP_CONSOLE_EXPORT PITerminal: public PIThread
|
||||
{
|
||||
PIOBJECT_SUBCLASS(PITerminal, PIThread)
|
||||
PIOBJECT_SUBCLASS(PITerminal, PIThread);
|
||||
public:
|
||||
|
||||
//! Constructs %PITerminal
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
void readConsole();
|
||||
void getCursor(int & x, int & y);
|
||||
uchar invertColor(uchar c);
|
||||
void run();
|
||||
void run() override;
|
||||
#ifndef WINDOWS
|
||||
void parseInput(const PIString & s);
|
||||
bool isCompleteEscSeq(const PIString & es);
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
#include "picontainers.h"
|
||||
|
||||
|
||||
const ssize_t minAlloc = 64;
|
||||
const size_t minAlloc = 64;
|
||||
|
||||
|
||||
ssize_t _PIContainerConstantsBase::calcMinCountPoT(ssize_t szof) {
|
||||
ssize_t ret = 0, elc = 1;
|
||||
size_t _PIContainerConstantsBase::calcMinCountPoT(size_t szof) {
|
||||
size_t ret = 0, elc = 1;
|
||||
while (elc * szof < minAlloc) {
|
||||
elc *= 2;
|
||||
++ret;
|
||||
|
||||
@@ -65,13 +65,13 @@ private:
|
||||
|
||||
class PIP_EXPORT _PIContainerConstantsBase {
|
||||
public:
|
||||
static ssize_t calcMinCountPoT(ssize_t szof);
|
||||
static size_t calcMinCountPoT(size_t szof);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class _PIContainerConstants {
|
||||
public:
|
||||
static ssize_t minCountPoT() {static ssize_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
|
||||
static size_t minCountPoT() {static size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -645,7 +645,7 @@ public:
|
||||
inline size_t length() const {return pid_size;}
|
||||
|
||||
//! \~english Number of elements that the container has currently allocated space for.
|
||||
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
|
||||
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
|
||||
//! \~\details
|
||||
//! \~english To find out the actual number of items, use the function \a size().
|
||||
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
|
||||
@@ -655,18 +655,18 @@ public:
|
||||
inline size_t _start() const {return pid_start;}
|
||||
|
||||
//! \~english Checks if the container has no elements.
|
||||
//! \~russian Проверяет пуст ли контейнер.
|
||||
//! \~russian Проверяет пуст ли массив.
|
||||
//! \~\return
|
||||
//! \~english **true** if the container is empty, **false** otherwise
|
||||
//! \~russian **true** если контейнер пуст, **false** иначе.
|
||||
//! \~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);}
|
||||
|
||||
//! \~english Checks if the container has elements.
|
||||
//! \~russian Проверяет не пуст ли контейнер.
|
||||
//! \~russian Проверяет не пуст ли массив.
|
||||
//! \~\return
|
||||
//! \~english **true** if the container is not empty, **false** otherwise
|
||||
//! \~russian **true** если контейнер не пуст, **false** иначе.
|
||||
//! \~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);}
|
||||
|
||||
@@ -689,7 +689,7 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
|
||||
inline bool any(std::function<bool(const T & e)> test) const {
|
||||
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
||||
if (test(pid_data[i])) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -714,7 +714,7 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
|
||||
inline bool every(std::function<bool(const T & e)> test) const {
|
||||
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
||||
if (!test(pid_data[i])) return false;
|
||||
}
|
||||
return true;
|
||||
@@ -825,7 +825,7 @@ public:
|
||||
start = pid_size + start;
|
||||
if (start < 0) start = 0;
|
||||
}
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
||||
if (e == pid_data[i]) return true;
|
||||
}
|
||||
return false;
|
||||
@@ -856,13 +856,13 @@ public:
|
||||
//! piCout << v.entries(2, -4); // 2
|
||||
//! \endcode
|
||||
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexOf()
|
||||
inline int entries(const T & e, size_t start = 0) const {
|
||||
inline int entries(const T & e, ssize_t start = 0) const {
|
||||
int ec = 0;
|
||||
if (start < 0) {
|
||||
start = pid_size + start;
|
||||
if (start < 0) start = 0;
|
||||
}
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
||||
if (e == pid_data[i]) ++ec;
|
||||
}
|
||||
return ec;
|
||||
@@ -890,13 +890,13 @@ public:
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere()
|
||||
inline int entries(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
|
||||
int ec = 0;
|
||||
if (start < 0) {
|
||||
start = pid_size + start;
|
||||
if (start < 0) start = 0;
|
||||
}
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
||||
if (test(pid_data[i])) ++ec;
|
||||
}
|
||||
return ec;
|
||||
@@ -931,14 +931,14 @@ public:
|
||||
//! piCout << v.indexOf(2, -3); // 0
|
||||
//! \endcode
|
||||
//! \~\sa \a indexWhere(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
||||
inline ssize_t indexOf(const T & e, size_t start = 0) const {
|
||||
inline ssize_t indexOf(const T & e, ssize_t start = 0) const {
|
||||
if (start < 0) {
|
||||
start = pid_size + start;
|
||||
if (start < 0) start = 0;
|
||||
}
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
||||
if (e == pid_data[i]) {
|
||||
return i - pid_start;
|
||||
return ssize_t(i) - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -972,14 +972,14 @@ public:
|
||||
//! piCout << v.indexWhere([](const PIString & s){return s.startsWith('k');}); // -1
|
||||
//! \endcode
|
||||
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
||||
inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||
inline ssize_t indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
|
||||
if (start < 0) {
|
||||
start = pid_size + start;
|
||||
if (start < 0) start = 0;
|
||||
}
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
||||
if (test(pid_data[i])) {
|
||||
return i - pid_start;
|
||||
return ssize_t(i) - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -1022,9 +1022,9 @@ public:
|
||||
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
|
||||
if (start >= size_s()) start = pid_size - 1;
|
||||
if (start < 0) start = pid_size + start;
|
||||
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
|
||||
for (size_t i = pid_start + size_t(start); i >= pid_start; --i) {
|
||||
if (e == pid_data[i]) {
|
||||
return i - pid_start;
|
||||
return ssize_t(i) - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -1058,9 +1058,9 @@ public:
|
||||
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
|
||||
if (start >= size_s()) start = pid_size - 1;
|
||||
if (start < 0) start = pid_size + start;
|
||||
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
|
||||
for (size_t i = pid_start + size_t(start); i >= pid_start; --i) {
|
||||
if (test(pid_data[i])) {
|
||||
return i - pid_start;
|
||||
return ssize_t(i) - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -1406,7 +1406,7 @@ public:
|
||||
inline PIDeque<T> & insert(size_t index, std::initializer_list<T> init_list) {
|
||||
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||
if (dir) {
|
||||
ssize_t os = pid_size - index;
|
||||
ssize_t os = ssize_t(pid_size) - index;
|
||||
alloc_forward(pid_size + init_list.size());
|
||||
if (os > 0) {
|
||||
memmove((void*)(&(pid_data[index + pid_start + init_list.size()])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
|
||||
@@ -1461,7 +1461,7 @@ public:
|
||||
piSwap<T*>(pid_data, other.pid_data);
|
||||
piSwap<size_t>(pid_size, other.pid_size);
|
||||
piSwap<size_t>(pid_rsize, other.pid_rsize);
|
||||
piSwap<ssize_t>(pid_start, other.pid_start);
|
||||
piSwap<size_t>(pid_start, other.pid_start);
|
||||
}
|
||||
|
||||
//! \~english Sorts the elements in non-descending order.
|
||||
@@ -1572,10 +1572,10 @@ public:
|
||||
//! Если `add_size < 0`, то с конца массива удаляются элементы.
|
||||
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
|
||||
//! \~\sa \a resize()
|
||||
inline PIDeque<T> & enlarge(llong pid_size) {
|
||||
llong ns = size_s() + pid_size;
|
||||
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));
|
||||
else resize(size_t(ns), e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1608,7 +1608,7 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||
inline PIDeque<T> & removeAll(const T & e) {
|
||||
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
if (pid_data[i + pid_start] == e) {
|
||||
remove(i);
|
||||
--i;
|
||||
@@ -1629,7 +1629,7 @@ public:
|
||||
//! \endcode
|
||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
|
||||
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
if (test(pid_data[i + pid_start])) {
|
||||
remove(i);
|
||||
--i;
|
||||
@@ -1938,7 +1938,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 prepend(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 Удаляет один элемент с конца массива.
|
||||
@@ -2280,7 +2280,8 @@ private:
|
||||
if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) {
|
||||
return pid_rsize + pid_rsize;
|
||||
}
|
||||
ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
|
||||
size_t t = _PIContainerConstants<T>::minCountPoT();
|
||||
size_t s_ = s - 1;
|
||||
while (s_ >> t)
|
||||
++t;
|
||||
return (1 << t);
|
||||
@@ -2348,8 +2349,8 @@ private:
|
||||
inline void checkMove() {
|
||||
if (pid_size >= 4) {
|
||||
if (pid_size < pid_rsize / 6) {
|
||||
if (pid_start < ssize_t(pid_size + pid_size) || pid_start > (ssize_t(pid_rsize) - ssize_t(pid_size) - ssize_t(pid_size))) {
|
||||
ssize_t ns = (pid_rsize - pid_size) / 2;
|
||||
if (pid_start < (pid_size + pid_size) || ssize_t(pid_start) > (ssize_t(pid_rsize) - ssize_t(pid_size) - ssize_t(pid_size))) {
|
||||
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));
|
||||
pid_start = ns;
|
||||
@@ -2357,7 +2358,7 @@ private:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ssize_t ns = (pid_rsize - 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));
|
||||
pid_start = ns;
|
||||
@@ -2387,14 +2388,14 @@ private:
|
||||
}
|
||||
inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) { //alloc backward
|
||||
size_t as;
|
||||
if (pid_start + start_offset < 0) {
|
||||
if (ssize_t(pid_start) + start_offset < 0) {
|
||||
as = asize(pid_rsize - start_offset);
|
||||
} else {
|
||||
as = pid_rsize;
|
||||
}
|
||||
if (as > pid_rsize) {
|
||||
T * td = (T*)(malloc(as * sizeof(T)));
|
||||
ssize_t ns = pid_start + as - pid_rsize;
|
||||
size_t ns = pid_start + 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));
|
||||
@@ -2410,8 +2411,9 @@ private:
|
||||
}
|
||||
|
||||
T * pid_data;
|
||||
size_t pid_size, pid_rsize;
|
||||
ssize_t pid_start;
|
||||
size_t pid_size;
|
||||
size_t pid_rsize;
|
||||
size_t pid_start;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -30,19 +30,56 @@
|
||||
#include "pipair.h"
|
||||
|
||||
|
||||
template<class T>
|
||||
void piQuickSort(T * a, ssize_t N) {
|
||||
if (N < 1) return;
|
||||
if (N < 46) {
|
||||
T tmp;
|
||||
ssize_t i,j;
|
||||
for(i=1; i<=N; i++) {
|
||||
tmp = a[i];
|
||||
j = i-1;
|
||||
while(tmp<a[j] && j>=0) {
|
||||
a[j+1] = a[j];
|
||||
j = j-1;
|
||||
}
|
||||
a[j+1] = tmp;
|
||||
}
|
||||
} else {
|
||||
ssize_t i = 0, j = N;
|
||||
T & p(a[N >> 1]);
|
||||
do {
|
||||
while (a[i] < p) i++;
|
||||
while (a[j] > p) j--;
|
||||
if (i <= j) {
|
||||
if (i != j) {
|
||||
//piCout << "swap" << i << j << a[i] << a[j];
|
||||
piSwap<T>(a[i], a[j]);
|
||||
}
|
||||
i++; j--;
|
||||
}
|
||||
} while (i <= j);
|
||||
if (j > 0) piQuickSort(a, j);
|
||||
if (N > i) piQuickSort(a + i, N - i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Key, typename T>
|
||||
class PIMapIterator;
|
||||
|
||||
|
||||
template <typename Key, typename T>
|
||||
class PIMap {
|
||||
template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIMap<Key1, T1> & v);
|
||||
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v);
|
||||
template <typename Key1, typename T1> friend class PIMapIterator;
|
||||
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:
|
||||
PIMap() {}
|
||||
PIMap() {;}
|
||||
PIMap(const PIMap<Key, T> & other) {*this = other;}
|
||||
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)) {}
|
||||
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
|
||||
PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
|
||||
for (auto i: init_list)
|
||||
insert(std::get<0>(i), std::get<1>(i));
|
||||
@@ -53,6 +90,7 @@ public:
|
||||
if (this == &other) return *this;
|
||||
clear();
|
||||
pim_content = other.pim_content;
|
||||
pim_index = other.pim_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -167,15 +205,12 @@ public:
|
||||
T & operator [](const Key & key) {
|
||||
bool f(false);
|
||||
ssize_t i = _find(key, f);
|
||||
if (!f) pim_content.insert(i, PIPair<Key, T>(key, T()));
|
||||
return pim_content[i].second;
|
||||
}
|
||||
const T operator [](const Key & key) const {
|
||||
bool f(false);
|
||||
ssize_t i = _find(key, f);
|
||||
if (f) return pim_content[i].second;
|
||||
return T();
|
||||
if (f) return pim_content[pim_index[i].index];
|
||||
pim_content.push_back(T());
|
||||
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
||||
return pim_content.back();
|
||||
}
|
||||
const T operator [](const Key & key) const {bool f(false); ssize_t i = _find(key, f); if (f) return pim_content[pim_index[i].index]; return T();}
|
||||
const T at(const Key & key) const {return (*this)[key];}
|
||||
|
||||
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
|
||||
@@ -186,26 +221,27 @@ public:
|
||||
#endif
|
||||
assert(&other != this);
|
||||
if (other.isEmpty()) return *this;
|
||||
// if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
|
||||
// if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
|
||||
for (int i = 0; i < other.pim_content.size_s(); ++i)
|
||||
insert(other.pim_content[i].first, other.pim_content[i].second);
|
||||
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
|
||||
if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
|
||||
for (int i = 0; i < other.pim_index.size_s(); ++i)
|
||||
insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content);}
|
||||
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content);}
|
||||
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);}
|
||||
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);}
|
||||
bool contains(const Key & key) const {bool f(false); _find(key, f); return f;}
|
||||
|
||||
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size);return *this;}
|
||||
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;}
|
||||
|
||||
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;}
|
||||
PIMap<Key, T> & remove(const Key & key) {return removeOne(key);}
|
||||
PIMap<Key, T> & erase(const Key & key) {return removeOne(key);}
|
||||
PIMap<Key, T> & clear() {pim_content.clear(); return *this;}
|
||||
PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;}
|
||||
|
||||
void swap(PIMap<Key, T> & other) {
|
||||
pim_content.swap(other.pim_content);
|
||||
pim_index.swap(other.pim_index);
|
||||
}
|
||||
|
||||
PIMap<Key, T> & insert(const Key & key, const T & value) {
|
||||
@@ -213,9 +249,10 @@ public:
|
||||
ssize_t i = _find(key, f);
|
||||
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
|
||||
if (f) {
|
||||
pim_content[i].second = value;
|
||||
pim_content[pim_index[i].index] = value;
|
||||
} else {
|
||||
pim_content.insert(i, PIPair<Key, T>(key, value));
|
||||
pim_content.push_back(value);
|
||||
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -224,34 +261,20 @@ public:
|
||||
ssize_t i = _find(key, f);
|
||||
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
|
||||
if (f) {
|
||||
pim_content[i].second = std::move(value);
|
||||
pim_content[pim_index[i].index] = std::move(value);
|
||||
} else {
|
||||
// pim_content.push_back(std::move(value));
|
||||
// pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
||||
pim_content.insert(i, PIPair<Key, T>(key, std::move(value)));
|
||||
pim_content.push_back(std::move(value));
|
||||
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
const T value(const Key & key, const T & default_ = T()) const {
|
||||
bool f(false);
|
||||
ssize_t i = _find(key, f);
|
||||
if (!f) return default_;
|
||||
return pim_content[i].second;
|
||||
}
|
||||
PIVector<T> values() const {
|
||||
PIVector<T> ret;
|
||||
for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].second;
|
||||
return ret;
|
||||
}
|
||||
Key key(const T & value_, const Key & default_ = Key()) const {
|
||||
for (int i = 0; i < pim_content.size_s(); ++i)
|
||||
if (pim_content[i].second == value_)
|
||||
return pim_content[i].first;
|
||||
return default_;
|
||||
}
|
||||
const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];}
|
||||
PIVector<T> values() const {return pim_content;}
|
||||
Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;}
|
||||
PIVector<Key> keys() const {
|
||||
PIVector<Key> ret;
|
||||
for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].first;
|
||||
for (int i = 0; i < pim_index.size_s(); ++i)
|
||||
ret << pim_index[i].key;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -259,53 +282,68 @@ public:
|
||||
piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:";
|
||||
for (size_t i = 0; i < pim_content.size(); ++i)
|
||||
piCout << PICoutManipulators::Tab << i << ":" << pim_content[i];
|
||||
// piCout << "index:";
|
||||
// for (size_t i = 0; i < pim_index.size(); ++i)
|
||||
// piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index;
|
||||
piCout << "index:";
|
||||
for (size_t i = 0; i < pim_index.size(); ++i)
|
||||
piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index;
|
||||
}
|
||||
|
||||
protected:
|
||||
// struct MapIndex {
|
||||
// MapIndex(Key k = Key(), size_t i = 0): key(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;}
|
||||
// };
|
||||
// template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
|
||||
// template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
|
||||
struct MapIndex {
|
||||
MapIndex(Key k = Key(), size_t i = 0): key(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;}
|
||||
};
|
||||
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);
|
||||
|
||||
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_content[mid].first) first = mid + 1;
|
||||
else if (key < pim_content[mid].first) last = mid - 1;
|
||||
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;
|
||||
}
|
||||
void _sort() {piQuickSort<MapIndex>(pim_index.data(), pim_index.size_s() - 1);}
|
||||
ssize_t _find(const Key & k, bool & found) const {
|
||||
if (pim_content.isEmpty()) {
|
||||
if (pim_index.isEmpty()) {
|
||||
found = false;
|
||||
return 0;
|
||||
}
|
||||
return binarySearch(0, pim_content.size_s() - 1, k, found);
|
||||
return binarySearch(0, pim_index.size_s() - 1, k, found);
|
||||
}
|
||||
void _remove(ssize_t index) {
|
||||
pim_content.remove(index);
|
||||
//if (index >= pim_index.size()) return;
|
||||
size_t ci = pim_index[index].index, bi = pim_index.size() - 1;
|
||||
pim_index.remove(index);
|
||||
for (size_t i = 0; i < pim_index.size(); ++i)
|
||||
if (pim_index[i].index == bi) {
|
||||
pim_index[i].index = ci;
|
||||
break;
|
||||
}
|
||||
piSwap<T>(pim_content[ci], pim_content.back());
|
||||
pim_content.resize(pim_index.size());
|
||||
}
|
||||
const value_type _pair(ssize_t index) const {
|
||||
if (index < 0 || index >= pim_content.size_s()) return value_type();
|
||||
return pim_content[index];
|
||||
if (index < 0 || index >= pim_index.size_s())
|
||||
return value_type();
|
||||
//piCout << "_pair" << index << pim_index[index].index;
|
||||
return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
|
||||
}
|
||||
Key & _key(ssize_t index) {return pim_content[index].first;}
|
||||
T & _value(ssize_t index) {return pim_content[index].second;}
|
||||
Key & _key(ssize_t index) {return pim_index[index].key;}
|
||||
T & _value(ssize_t index) {return pim_content[pim_index[index].index];}
|
||||
|
||||
PIDeque<PIPair<Key, T>> pim_content;
|
||||
PIVector<T> pim_content;
|
||||
PIDeque<MapIndex> pim_index;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ 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()
|
||||
@@ -141,4 +142,5 @@ PIPair<T1,T2> createPIPair(T1 && f, T2 && s) {
|
||||
return PIPair<T1,T2>(std::move(f), std::move(s));
|
||||
}
|
||||
|
||||
|
||||
#endif // PIPAIR_H
|
||||
|
||||
@@ -645,7 +645,7 @@ public:
|
||||
inline size_t length() const {return piv_size;}
|
||||
|
||||
//! \~english Number of elements that the container has currently allocated space for.
|
||||
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
|
||||
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
|
||||
//! \~\details
|
||||
//! \~english To find out the actual number of items, use the function \a size().
|
||||
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
|
||||
@@ -653,18 +653,18 @@ public:
|
||||
inline size_t capacity() const {return piv_rsize;}
|
||||
|
||||
//! \~english Checks if the container has no elements.
|
||||
//! \~russian Проверяет пуст ли контейнер.
|
||||
//! \~russian Проверяет пуст ли массив.
|
||||
//! \~\return
|
||||
//! \~english **true** if the container is empty, **false** otherwise
|
||||
//! \~russian **true** если контейнер пуст, **false** иначе.
|
||||
//! \~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);}
|
||||
|
||||
//! \~english Checks if the container has elements.
|
||||
//! \~russian Проверяет не пуст ли контейнер.
|
||||
//! \~russian Проверяет не пуст ли массив.
|
||||
//! \~\return
|
||||
//! \~english **true** if the container is not empty, **false** otherwise
|
||||
//! \~russian **true** если контейнер не пуст, **false** иначе.
|
||||
//! \~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);}
|
||||
|
||||
@@ -1512,8 +1512,8 @@ public:
|
||||
//! Если `add_size < 0`, то с конца массива удаляются элементы.
|
||||
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
|
||||
//! \~\sa \a resize()
|
||||
inline PIVector<T> & enlarge(llong add_size, const T & e = T()) {
|
||||
llong ns = size_s() + add_size;
|
||||
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);
|
||||
return *this;
|
||||
|
||||
@@ -265,13 +265,15 @@
|
||||
|
||||
#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 "-Wdeprecated-declarations"
|
||||
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
|
||||
# pragma GCC diagnostic ignored "-Wc++11-extensions"
|
||||
# endif
|
||||
@@ -287,7 +289,9 @@
|
||||
|
||||
#ifdef CC_VC
|
||||
# undef DEPRECATED
|
||||
# define 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)
|
||||
@@ -312,7 +316,9 @@
|
||||
|
||||
#ifdef CC_OTHER
|
||||
# undef DEPRECATED
|
||||
# undef DEPRECATEDM
|
||||
# define DEPRECATED
|
||||
# define DEPRECATEDM(msg)
|
||||
#endif
|
||||
|
||||
#endif //DOXYGEN
|
||||
|
||||
523
libs/main/core/pibinarystream.h
Normal file
523
libs/main/core/pibinarystream.h
Normal file
@@ -0,0 +1,523 @@
|
||||
/*! \file pibinarystream.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Binary serialization interface
|
||||
* \~russian Интерфейс бинарной сериализации
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Binary serialization interface
|
||||
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 PIBINARYSTREAM_H
|
||||
#define PIBINARYSTREAM_H
|
||||
|
||||
#include "pimemoryblock.h"
|
||||
#include "pibitarray.h"
|
||||
#include "pimap.h"
|
||||
#include "pivector2d.h"
|
||||
|
||||
#define PIP_BINARY_STREAM
|
||||
|
||||
#define BINARY_STREAM_FRIEND(T) \
|
||||
template<typename P> friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v); \
|
||||
template<typename P> friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v);
|
||||
#define BINARY_STREAM_WRITE(T) \
|
||||
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v)
|
||||
#define BINARY_STREAM_READ(T) \
|
||||
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v)
|
||||
|
||||
|
||||
//! \ingroup Core
|
||||
//! \~\brief
|
||||
//! \~english Binary serialization interface.
|
||||
//! \~russian Интерфейс бинарной сериализации.
|
||||
//! \~\details
|
||||
//! \~english In your class you should implement this methods:
|
||||
//! \~russian В производном классе вы должны реализовать следующие методы:
|
||||
//! \~\code
|
||||
//! bool binaryStreamAppendImp (const void * d, size_t s);
|
||||
//! bool binaryStreamTakeImp (void * d, size_t s);
|
||||
//! ssize_t binaryStreamSizeImp () const;
|
||||
//! \endcode
|
||||
//! \~english function binaryStreamSizeImp must return -1 if size unknown
|
||||
//! \~russian функция binaryStreamSizeImp должна возвращать -1 если нет информации о размере
|
||||
template<typename P>
|
||||
class PIBinaryStream {
|
||||
public:
|
||||
//! \~russian Записать данные
|
||||
bool binaryStreamAppend(const void * d, size_t s) {
|
||||
if (!static_cast<P*>(this)->binaryStreamAppendImp(d, s)) {
|
||||
return false;
|
||||
printf("[PIBinaryStream] binaryStreamAppend() error\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//! \~russian Прочитать данные
|
||||
bool binaryStreamTake(void * d, size_t s) {
|
||||
if (!static_cast<P*>(this)->binaryStreamTakeImp(d, s)) {
|
||||
return false;
|
||||
printf("[PIBinaryStream] binaryStreamTake() error\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//! \~russian Узнать оставшийся размер
|
||||
//!\~\details
|
||||
//!\~russian возвращает -1 если нет информации о размере
|
||||
ssize_t binaryStreamSize() const {
|
||||
return static_cast<P*>(this)->binaryStreamSizeImp();
|
||||
}
|
||||
|
||||
//! \~russian Записать данные
|
||||
template<typename T>
|
||||
void binaryStreamAppend(T v) {binaryStreamAppend(&v, sizeof(v));}
|
||||
|
||||
//! \~russian Прочитать int
|
||||
int binaryStreamTakeInt() {
|
||||
int r = 0;
|
||||
binaryStreamTake(&r, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// helper class to detect default operators
|
||||
template<typename P>
|
||||
class PIBinaryStreamTrivialRef {
|
||||
public:
|
||||
PIBinaryStreamTrivialRef(PIBinaryStream<P> & s): p(s) {}
|
||||
PIBinaryStream<P> & p;
|
||||
};
|
||||
|
||||
|
||||
template<typename P, typename T> inline PIBinaryStream<P> & operator <<(PIBinaryStreamTrivialRef<P> s, const T & v) {
|
||||
s.p << v;
|
||||
return s.p;
|
||||
}
|
||||
template<typename P, typename T> inline PIBinaryStream<P> & operator >>(PIBinaryStreamTrivialRef<P> s, T & v) {
|
||||
s.p >> v;
|
||||
return s.p;
|
||||
}
|
||||
|
||||
|
||||
// specify types
|
||||
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const bool v) {
|
||||
s.binaryStreamAppend((uchar)v);
|
||||
return s;
|
||||
}
|
||||
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, bool & v) {
|
||||
uchar c;
|
||||
s.binaryStreamTake(&c, sizeof(c));
|
||||
v = c;
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMemoryBlock v) {
|
||||
s.binaryStreamAppend(v.data(), v.size());
|
||||
return s;
|
||||
}
|
||||
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMemoryBlock v) {
|
||||
s.binaryStreamTake(v.data(), v.size());
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// store simple types
|
||||
|
||||
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v) {
|
||||
//piCout << "<< enum";
|
||||
s.binaryStreamAppend((int)v);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStreamTrivialRef<P> operator <<(PIBinaryStream<P> & s, const T & v) {
|
||||
s.binaryStreamAppend(&v, sizeof(v));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Store operator for PIVector of any trivial copyable type
|
||||
//! \~russian Оператор сохранения для PIVector тривиальных типов
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
|
||||
//piCout << "<< vector trivial default";
|
||||
s.binaryStreamAppend((int)v.size());
|
||||
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
|
||||
return s;
|
||||
}
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
|
||||
//piCout << "<< vector trivial custom";
|
||||
s.binaryStreamAppend((int)v.size());
|
||||
for (size_t i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Store operator for PIDeque of any trivial copyable type
|
||||
//! \~russian Оператор сохранения для PIDeque тривиальных типов
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
|
||||
//piCout << "<< deque trivial default";
|
||||
s.binaryStreamAppend((int)v.size());
|
||||
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
|
||||
return s;
|
||||
}
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
|
||||
//piCout << "<< deque trivial custom";
|
||||
s.binaryStreamAppend((int)v.size());
|
||||
for (size_t i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Store operator for PIVector2D of any trivial copyable type
|
||||
//! \~russian Оператор сохранения для PIVector2D тривиальных типов
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
|
||||
//piCout << "<< vector2d trivial default";
|
||||
s.binaryStreamAppend((int)v.rows());
|
||||
s.binaryStreamAppend((int)v.cols());
|
||||
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
|
||||
return s;
|
||||
}
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
|
||||
//piCout << "<< vector2d trivial custom";
|
||||
s.binaryStreamAppend((int)v.rows());
|
||||
s.binaryStreamAppend((int)v.cols());
|
||||
s << v.toPlainVector();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
template<typename P>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
|
||||
|
||||
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
template<typename P, typename Type0, typename Type1>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
|
||||
|
||||
|
||||
|
||||
|
||||
// restore simple types
|
||||
|
||||
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v) {
|
||||
//piCout << ">> enum";
|
||||
v = (T)s.binaryStreamTakeInt();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStreamTrivialRef<P> operator >>(PIBinaryStream<P> & s, T & v) {
|
||||
if (!s.binaryStreamTake(&v, sizeof(v))) {
|
||||
printf("error with %s\n", __PIP_TYPENAME__(T));
|
||||
assert(false);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Restore operator for PIVector of any trivial copyable type
|
||||
//! \~russian Оператор извлечения для PIVector тривиальных типов
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
|
||||
//piCout << ">> vector trivial default";
|
||||
int sz = s.binaryStreamTakeInt();
|
||||
v._resizeRaw(sz);
|
||||
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
|
||||
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(false);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
|
||||
//piCout << ">> vector trivial custom";
|
||||
int sz = s.binaryStreamTakeInt();
|
||||
v._resizeRaw(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Restore operator for PIDeque of any trivial copyable type
|
||||
//! \~russian Оператор извлечения для PIDeque тривиальных типов
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
|
||||
//piCout << ">> deque trivial default";
|
||||
int sz = s.binaryStreamTakeInt();
|
||||
v._resizeRaw(sz);
|
||||
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
|
||||
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(false);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
|
||||
//piCout << ">> deque trivial custom";
|
||||
int sz = s.binaryStreamTakeInt();
|
||||
v._resizeRaw(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Restore operator for PIVector2D of any trivial copyable type
|
||||
//! \~russian Оператор извлечения для PIVector2D тривиальных типов
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
|
||||
//piCout << ">> vector2d trivial default";
|
||||
int r, c;
|
||||
r = s.binaryStreamTakeInt();
|
||||
c = s.binaryStreamTakeInt();
|
||||
v._resizeRaw(r, c);
|
||||
if (!s.binaryStreamTake(v.data(), v.size() * sizeof(T))) {
|
||||
printf("error with PIVector2D<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(false);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename P, typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
|
||||
//piCout << ">> vector2d trivial custom";
|
||||
int r, c;
|
||||
PIVector<T> tmp;
|
||||
r = s.binaryStreamTakeInt();
|
||||
c = s.binaryStreamTakeInt();
|
||||
s >> tmp;
|
||||
v = PIVector2D<T>(r, c, tmp);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
template<typename P>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIBitArray & v) {s >> v.size_ >> v.data_; return s;}
|
||||
|
||||
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
template<typename P, typename Type0, typename Type1>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
|
||||
|
||||
|
||||
|
||||
|
||||
// store complex types
|
||||
|
||||
|
||||
//! \~english Store operator for PIVector of any compound type
|
||||
//! \~russian Оператор сохранения для PIVector сложных типов
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
|
||||
//piCout << "<< vector complex";
|
||||
s.binaryStreamAppend(int(v.size_s()));
|
||||
for (size_t i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Store operator for PIDeque of any compound type
|
||||
//! \~russian Оператор сохранения для PIDeque сложных типов
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
|
||||
//piCout << "<< deque complex";
|
||||
s.binaryStreamAppend(int(v.size_s()));
|
||||
for (size_t i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Store operator for PIVector2D of any compound type
|
||||
//! \~russian Оператор сохранения для PIVector2D сложных типов
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
|
||||
//piCout << "<< vector2d complex";
|
||||
s.binaryStreamAppend(int(v.rows()));
|
||||
s.binaryStreamAppend(int(v.cols()));
|
||||
s << v.toPlainVector();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// restore complex types
|
||||
|
||||
|
||||
//! \~english Restore operator for PIVector of any compound type
|
||||
//! \~russian Оператор извлечения для PIVector сложных типов
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
|
||||
//piCout << ">> vector complex";
|
||||
/*if (s.size_s() < 4) {
|
||||
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}*/
|
||||
v.resize(s.binaryStreamTakeInt());
|
||||
for (size_t i = 0; i < v.size(); ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Restore operator for PIDeque of any compound type
|
||||
//! \~russian Оператор извлечения для PIDeque сложных типов
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
|
||||
//piCout << ">> deque complex";
|
||||
/*if (s.size_s() < 4) {
|
||||
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}*/
|
||||
v.resize(s.binaryStreamTakeInt());
|
||||
for (size_t i = 0; i < v.size(); ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Restore operator for PIVector2D of any compound type
|
||||
//! \~russian Оператор извлечения для PIVector2D сложных типов
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
|
||||
//piCout << ">> vector2d complex";
|
||||
/*if (s.size_s() < 8) {
|
||||
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 8);
|
||||
}*/
|
||||
int r, c;
|
||||
PIVector<T> tmp;
|
||||
r = s.binaryStreamTakeInt();
|
||||
c = s.binaryStreamTakeInt();
|
||||
s >> tmp;
|
||||
v = PIVector2D<T>(r, c, tmp);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// other types
|
||||
|
||||
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
template <typename P, typename Key, typename T>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMap<Key, T> & v) {
|
||||
s.binaryStreamAppend((int)v.pim_index.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) {
|
||||
s.binaryStreamAppend((int)v.pim_index[i].index);
|
||||
s << v.pim_index[i].key;
|
||||
}
|
||||
s << v.pim_content;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
template <typename P, typename Key, typename T>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMap<Key, T> & v) {
|
||||
/*if (s.size_s() < 4) {
|
||||
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}*/
|
||||
int sz = s.binaryStreamTakeInt(); v.pim_index.resize(sz);
|
||||
int ind = 0;
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
ind = s.binaryStreamTakeInt();
|
||||
s >> v.pim_index[i].key;
|
||||
v.pim_index[i].index = ind;
|
||||
}
|
||||
s >> v.pim_content;
|
||||
if (v.pim_content.size_s() != v.pim_index.size_s()) {
|
||||
piCout << "Warning: loaded invalid PIMap, clear";
|
||||
v.clear();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// non-defined complex types
|
||||
|
||||
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & ) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "[PIBinaryStream] Error: using undeclared operator << for complex type!");
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & ) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "[PIBinaryStream] Error: using undeclared operator >> for complex type!");
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -28,8 +28,10 @@
|
||||
#include "pivector.h"
|
||||
|
||||
class PIP_EXPORT PIBitArray {
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIBitArray & v);
|
||||
template <typename P>
|
||||
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIBitArray & v);
|
||||
template <typename P>
|
||||
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIBitArray & v);
|
||||
public:
|
||||
PIBitArray(const int & size = 0) {resize(size);}
|
||||
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
|
||||
|
||||
@@ -28,14 +28,14 @@
|
||||
//! It can be constructed from any data and size.
|
||||
//! You can use %PIByteArray as binary stream
|
||||
//! to serialize/deserialize any objects and data.
|
||||
//! This class based on PIDeque<uchar> and provide some handle function
|
||||
//! This class use PIDeque<uchar> and provide some handle function
|
||||
//! to manipulate it.
|
||||
//! \~russian
|
||||
//! %PIByteArray используется для хранения байтов.
|
||||
//! Он может быть сконструирован из любых даных.
|
||||
//! Можно использовать %PIByteArray как потоковый объект
|
||||
//! для сериализации/десериализации любых типов и данных.
|
||||
//! Этот класс наследован от PIDeque<uchar> и предоставляет набор
|
||||
//! Этот класс использует PIDeque<uchar> и предоставляет набор
|
||||
//! удобных методов для работы с байтами.
|
||||
//!
|
||||
//! \~english \section PIByteArray_sec0 Usage
|
||||
@@ -438,38 +438,3 @@ std::ostream &operator <<(std::ostream & s, const PIByteArray & ba) {
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {
|
||||
if (s.size_s() < 4) {
|
||||
s.clear();
|
||||
v.clear();
|
||||
return s;
|
||||
}
|
||||
assert(s.size_s() >= 4);
|
||||
int sz = 0;
|
||||
s >> sz;
|
||||
if (sz > s.size_s()) {
|
||||
piCout << "[PIByteArray] Warning: operator >> wants too much data, discard!" << sz << s.size_s();
|
||||
s.clear();
|
||||
v.clear();
|
||||
return s;
|
||||
}
|
||||
v.resize(sz);
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), sz);
|
||||
s.remove(0, sz);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {
|
||||
s << int(v.size_s());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s());
|
||||
memcpy(s.data(os), v.data(), v.size());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -27,9 +27,7 @@
|
||||
#define PIBYTEARRAY_H
|
||||
|
||||
#include "pichar.h"
|
||||
#include "pibitarray.h"
|
||||
#include "pimap.h"
|
||||
#include "pivector2d.h"
|
||||
#include "pibinarystream.h"
|
||||
#include <stdio.h>
|
||||
|
||||
class PIString;
|
||||
@@ -40,23 +38,24 @@ class PIByteArray;
|
||||
//! \~\brief
|
||||
//! \~english The %PIByteArray class provides an array of bytes.
|
||||
//! \~russian Класс %PIByteArray представляет собой массив байтов.
|
||||
class PIP_EXPORT PIByteArray: public PIDeque<uchar>
|
||||
class PIP_EXPORT PIByteArray: public PIBinaryStream<PIByteArray>
|
||||
{
|
||||
public:
|
||||
typedef ::PIMemoryBlock RawData DEPRECATEDM("use PIMemoryBlock instead");
|
||||
|
||||
//! \~english Constructs an empty byte array
|
||||
//! \~russian Создает пустой байтовый массив
|
||||
PIByteArray() {;}
|
||||
PIByteArray() {}
|
||||
|
||||
//! \~english Constructs copy of byte array "o"
|
||||
//! \~russian Создает копию байтового массива "o"
|
||||
PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {}
|
||||
PIByteArray(const PIByteArray & o): d(o.d) {}
|
||||
|
||||
//! \~english Constructs copy of byte array "o"
|
||||
//! \~russian Создает копию байтового массива "o"
|
||||
PIByteArray(const PIDeque<uchar> & o): PIDeque<uchar>(o) {}
|
||||
PIByteArray(const PIDeque<uchar> & o): d(o) {}
|
||||
|
||||
PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {}
|
||||
PIByteArray(PIByteArray && o): d(std::move(o.d)) {}
|
||||
|
||||
//! \~english Constructs 0-filled byte array with size "size"
|
||||
//! \~russian Создает заполненный "0" байтовый массив размером "size"
|
||||
@@ -64,42 +63,989 @@ public:
|
||||
|
||||
//! \~english Constructs byte array from data "data" and size "size"
|
||||
//! \~russian Создает байтовый массив из данных по указателю "data" размером "size"
|
||||
PIByteArray(const void * data, const uint size): PIDeque<uchar>((const uchar*)data, size_t(size)) {}
|
||||
PIByteArray(const void * data, const uint size): d((const uchar*)data, size_t(size)) {}
|
||||
|
||||
//! \~english Constructs byte array with size "size" filled by "t"
|
||||
//! \~russian Создает заполненный "t" байтовый массив размером "size"
|
||||
PIByteArray(const uint size, uchar t): PIDeque<uchar>(size, t) {}
|
||||
PIByteArray(const uint size, uchar t): d(size, t) {}
|
||||
|
||||
//! \~english Contructs array from
|
||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~russian Создает массив из
|
||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIByteArray v{1,2,3};
|
||||
//! piCout << v; // {1, 2, 3}
|
||||
//! \endcode
|
||||
PIByteArray(std::initializer_list<uchar> init_list) : d(init_list) {}
|
||||
|
||||
//! \~english Help struct to store/restore custom blocks of data to/from PIByteArray
|
||||
//! \~russian Вспомогательная структура для сохранения/извлечения произвольного блока данных в/из байтового массива
|
||||
struct RawData {
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
|
||||
public:
|
||||
//! \~english Constructs data block
|
||||
//! \~russian Создает блок данных
|
||||
RawData(void * data = 0, int size = 0) {d = data; s = size;}
|
||||
RawData(const RawData & o) {d = o.d; s = o.s;}
|
||||
//! \~english Constructs data block
|
||||
//! \~russian Создает блок данных
|
||||
RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;}
|
||||
RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
|
||||
private:
|
||||
void * d;
|
||||
int s;
|
||||
};
|
||||
//! \~english Swaps array `v` other with this array.
|
||||
//! \~russian Меняет местами массив `v` с этим массивом.
|
||||
//! \~\details
|
||||
//! \~english This operation is very fast and never fails.
|
||||
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
|
||||
inline void swap(PIByteArray & other) {
|
||||
d.swap(other.d);
|
||||
}
|
||||
|
||||
//! \~english Iterator to the first element.
|
||||
//! \~russian Итератор на первый элемент.
|
||||
//! \~\details 
|
||||
//!
|
||||
//! \~english If the array is empty, the returned iterator is equal to \a end().
|
||||
//! \~russian Если массив - пуст, возвращаемый итератор будет равен \a end().
|
||||
//! \~\return \ref stl_iterators
|
||||
//! \~\sa \a end(), \a rbegin(), \a rend()
|
||||
inline PIDeque<uchar>::iterator begin() {return d.begin();}
|
||||
|
||||
//! \~english Iterator to the element following the last element.
|
||||
//! \~russian Итератор на элемент, следующий за последним элементом.
|
||||
//! \~\details 
|
||||
//!
|
||||
//! \~english This element acts as a placeholder;
|
||||
//! attempting to access it results in undefined behavior.
|
||||
//! \~russian Этот элемент существует лишь условно,
|
||||
//! попытка доступа к нему приведёт к выходу за разрешенную память.
|
||||
//! \~\return \ref stl_iterators
|
||||
//! \~\sa \a begin(), \a rbegin(), \a rend()
|
||||
inline PIDeque<uchar>::iterator end() {return d.end();}
|
||||
|
||||
inline PIDeque<uchar>::const_iterator begin() const {return d.begin();}
|
||||
inline PIDeque<uchar>::const_iterator end() const {return d.end();}
|
||||
|
||||
//! \~english Returns a reverse iterator to the first element of the reversed array.
|
||||
//! \~russian Обратный итератор на первый элемент.
|
||||
//! \~\details 
|
||||
//!
|
||||
//! \~english It corresponds to the last element of the non-reversed array.
|
||||
//! If the array is empty, the returned iterator is equal to \a rend().
|
||||
//! \~russian Итератор для прохода массива в обратном порядке.
|
||||
//! Указывает на последний элемент.
|
||||
//! Если массив пустой, то совпадает с итератором \a rend().
|
||||
//! \~\return \ref stl_iterators
|
||||
//! \~\sa \a rend(), \a begin(), \a end()
|
||||
inline PIDeque<uchar>::reverse_iterator rbegin() {return d.rbegin();}
|
||||
|
||||
//! \~english Returns a reverse iterator to the element.
|
||||
//! following the last element of the reversed array.
|
||||
//! \~russian Обратный итератор на элемент, следующий за последним элементом.
|
||||
//! \~\details 
|
||||
//!
|
||||
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
|
||||
//! This element acts as a placeholder, attempting to access it results in undefined behavior.
|
||||
//! \~russian Итератор для прохода массива в обратном порядке.
|
||||
//! Указывает на элемент, предшествующий первому элементу.
|
||||
//! Этот элемент существует лишь условно,
|
||||
//! попытка доступа к нему приведёт к выходу за разрешенную память.
|
||||
//! \~\return \ref stl_iterators
|
||||
//! \~\sa \a rbegin(), \a begin(), \a end()
|
||||
inline PIDeque<uchar>::reverse_iterator rend() {return d.rend();}
|
||||
|
||||
inline PIDeque<uchar>::const_reverse_iterator rbegin() const {return d.rbegin();}
|
||||
inline PIDeque<uchar>::const_reverse_iterator rend() const {return d.rend();}
|
||||
|
||||
//! \~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 d.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 d.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 d.length();}
|
||||
|
||||
//! \~english Number of elements that the container has currently allocated space for.
|
||||
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
|
||||
//! \~\details
|
||||
//! \~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 d.capacity();}
|
||||
|
||||
//! \~english Checks if the container has no elements.
|
||||
//! \~russian Проверяет пуст ли массив.
|
||||
//! \~\return
|
||||
//! \~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 d.isEmpty();}
|
||||
|
||||
//! \~english Checks if the container has elements.
|
||||
//! \~russian Проверяет не пуст ли массив.
|
||||
//! \~\return
|
||||
//! \~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 d.isNotEmpty();}
|
||||
|
||||
//! \~english Tests whether at least one element in the array
|
||||
//! passes the test implemented by the provided function `test`.
|
||||
//! \~russian Проверяет, удовлетворяет ли какой-либо элемент массива условию,
|
||||
//! заданному в передаваемой функции `test`.
|
||||
//! \~\return
|
||||
//! \~english **true** if, in the array,
|
||||
//! it finds an element for which the provided function returns **true**;
|
||||
//! otherwise it returns **false**. Always returns **false** if is empty.
|
||||
//! \~russian **true** если хотя бы для одного элемента
|
||||
//! передаваемая функция возвращает **true**, в остальных случаях **false**.
|
||||
//! Метод возвращает **false** при любом условии для пустого массива.
|
||||
//! \~\details
|
||||
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
|
||||
inline bool any(std::function<bool(uchar e)> test) const {
|
||||
return d.any(test);
|
||||
}
|
||||
|
||||
//! \~english Tests whether all elements in the array passes the test
|
||||
//! implemented by the provided function `test`.
|
||||
//! \~russian Проверяет, удовлетворяют ли все элементы массива условию,
|
||||
//! заданному в передаваемой функции `test`.
|
||||
//! \~\return
|
||||
//! \~english **true** if, in the array,
|
||||
//! it finds an element for which the provided function returns **true**;
|
||||
//! otherwise it returns **false**. Always returns **true** if is empty.
|
||||
//! \~russian **true** если для всех элементов передаваемая функция возвращает **true**,
|
||||
//! в остальных случаях **false**.
|
||||
//! Метод возвращает **true** при любом условии для пустого массива.
|
||||
//! \~\details
|
||||
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
|
||||
inline bool every(std::function<bool(uchar e)> test) const {
|
||||
return d.every(test);
|
||||
}
|
||||
|
||||
//! \~english Full access to element by `index`.
|
||||
//! \~russian Полный доступ к элементу по индексу `index`.
|
||||
//! \~\details
|
||||
//! \~english Element index starts from `0`.
|
||||
//! Element index must be in range from `0` to `size()-1`.
|
||||
//! Otherwise will be undefined behavior.
|
||||
//! \~russian Индекс элемента считается от `0`.
|
||||
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
|
||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||
//! \~\sa \a at()
|
||||
inline uchar & operator [](size_t index) {return d[index];}
|
||||
inline uchar operator [](size_t index) const {return d[index];}
|
||||
|
||||
//! \~english Read only access to element by `index`.
|
||||
//! \~russian Доступ исключительно на чтение к элементу по индексу `index`.
|
||||
//! \~\details
|
||||
//! \~english Element index starts from `0`.
|
||||
//! Element index must be in range from `0` to `size()-1`.
|
||||
//! Otherwise will be undefined behavior.
|
||||
//! \~russian Индекс элемента считается от `0`.
|
||||
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
|
||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||
inline uchar at(size_t index) const {return d.at(index);}
|
||||
|
||||
//! \~english Last element.
|
||||
//! \~russian Последний элемент массива.
|
||||
//! \~\details
|
||||
//! \~english Returns a reference to the last item in the array.
|
||||
//! This function assumes that the array isn't empty.
|
||||
//! Otherwise will be undefined behavior.
|
||||
//! \~russian Возвращает ссылку на последний элемент в массиве.
|
||||
//! Эта функция предполагает, что массив не пустой.
|
||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||
inline uchar & back() {return d.back();}
|
||||
inline uchar back() const {return d.back();}
|
||||
|
||||
//! \~english Last element.
|
||||
//! \~russian Первый элемент массива.
|
||||
//! \~\details
|
||||
//! \~english Returns a reference to the last item in the array.
|
||||
//! This function assumes that the array isn't empty.
|
||||
//! Otherwise will be undefined behavior.
|
||||
//! \~russian Возвращает ссылку на пенрвый элемент в массиве.
|
||||
//! Эта функция предполагает, что массив не пустой.
|
||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||
inline uchar & front() {return d.front();}
|
||||
inline uchar front() const {return d.front();}
|
||||
|
||||
//! \~english Tests if element `e` exists in the array.
|
||||
//! \~russian Проверяет наличие элемента `e` в массиве.
|
||||
//! \~\details
|
||||
//! \~english Optional argument `start` - the position in this array at which to begin searching.
|
||||
//! If the index is greater than or equal to the array's size,
|
||||
//! **false** is returned, which means the array will not be searched.
|
||||
//! If the provided index value is a negative number,
|
||||
//! it is taken as the offset from the end of the array.
|
||||
//! Note: if the provided index is negative,
|
||||
//! the array is still searched from front to back.
|
||||
//! Default: 0 (entire array is searched).
|
||||
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
|
||||
//! Если индекс больше или равен длине массива,
|
||||
//! возвращается **false**, что означает, что массив даже не просматривается.
|
||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||
//! \~\code
|
||||
//! PIByteArray v{1, 2, 3, 4};
|
||||
//! piCout << v.contains(3); // true
|
||||
//! piCout << v.contains(5); // false
|
||||
//! piCout << v.contains(3, 3); // false
|
||||
//! piCout << v.contains(3, -2); // true
|
||||
//! piCout << v.contains(3, -99); // true
|
||||
//! \endcode
|
||||
//! \~\return
|
||||
//! \~english **true** if the array contains an occurrence of element `e`,
|
||||
//! otherwise it returns **false**.
|
||||
//! \~russian **true** если элемент `e` присутствует в массиве,
|
||||
//! в остальных случаях **false**.
|
||||
//! \~\sa \a every(), \a any(), \a entries()
|
||||
inline bool contains(uchar e, ssize_t start = 0) const {
|
||||
return d.contains(e, start);
|
||||
}
|
||||
|
||||
//! \~english Count elements equal `e` in the array.
|
||||
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
|
||||
//! \~\details
|
||||
//! \~english Optional argument `start` - the position in this array at which to begin searching.
|
||||
//! If the index is greater than or equal to the array's size,
|
||||
//! 0 is returned, which means the array will not be searched.
|
||||
//! If the provided index value is a negative number,
|
||||
//! it is taken as the offset from the end of the array.
|
||||
//! Note: if the provided index is negative,
|
||||
//! the array is still searched from front to back.
|
||||
//! Default: 0 (entire array is searched).
|
||||
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
|
||||
//! Если индекс больше или равен длине массива,
|
||||
//! возвращается 0, что означает, что массив даже не просматривается.
|
||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||
//! \~\sa \a every(), \a any(), \a contains(), \a indexOf()
|
||||
inline int entries(uchar e, ssize_t start = 0) const {
|
||||
return d.entries(e, start);
|
||||
}
|
||||
|
||||
//! \~english Count elements in the array passes the test implemented by the provided function `test`.
|
||||
//! \~russian Подсчитывает количество элементов в массиве,
|
||||
//! проходящих по условию, заданному в передаваемой функции `test`.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! Optional argument `start` - the position in this array at which to begin searching.
|
||||
//! If the index is greater than or equal to the array's size,
|
||||
//! 0 is returned, which means the array will not be searched.
|
||||
//! If the provided index value is a negative number,
|
||||
//! it is taken as the offset from the end of the array.
|
||||
//! Note: if the provided index is negative,
|
||||
//! the array is still searched from front to back.
|
||||
//! Default: 0 (entire array is searched).
|
||||
//! \~russian Перегруженная функция.
|
||||
//! Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
|
||||
//! Если индекс больше или равен длине массива,
|
||||
//! возвращается 0, что означает, что массив даже не просматривается.
|
||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||
//! \~\sa \a every(), \a any(), \a contains(), \a indexWhere()
|
||||
inline int entries(std::function<bool(uchar e)> test, ssize_t start = 0) const {
|
||||
return d.entries(test, start);
|
||||
}
|
||||
|
||||
//! \~english Returns the first index at which a given element `e`
|
||||
//! can be found in the array, or `-1` if it is not present.
|
||||
//! \~russian Возвращает первый индекс, по которому данный элемент `e`
|
||||
//! может быть найден в массиве или `-1`, если такого индекса нет.
|
||||
//! \~\details
|
||||
//! \~english Optional argument `start` - the position in this array at which to begin searching.
|
||||
//! If the index is greater than or equal to the array's size,
|
||||
//! `-1` is returned, which means the array will not be searched.
|
||||
//! If the provided index value is a negative number,
|
||||
//! it is taken as the offset from the end of the array.
|
||||
//! Note: if the provided index is negative,
|
||||
//! the array is still searched from front to back.
|
||||
//! Default: 0 (entire array is searched).
|
||||
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
|
||||
//! Если индекс больше или равен длине массива,
|
||||
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||
//! \~\code
|
||||
//! PIByteArray v{2, 5, 9};
|
||||
//! piCout << v.indexOf(2); // 0
|
||||
//! piCout << v.indexOf(7); // -1
|
||||
//! piCout << v.indexOf(9, 2); // 2
|
||||
//! piCout << v.indexOf(2, -1); // -1
|
||||
//! piCout << v.indexOf(2, -3); // 0
|
||||
//! \endcode
|
||||
//! \~\sa \a indexWhere(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
||||
inline ssize_t indexOf(const uchar & e, ssize_t start = 0) const {
|
||||
return d.indexOf(e, start);
|
||||
}
|
||||
|
||||
//! \~english Returns the first index passes the test implemented by the provided function `test`,
|
||||
//! or `-1` if it is not present.
|
||||
//! can be found in the array, or `-1` if it is not present.
|
||||
//! \~russian Возвращает первый индекс элемента проходящего по условию,
|
||||
//! заданному в передаваемой функции `test`, или `-1`, если таких элементов нет.
|
||||
//! \~\details
|
||||
//! \~english Optional argument `start` - the position in this array at which to begin searching.
|
||||
//! If the index is greater than or equal to the array's size,
|
||||
//! `-1` is returned, which means the array will not be searched.
|
||||
//! If the provided index value is a negative number,
|
||||
//! it is taken as the offset from the end of the array.
|
||||
//! Note: if the provided index is negative,
|
||||
//! the array is still searched from front to back.
|
||||
//! Default: 0 (entire array is searched).
|
||||
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
|
||||
//! Если индекс больше или равен длине массива,
|
||||
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||
//! \~\code
|
||||
//! PIByteArray v{2, 5, 9};
|
||||
//! piCout << v.indexWhere([](const uchar & s){return s > 3;}); // 1
|
||||
//! piCout << v.indexWhere([](const uchar & s){return s > 3;}, 2); // 2
|
||||
//! piCout << v.indexWhere([](const uchar & s){return s > 10;}); // -1
|
||||
//! \endcode
|
||||
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
||||
inline ssize_t indexWhere(std::function<bool(const uchar & e)> test, ssize_t start = 0) const {
|
||||
return d.indexWhere(test, start);
|
||||
}
|
||||
|
||||
//! \~english Returns the last index at which a given element `e`
|
||||
//! can be found in the array, or `-1` if it is not present.
|
||||
//! \~russian Возвращает последний индекс, по которому данный элемент `e`
|
||||
//! может быть найден в массиве или `-1`, если такого индекса нет.
|
||||
//! \~\details
|
||||
//! \~english Optional argument `start` - the position in this array
|
||||
//! at which to start searching backwards.
|
||||
//! If the index is greater than or equal to the array's size,
|
||||
//! causes the whole array to be searched.
|
||||
//! If the provided index value is a negative number,
|
||||
//! it is taken as the offset from the end of the array.
|
||||
//! Therefore, if calculated index less than 0,
|
||||
//! the array is not searched, and the method returns `-1`.
|
||||
//! Note: if the provided index is negative,
|
||||
//! the array is still searched from back to front.
|
||||
//! Default: -1 (entire array is searched).
|
||||
//! \~russian Опциональный аргумент `start` указывает на индекс
|
||||
//! c которого начинать поиск в обратном направлении.
|
||||
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
|
||||
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
||||
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
||||
//! и означает, что просматривается весь массив.
|
||||
//! \~\code
|
||||
//! PIByteArray v{2, 5, 9, 2};
|
||||
//! piCout << v.lastIndexOf(2); // 3
|
||||
//! piCout << v.lastIndexOf(7); // -1
|
||||
//! piCout << v.lastIndexOf(2, 2); // 0
|
||||
//! piCout << v.lastIndexOf(2, -3); // 0
|
||||
//! piCout << v.lastIndexOf(2, -300); // -1
|
||||
//! piCout << v.lastIndexOf(2, 300); // 3
|
||||
//! \endcode
|
||||
//! \~\sa \a indexOf(), \a indexWhere(), \a lastIndexWhere(), \a contains()
|
||||
inline ssize_t lastIndexOf(const uchar & e, ssize_t start = -1) const {
|
||||
return d.lastIndexOf(e, start);
|
||||
}
|
||||
|
||||
//! \~english Returns the last index passes the test implemented by the provided function `test`,
|
||||
//! or `-1` if it is not present.
|
||||
//! \~russian Возвращает последний индекс элемента проходящего по условию,
|
||||
//! заданному в передаваемой функции `test`, или `-1`, если таких элементов нет.
|
||||
//! \~\details
|
||||
//! \~english Optional argument `start` - the position in this array
|
||||
//! at which to start searching backwards.
|
||||
//! If the index is greater than or equal to the array's size,
|
||||
//! causes the whole array to be searched.
|
||||
//! If the provided index value is a negative number,
|
||||
//! it is taken as the offset from the end of the array.
|
||||
//! Therefore, if calculated index less than 0,
|
||||
//! the array is not searched, and the method returns `-1`.
|
||||
//! Note: if the provided index is negative,
|
||||
//! the array is still searched from back to front.
|
||||
//! Default: -1 (entire array is searched).
|
||||
//! \~russian Опциональный аргумент `start` указывает на индекс
|
||||
//! c которого начинать поиск в обратном направлении.
|
||||
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
|
||||
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
||||
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
||||
//! и означает, что просматривается весь массив.
|
||||
//! \~\sa \a indexOf(), \a lastIndexOf(), \a indexWhere(), \a contains()
|
||||
inline ssize_t lastIndexWhere(std::function<bool(const uchar & e)> test, ssize_t start = -1) const {
|
||||
return d.lastIndexWhere(test, start);
|
||||
}
|
||||
|
||||
//! \~english Pointer to array
|
||||
//! \~russian Указатель на память массива
|
||||
//! \~\details
|
||||
//! \~english Optional argument `index` the position in this array,
|
||||
//! where is pointer. Default: start of array.
|
||||
//! \~russian Опциональный аргумент `index` указывает на индекс c которого брать указатель.
|
||||
//! По умолчанию указывает на начало массива.
|
||||
inline uchar * data(size_t index = 0) {return d.data(index);}
|
||||
|
||||
//! \~english Read only pointer to array
|
||||
//! \~russian Указатель на память массива только для чтения.
|
||||
//! \~\details
|
||||
//! \~english The pointer can be used to access and modify the items in the array.
|
||||
//! The pointer remains valid as long as the array isn't reallocated.
|
||||
//! Optional argument `index` the position in this array,
|
||||
//! where is pointer. Default: start of array.
|
||||
//! \~russian Указатель можно использовать для доступа и изменения элементов в массиве.
|
||||
//! Указатель остается действительным только до тех пор, пока массив не будет перераспределен.
|
||||
//! Опциональный аргумент `index` указывает на индекс c которого брать указатель.
|
||||
//! По умолчанию указывает на начало массива.
|
||||
inline const uchar * data(size_t index = 0) const {return d.data(index);}
|
||||
|
||||
//! \~english Clear array, remove all elements.
|
||||
//! \~russian Очищает массив, удаляет все элементы.
|
||||
//! \~\details
|
||||
//! \~\note
|
||||
//! \~english Reserved memory will not be released.
|
||||
//! \~russian Зарезервированная память не освободится.
|
||||
//! \~\sa \a resize()
|
||||
inline PIByteArray & clear() {
|
||||
resize(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Assigns element 'e' to all items in the array.
|
||||
//! \~russian Заполняет весь массив копиями элемента 'e'.
|
||||
//! \~\details
|
||||
//! \~\sa \a resize()
|
||||
inline PIByteArray & fill(uchar e = 0) {
|
||||
d.fill(e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Assigns result of function 'f(size_t i)' to all items in the array.
|
||||
//! \~russian Заполняет весь массив результатом вызова функции 'f(size_t i)'.
|
||||
//! \~\details
|
||||
//! \~\sa \a resize()
|
||||
inline PIByteArray & fill(std::function<uchar(size_t i)> f) {
|
||||
d.fill(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Same as \a fill().
|
||||
//! \~russian Тоже самое что и \a fill().
|
||||
//! \~\sa \a fill(), \a resize()
|
||||
inline PIByteArray & assign(uchar e = 0) {return fill(e);}
|
||||
|
||||
//! \~english First does `resize(new_size)` then `fill(e)`.
|
||||
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
|
||||
//! \~\sa \a fill(), \a resize()
|
||||
inline PIByteArray & assign(size_t new_size, uchar e) {
|
||||
resize(new_size);
|
||||
return fill(e);
|
||||
}
|
||||
|
||||
//! \~english Sets size of the array, new elements are copied from `e`.
|
||||
//! \~russian Устанавливает размер массива, новые элементы копируются из `e`.
|
||||
//! \~\details
|
||||
//! \~english If `new_size` is greater than the current \a size(),
|
||||
//! elements are added to the end; the new elements are initialized from `e`.
|
||||
//! If `new_size` is less than the current \a size(), elements are removed from the end.
|
||||
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
|
||||
//! новые элементы добавляются в конец массива и создаются из `e`.
|
||||
//! Если `new_size` меньше чем текущий размер массива \a size(),
|
||||
//! лишние элементы удаляются с конца массива.
|
||||
//! \~\sa \a size(), \a clear()
|
||||
inline PIByteArray & resize(size_t new_size, uchar e = 0) {
|
||||
d.resize(new_size, e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Sets size of the array, new elements created by function `f(size_t i)`.
|
||||
//! \~russian Устанавливает размер массива, новые элементы создаются функцией `f(size_t i)`.
|
||||
//! \~\details
|
||||
//! \~english If `new_size` is greater than the current \a size(),
|
||||
//! elements are added to the end; the new elements created by function `f(size_t i)`.
|
||||
//! If `new_size` is less than the current \a size(), elements are removed from the end.
|
||||
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
|
||||
//! новые элементы добавляются в конец массива и функцией `f(size_t i)`.
|
||||
//! Если `new_size` меньше чем текущий размер массива \a size(),
|
||||
//! лишние элементы удаляются с конца массива.
|
||||
//! \~\sa \a size(), \a clear()
|
||||
inline PIByteArray & resize(size_t new_size, std::function<uchar(size_t i)> f) {
|
||||
d.resize(new_size, f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Return resized byte array
|
||||
//! \~russian Возвращает копию байтового массива с измененным размером
|
||||
PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
|
||||
PIByteArray resized(uint new_size) const {
|
||||
PIByteArray ret(new_size);
|
||||
memcpy(ret.data(), data(), new_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! \~english Attempts to allocate memory for at least `new_size` elements.
|
||||
//! \~russian Резервируется память под как минимум `new_size` элементов.
|
||||
//! \~\details
|
||||
//! \~english If you know in advance how large the array will be,
|
||||
//! you should call this function to prevent reallocations and memory fragmentation.
|
||||
//! If `new_size` is greater than the current \a capacity(),
|
||||
//! new storage is allocated, otherwise the function does nothing.
|
||||
//! This function does not change the \a size() of the array.
|
||||
//! \~russian Если вы заранее знаете, насколько велик будет массив,
|
||||
//! вы можете вызвать эту функцию, чтобы предотвратить перераспределение и фрагментацию памяти.
|
||||
//! Если размер `new_size` больше чем выделенная память \a capacity(),
|
||||
//! то произойдёт выделение новой памяти и перераспределение массива.
|
||||
//! Эта функция не изменяет количество элементов в массиве \a size().
|
||||
//! \~\sa \a size(), \a capacity(), \a resize()
|
||||
inline PIByteArray & reserve(size_t new_size) {
|
||||
d.reserve(new_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Inserts value `e` at `index` position in the array.
|
||||
//! \~russian Вставляет значение `e` в позицию `index` в массиве.
|
||||
//! \~\details
|
||||
//! \~english The index must be greater than 0 and less than or equal to \a size().
|
||||
//! \~russian Индекс должен быть больше 0 и меньше или равен \a size().
|
||||
//! \~\sa \a append(), \a prepend(), \a remove()
|
||||
inline PIByteArray & insert(size_t index, uchar e = 0) {
|
||||
d.insert(index, e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Inserts array `v` at `index` position in the array.
|
||||
//! \~russian Вставляет массив `v` в позицию `index` в массиве.
|
||||
//! \~\details
|
||||
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
|
||||
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
|
||||
//! \~\sa \a append(), \a prepend(), \a remove()
|
||||
inline PIByteArray & insert(size_t index, const PIByteArray & v) {
|
||||
d.insert(index, v.d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Inserts the given elements at `index` position in the array.
|
||||
//! \~russian Вставляет элементы в позицию `index` в массиве.
|
||||
//! \~\details
|
||||
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
|
||||
//! Inserts the given elements from
|
||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
|
||||
//! Вставляет элементы из
|
||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~\sa \a append(), \a prepend(), \a remove()
|
||||
inline PIByteArray & insert(size_t index, std::initializer_list<uchar> init_list) {
|
||||
d.insert(index, init_list);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Removes `count` elements from the middle of the array, starting at `index` position.
|
||||
//! \~russian Удаляет элементы из массива, начиная с позиции `index` в количестве `count`.
|
||||
//! \~\details
|
||||
//! \~\sa \a resize(), \a insert(), \a removeOne(), \a removeAll(), \a removeWhere()
|
||||
inline PIByteArray & remove(size_t index, size_t count = 1) {
|
||||
d.remove(index, count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Return sub-array starts from "index" and has "count" or less bytes
|
||||
//! \~russian Возвращает подмассив с данными от индекса "index" и размером не более "count"
|
||||
PIByteArray getRange(size_t index, size_t count) const {
|
||||
return PIDeque<uchar>::getRange(index, count);
|
||||
return d.getRange(index, count);
|
||||
}
|
||||
|
||||
//! \~english Reverses this array.
|
||||
//! \~russian Обращает порядок следования элементов этого массива.
|
||||
//! \~\details
|
||||
//! \~english This method reverses an array [in place](https://en.wikipedia.org/wiki/In-place_algorithm).
|
||||
//! The first array element becomes the last, and the last array element becomes the first.
|
||||
//! The reverse method transposes the elements of the calling array object in place,
|
||||
//! mutating the array, and returning a reference to the array.
|
||||
//! \~russian Метод reverse() на месте переставляет элементы массива,
|
||||
//! на котором он был вызван, изменяет массив и возвращает ссылку на него.
|
||||
//! Первый элемент массива становится последним, а последний — первым.
|
||||
//! \~\sa \a reversed()
|
||||
inline PIByteArray & reverse() {
|
||||
d.reverse();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Returns reversed array.
|
||||
//! \~russian Возвращает перевернутый массив.
|
||||
//! \~\details
|
||||
//! \~english Returns a copy of the array with elements in reverse order.
|
||||
//! The first array element becomes the last, and the last array element becomes the first.
|
||||
//! \~russian Возвращает копию массива с элементами в обратном порядке.
|
||||
//! Первый элемент массива становится последним, а последний — первым.
|
||||
//! \~\sa \a reverse()
|
||||
inline PIByteArray reversed() const {
|
||||
PIByteArray ret(*this);
|
||||
return ret.reverse();
|
||||
}
|
||||
|
||||
//! \~english Increases or decreases the size of the array by `add_size` elements.
|
||||
//! \~russian Увеличивает или уменьшает размер массива на `add_size` элементов.
|
||||
//! \~\details
|
||||
//! \~english If `add_size > 0` then elements are added to the end of the array.
|
||||
//! If `add_size < 0` then elements are removed from the end of the array.
|
||||
//! If `add_size < 0` and there are fewer elements in the array than specified, then the array becomes empty.
|
||||
//! \~russian Если `add_size > 0`, то в конец массива добавляются элементы.
|
||||
//! Если `add_size < 0`, то с конца массива удаляются элементы.
|
||||
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
|
||||
//! \~\sa \a resize()
|
||||
inline PIByteArray & enlarge(ssize_t add_size, uchar e = 0) {
|
||||
d.enlarge(add_size, e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Remove no more than one element equal `e`.
|
||||
//! \~russian Удаляет первый элемент, который равен элементу `e`.
|
||||
//! \~\details
|
||||
//! \~\sa \a remove(), \a removeAll(), \a removeWhere()
|
||||
inline PIByteArray & removeOne(uchar e) {
|
||||
d.removeOne(e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Remove all elements equal `e`.
|
||||
//! \~russian Удаляет все элементы, равные элементу `e`.
|
||||
//! \~\details
|
||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||
inline PIByteArray & removeAll(uchar e) {
|
||||
d.removeAll(e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Remove all elements in the array
|
||||
//! passes the test implemented by the provided function `test`.
|
||||
//! \~russian Удаляет все элементы, удовлетворяющие условию,
|
||||
//! заданному в передаваемой функции `test`.
|
||||
//! \~\details
|
||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||
inline PIByteArray & removeWhere(std::function<bool(uchar e)> test) {
|
||||
d.removeWhere(test);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given element `e` to the end of the array.
|
||||
//! \~russian Добавляет элемент `e` в конец массива.
|
||||
//! \~\details
|
||||
//! \~english If size() is less than capacity(), which is most often
|
||||
//! then the addition will be very fast.
|
||||
//! In any case, the addition is fast and does not depend on the size of the array.
|
||||
//! If the new size() is greater than capacity()
|
||||
//! then all iterators and references
|
||||
//! (including the past-the-end iterator) are invalidated.
|
||||
//! Otherwise only the past-the-end iterator is invalidated.
|
||||
//! \~russian Если size() меньше capacity(), что часто бывает,
|
||||
//! то добавление будет очень быстрым.
|
||||
//! В любом случае добавление быстрое и не зависит от размера массива.
|
||||
//! Если новый size() больше, чем capacity(),
|
||||
//! то все итераторы и указатели становятся нерабочими.
|
||||
//! В противном случае все, кроме итераторов, указывающих на конец массива,
|
||||
//! остаются в рабочем состоянии.
|
||||
//! \~\sa \a push_front(), \a append(), \a prepend(), \a insert()
|
||||
inline PIByteArray & push_back(uchar e) {
|
||||
d.push_back(e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given elements to the end of the array.
|
||||
//! \~russian Добавляет элементы в конец массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! Appends the given elements from
|
||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~russian Перегруженая функция.
|
||||
//! Добавляет элементы из
|
||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~\sa \a push_back()
|
||||
inline PIByteArray & push_back(std::initializer_list<uchar> init_list) {
|
||||
d.push_back(init_list);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given array `v` to the end of the array.
|
||||
//! \~russian Добавляет массив `v` в конец массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! \~russian Перегруженая функция.
|
||||
//! \~\sa \a push_back()
|
||||
inline PIByteArray & push_back(const PIByteArray & v) {
|
||||
d.push_back(v.d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//! \~english Add to the end data "data" with size "size"
|
||||
//! \~russian Добавляет в конец массива данные по указателю "data" размером "size"
|
||||
PIByteArray & push_back(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
|
||||
|
||||
//! \~english Appends the given element `e` to the begin of the array.
|
||||
//! \~russian Добавляет элемент `e` в начало массива.
|
||||
//! \~\details
|
||||
//! \~english If there is free space at the beginning of the array,
|
||||
//! which is most often, then the addition will be very fast.
|
||||
//! In any case, the addition is fast and does not depend on the size of the array.
|
||||
//! If there is no free space at the beginning of the array
|
||||
//! then all iterators and references
|
||||
//! (including the past-the-begin iterator) are invalidated.
|
||||
//! Otherwise only the past-the-begin iterator is invalidated.
|
||||
//! \~russian Если в начале массива имеется свободное место,
|
||||
//! что часто бывает, то добавление будет очень быстрым.
|
||||
//! В любом случае добавление быстрое и не зависит от размера массива.
|
||||
//! Если в начале массива нет свободного места,
|
||||
//! то все итераторы и указатели становятся нерабочими.
|
||||
//! В противном случае все, кроме итераторов указывающих, на начало массива,
|
||||
//! остаются в рабочем состоянии.
|
||||
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
|
||||
inline PIByteArray & push_front(uchar e) {
|
||||
d.push_front(e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given array `v` to the begin of the array.
|
||||
//! \~russian Добавляет массив `v` в начало массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! \~russian Перегруженая функция.
|
||||
//! \~\sa \a push_front()
|
||||
inline PIByteArray & push_front(const PIByteArray & v) {
|
||||
d.push_front(v.d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given elements to the begin of the array.
|
||||
//! \~russian Добавляет элементы в начало массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! Appends the given elements from
|
||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~russian Перегруженая функция.
|
||||
//! Добавляет элементы из
|
||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~\sa \a append()
|
||||
inline PIByteArray & push_front(std::initializer_list<uchar> init_list) {
|
||||
d.push_front(init_list);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given element `e` to the begin of the array.
|
||||
//! \~russian Добавляет элемент `e` в начало массива.
|
||||
//! \~\details
|
||||
//! \~english If there is free space at the beginning of the array,
|
||||
//! which is most often, then the addition will be very fast.
|
||||
//! In any case, the addition is fast and does not depend on the size of the array.
|
||||
//! If there is no free space at the beginning of the array
|
||||
//! then all iterators and references
|
||||
//! (including the past-the-begin iterator) are invalidated.
|
||||
//! Otherwise only the past-the-begin iterator is invalidated.
|
||||
//! \~russian Если в начале массива имеется свободное место,
|
||||
//! что часто бывает, то добавление будет очень быстрым.
|
||||
//! В любом случае добавление быстрое и не зависит от размера массива.
|
||||
//! Если в начале массива нет свободного места,
|
||||
//! то все итераторы и указатели становятся нерабочими.
|
||||
//! В противном случае все, кроме итераторов указывающих, на начало массива,
|
||||
//! остаются в рабочем состоянии.
|
||||
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
|
||||
inline PIByteArray & prepend(uchar e) {
|
||||
d.prepend(e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given array `v` to the begin of the array.
|
||||
//! \~russian Добавляет массив `v` в начало массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! \~russian Перегруженая функция.
|
||||
//! \~\sa \a prepend()
|
||||
inline PIByteArray & prepend(const PIByteArray & v) {
|
||||
d.prepend(v.d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Appends the given elements to the begin of the array.
|
||||
//! \~russian Добавляет элементы в начало массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! Appends the given elements from
|
||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~russian Перегруженая функция.
|
||||
//! Добавляет элементы из
|
||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~\sa \a append()
|
||||
inline PIByteArray & prepend(std::initializer_list<uchar> init_list) {
|
||||
d.prepend(init_list);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Remove one element from the end of the array.
|
||||
//! \~russian Удаляет один элемент с конца массива.
|
||||
//! \~\details
|
||||
//! \~english Deleting an element from the end is very fast
|
||||
//! and does not depend on the size of the array.
|
||||
//! \~russian Удаление элемента с конца выполняется очень быстро
|
||||
//! и не зависит от размера массива.
|
||||
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
|
||||
inline PIByteArray & pop_back() {
|
||||
d.pop_back();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Remove one element from the begining of the array.
|
||||
//! \~russian Удаляет один элемент с начала массива.
|
||||
//! \~\details
|
||||
//! \~english Removing an element from the beginning takes longer than from the end.
|
||||
//! This time is directly proportional to the size of the array.
|
||||
//! All iterators and references are invalidated.
|
||||
//! \~russian Удаление элемента с начала выполняется дольше, чем с конца.
|
||||
//! Это время прямопропорционально размеру массива.
|
||||
//! При удалении элемента все итераторы и указатели становятся нерабочими.
|
||||
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
|
||||
inline PIByteArray & pop_front() {
|
||||
d.pop_front();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Remove one element from the end of the array and return it.
|
||||
//! \~russian Удаляет один элемент с начала массива и возвращает его.
|
||||
//! \~\details
|
||||
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
||||
inline uchar take_back() {
|
||||
return d.take_back();
|
||||
}
|
||||
|
||||
//! \~english Remove one element from the begining of the array and return it.
|
||||
//! \~russian Удаляет один элемент с конца массива и возвращает его.
|
||||
//! \~\details
|
||||
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
||||
inline uchar take_front() {
|
||||
return d.take_front();
|
||||
}
|
||||
|
||||
//! \~english Returns a new array with all elements
|
||||
//! that pass the test implemented by the provided function `test`.
|
||||
//! \~russian Возвращает новый массив со всеми элементами,
|
||||
//! прошедшими проверку, задаваемую в передаваемой функции `test`.
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIByteArray v{3, 2, 5, 2, 7};
|
||||
//! PIByteArray v2 = v.filter([](const uchar & i){return i > 2;});
|
||||
//! piCout << v2; // {3, 5, 7}
|
||||
//! \endcode
|
||||
//! \~\sa \a map(), \a any(), \a every()
|
||||
inline PIByteArray filter(std::function<bool(const uchar & e)> test) const {
|
||||
return PIByteArray(d.filter(test));
|
||||
}
|
||||
|
||||
//! \~english Execute function `void f(const uchar & e)` for every element in array.
|
||||
//! \~russian Выполняет функцию `void f(const uchar & e)` для каждого элемента массива.
|
||||
//! \~\details
|
||||
//! \~russian Не позволяет изменять элементы массива.
|
||||
//! Для редактирования элементов используйте функцию вида `void f(uchar & e)`.
|
||||
//! \~english Does not allow changing array elements.
|
||||
//! To edit elements, use the function like `void f(T & e)`
|
||||
//! \~\code
|
||||
//! PIByteArray v{1, 2, 3, 4, 5};
|
||||
//! int s = 0;
|
||||
//! v.forEach([&s](const uchar & e){s += e;});
|
||||
//! piCout << s; // 15
|
||||
//! \endcode
|
||||
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
|
||||
inline void forEach(std::function<void(const uchar & e)> f) const {
|
||||
d.forEach(f);
|
||||
}
|
||||
|
||||
//! \~english Execute function `void f(uchar & e)` for every element in array.
|
||||
//! \~russian Выполняет функцию `void f(uchar & e)` для каждого элемента массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! Allows you to change the elements of the array.
|
||||
//! \~russian Перегруженая функция.
|
||||
//! Позволяет изменять элементы массива.
|
||||
//! \~\code
|
||||
//! PIByteArray v{1, 2, 3, 4, 5};
|
||||
//! v.forEach([](uchar & e){e++;});
|
||||
//! piCout << v; // {2, 3, 4, 5, 6}
|
||||
//! \endcode
|
||||
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
|
||||
inline PIByteArray & forEach(std::function<void(uchar & e)> f) {
|
||||
d.forEach(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Сreates a new array populated with the results
|
||||
//! of calling a provided function `ST f(const uchar & e)` on every element in the calling array.
|
||||
//! \~russian Создаёт новый массив с результатом вызова указанной функции
|
||||
//! `ST f(const T & e)` для каждого элемента массива.
|
||||
//! \~\details
|
||||
//! \~english Calls a provided function`ST f(const uchar & e)`
|
||||
//! once for each element in an array, in order,
|
||||
//! and constructs a new array from the results.
|
||||
//! \~russian Метод `map` вызывает переданную функцию `ST f(const uchar & e)`
|
||||
//! один раз для каждого элемента в порядке их появления
|
||||
//! и конструирует новый массив из результатов её вызова.
|
||||
//! \~\code
|
||||
//! PIByteArray v{0x31, 0x0A, 0xFF};
|
||||
//! PIStringList sl = v.map<PIString>([](const uchar & i){return PIString::fromNumber(i, 16);});
|
||||
//! piCout << sl; {"31", "A", "FF"}
|
||||
//! \endcode
|
||||
//! \~\sa \a forEach(), \a reduce()
|
||||
template <typename ST>
|
||||
inline PIDeque<ST> map(std::function<ST(const uchar & e)> f) const {
|
||||
return d.map<ST>(f);
|
||||
}
|
||||
|
||||
//! \~english Applies the function `ST f(const uchar & e, const ST & acc)`
|
||||
//! to each element of the array (from left to right), returns one value.
|
||||
//! \~russian Применяет функцию `ST f(const uchar & e, const ST & acc)`
|
||||
//! к каждому элементу массива (слева-направо), возвращает одно значение.
|
||||
//! \~\details
|
||||
//! \~english The reduce() method performs the `f` function
|
||||
//! once for each element in the array.
|
||||
//! If the `initial` argument is passed when calling reduce(),
|
||||
//! then when the function `f` is called for the first time,
|
||||
//! the value of `acc` will be assigned to `initial`.
|
||||
//! If the array is empty, the value `initial` will be returned.
|
||||
//! \param f is a function like `ST f(const uchar & e, const ST & acc)`,
|
||||
//! executed for each element of the array. It takes two arguments:
|
||||
//! * **e** - current element of the array
|
||||
//! * **acc** - accumulator accumulating the value
|
||||
//! which this function returns after visiting the next element
|
||||
//!
|
||||
//! \param initial _optional_ Object used as the second argument
|
||||
//! when the `f` function is first called.
|
||||
//! \~russian Метод reduce() выполняет функцию `f`
|
||||
//! один раз для каждого элемента, присутствующего в массиве.
|
||||
//! Если при вызове reduce() передан аргумент `initial`,
|
||||
//! то при первом вызове функции `f` значение `acc`
|
||||
//! будет равным значению `initial`.
|
||||
//! Если массив пустой то будет возвращено значение `initial`.
|
||||
//! \param f Функция, вида `ST f(const uchar & e, const ST & acc)`,
|
||||
//! выполняющаяся для каждого элемента массива.
|
||||
//! Она принимает два аргумента:
|
||||
//! * **e** - текущий элемент массива
|
||||
//! * **acc** - аккумулятор, аккумулирующий значение
|
||||
//! которое возвращает эта функция после посещения очередного элемента
|
||||
//!
|
||||
//! \param initial _опциональный_ Объект,
|
||||
//! используемый в качестве второго аргумента при первом вызове функции `f`.
|
||||
//!
|
||||
//! \~\code
|
||||
//! PIByteArray v{1, 2, 3, 4, 5};
|
||||
//! PIString s = v.reduce<PIString>([](const uchar & e, const PIString & acc){return acc + PIString::fromNumber(e);});
|
||||
//! piCout << s; // "12345"
|
||||
//! \endcode
|
||||
//! \~\sa \a forEach(), \a map()
|
||||
template <typename ST>
|
||||
inline ST reduce(std::function<ST(const uchar & e, const ST & acc)> f, const ST & initial = ST()) const {
|
||||
return d.reduce<ST>(f, initial);
|
||||
}
|
||||
|
||||
//! \~english Convert data to Base 64 and return this byte array
|
||||
//! \~russian Преобразует данные в Base 64 и возвращает текущий массив
|
||||
@@ -142,6 +1088,21 @@ public:
|
||||
//! \~russian Добавляет в конец массива байт "t"
|
||||
PIByteArray & append(uchar t) {push_back(t); return *this;}
|
||||
|
||||
//! \~english Appends the given elements to the end of the array.
|
||||
//! \~russian Добавляет элементы в конец массива.
|
||||
//! \~\details
|
||||
//! \~english Overloaded function.
|
||||
//! Appends the given elements from
|
||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~russian Перегруженая функция.
|
||||
//! Добавляет элементы из
|
||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||
//! \~\sa \a push_back()
|
||||
inline PIByteArray & append(std::initializer_list<uchar> init_list) {
|
||||
d.append(init_list);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \~english Returns 8-bit checksum
|
||||
//! \~russian Возвращает 8-битную контрольную сумму
|
||||
uchar checksumPlain8(bool inverse = true) const;
|
||||
@@ -154,7 +1115,7 @@ public:
|
||||
//! \~russian Возвращает хэш содержимого
|
||||
uint hash() const;
|
||||
|
||||
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
|
||||
void operator =(const PIDeque<uchar> & o) {resize(o.size()); memcpy(data(), o.data(), o.size());}
|
||||
|
||||
PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
|
||||
|
||||
@@ -170,13 +1131,22 @@ public:
|
||||
static PIByteArray fromBase64(const PIString & base64);
|
||||
|
||||
|
||||
class StreamRef {
|
||||
public:
|
||||
StreamRef(PIByteArray & s): ba(s) {}
|
||||
operator PIByteArray&() {return ba;}
|
||||
private:
|
||||
PIByteArray & ba;
|
||||
};
|
||||
bool binaryStreamAppendImp(const void * d_, size_t s) {
|
||||
append(d_, s);
|
||||
return true;
|
||||
}
|
||||
bool binaryStreamTakeImp(void * d_, size_t s) {
|
||||
size_t rs = size();
|
||||
if (rs > s) rs = s;
|
||||
memcpy(d_, data(), rs);
|
||||
remove(0, rs);
|
||||
return rs == s;
|
||||
}
|
||||
|
||||
ssize_t binaryStreamSizeImp() const {return size();}
|
||||
|
||||
private:
|
||||
PIDeque<uchar> d;
|
||||
|
||||
};
|
||||
|
||||
@@ -235,443 +1205,14 @@ inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
|
||||
|
||||
|
||||
|
||||
|
||||
// store operators for basic types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator for any trivial copyable type
|
||||
//! \~russian Оператор сохранения для тривиальных типов
|
||||
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
|
||||
int os = s.size_s();
|
||||
s.enlarge(sizeof(v));
|
||||
memcpy(s.data(os), &v, sizeof(v));
|
||||
BINARY_STREAM_WRITE(PIByteArray) {
|
||||
s.binaryStreamAppend((int)v.size_s());
|
||||
s.binaryStreamAppend(v.data(), v.size());
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator, see \ref PIByteArray_sec1 for details
|
||||
//! \~russian Оператор сохранения, подробнее в \ref PIByteArray_sec1
|
||||
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
|
||||
int os = s.size_s();
|
||||
if (v.s > 0) {
|
||||
s.enlarge(v.s);
|
||||
memcpy(s.data(os), v.d, v.s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator for PIVector of any trivial copyable type
|
||||
//! \~russian Оператор сохранения для PIVector тривиальных типов
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
s << int(v.size_s());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s()*sizeof(T));
|
||||
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator for PIDeque of any trivial copyable type
|
||||
//! \~russian Оператор сохранения для PIDeque тривиальных типов
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
s << int(v.size_s());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s()*sizeof(T));
|
||||
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator for PIVector2D of any trivial copyable type
|
||||
//! \~russian Оператор сохранения для PIVector2D тривиальных типов
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
s << int(v.rows()) << int(v.cols());
|
||||
int os = s.size_s();
|
||||
if (v.size_s() > 0) {
|
||||
s.enlarge(v.size_s()*sizeof(T));
|
||||
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
|
||||
|
||||
//! \relatesalso PIPair
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
template<typename Type0, typename Type1>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
|
||||
|
||||
|
||||
|
||||
|
||||
// restore operators for basic types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator for any trivial copyable type
|
||||
//! \~russian Оператор извлечения для тривиальных типов
|
||||
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
|
||||
if (s.size() < sizeof(v)) {
|
||||
printf("error with %s\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size() >= sizeof(v));
|
||||
}
|
||||
memcpy((void*)(&v), s.data(), sizeof(v));
|
||||
s.remove(0, sizeof(v));
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator, see \ref PIByteArray_sec1 for details
|
||||
//! \~russian Оператор извлечения, подробнее в \ref PIByteArray_sec1
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
|
||||
if (s.size_s() < v.s) {
|
||||
printf("error with RawData %d < %d\n", (int)s.size_s(), v.s);
|
||||
assert(s.size_s() >= v.s);
|
||||
}
|
||||
if (v.s > 0) {
|
||||
memcpy((void*)(v.d), s.data(), v.s);
|
||||
s.remove(0, v.s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator for PIVector of any trivial copyable type
|
||||
//! \~russian Оператор извлечения для PIVector тривиальных типов
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
if (s.size_s() < 4) {
|
||||
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}
|
||||
int sz; s >> sz;
|
||||
v._resizeRaw(sz);
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||
s.remove(0, sz*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
if (s.size_s() < 4) {
|
||||
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator for PIDeque of any trivial copyable type
|
||||
//! \~russian Оператор извлечения для PIDeque тривиальных типов
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
if (s.size_s() < 4) {
|
||||
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}
|
||||
int sz; s >> sz;
|
||||
v._resizeRaw(sz);
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||
s.remove(0, sz*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
if (s.size_s() < 4) {
|
||||
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator for PIVector2D of any trivial copyable type
|
||||
//! \~russian Оператор извлечения для PIVector2D тривиальных типов
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
if (s.size_s() < 8) {
|
||||
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 8);
|
||||
}
|
||||
int r, c; s >> r >> c;
|
||||
v._resizeRaw(r, c);
|
||||
int sz = r*c;
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||
s.remove(0, sz*sizeof(T));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T,
|
||||
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
if (s.size_s() < 8) {
|
||||
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 8);
|
||||
}
|
||||
int r,c;
|
||||
PIVector<T> tmp;
|
||||
s >> r >> c >> tmp;
|
||||
v = PIVector2D<T>(r, c, tmp);
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
|
||||
|
||||
//! \relatesalso PIPair
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
template<typename Type0, typename Type1>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
|
||||
|
||||
|
||||
|
||||
|
||||
// store operators for complex types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator for PIVector of any compound type
|
||||
//! \~russian Оператор сохранения для PIVector сложных типов
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator for PIDeque of any compound type
|
||||
//! \~russian Оператор сохранения для PIDeque сложных типов
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
s << int(v.size_s());
|
||||
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator for PIVector2D of any compound type
|
||||
//! \~russian Оператор сохранения для PIVector2D сложных типов
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// restore operators for complex types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator for PIVector of any compound type
|
||||
//! \~russian Оператор извлечения для PIVector сложных типов
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
if (s.size_s() < 4) {
|
||||
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator for PIDeque of any compound type
|
||||
//! \~russian Оператор извлечения для PIDeque сложных типов
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
if (s.size_s() < 4) {
|
||||
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}
|
||||
int sz; s >> sz;
|
||||
v.resize(sz);
|
||||
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator for PIVector2D of any compound type
|
||||
//! \~russian Оператор извлечения для PIVector2D сложных типов
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
if (s.size_s() < 8) {
|
||||
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 8);
|
||||
}
|
||||
int r,c;
|
||||
PIVector<T> tmp;
|
||||
s >> r >> c >> tmp;
|
||||
v = PIVector2D<T>(r, c, tmp);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// other types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
template <typename Key, typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
|
||||
// s << int(v.pim_index.size_s());
|
||||
// for (uint i = 0; i < v.size(); ++i)
|
||||
// s << int(v.pim_index[i].index) << v.pim_index[i].key;
|
||||
s << v.pim_content;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
template <typename Key, typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
|
||||
if (s.size_s() < 4) {
|
||||
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
|
||||
assert(s.size_s() >= 4);
|
||||
}
|
||||
// int sz; s >> sz; v.pim_index.resize(sz);
|
||||
// int ind = 0;
|
||||
// for (int i = 0; i < sz; ++i) {
|
||||
// s >> ind >> v.pim_index[i].key;
|
||||
// v.pim_index[i].index = ind;
|
||||
// }
|
||||
s >> v.pim_content;
|
||||
// if (v.pim_content.size_s() != v.pim_index.size_s()) {
|
||||
// piCout << "Warning: loaded invalid PIMap, clear";
|
||||
// v.clear();
|
||||
// }
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const T & ) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, T & ) {
|
||||
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator >> for complex type!");
|
||||
BINARY_STREAM_READ(PIByteArray) {
|
||||
v.resize(s.binaryStreamTakeInt());
|
||||
s.binaryStreamTake(v.data(), v.size());
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ int PIChunkStream::read() {
|
||||
last_id = readVInt(*data_);
|
||||
last_data.resize(readVInt(*data_));
|
||||
//piCout << last_id << last_data.size();
|
||||
(*data_) >> PIByteArray::RawData(last_data.data(), last_data.size_s());
|
||||
(*data_) >> PIMemoryBlock(last_data.data(), last_data.size_s());
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
//! \~english Returns value of last readed chunk
|
||||
//! \~russian Возвращает значение последнего прочитанного чанка
|
||||
template <typename T>
|
||||
T getData() const {T ret; PIByteArray s(last_data); s >> ret; return ret;}
|
||||
T getData() const {T ret{}; PIByteArray s(last_data); s >> ret; return ret;}
|
||||
|
||||
//! \~english Place value of last readed chunk into \"v\"
|
||||
//! \~russian Записывает значение последнего прочитанного чанка в \"v\"
|
||||
|
||||
@@ -42,6 +42,13 @@
|
||||
//!
|
||||
|
||||
|
||||
bool PIConstChars::contains(char c) const {
|
||||
for (int i = 0; i < (int)len; ++i)
|
||||
if (str[i] == c) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PIConstChars::startsWith(const PIConstChars & str) const {
|
||||
if (size() < str.size()) return false;
|
||||
return str == left(str.size());
|
||||
|
||||
@@ -86,6 +86,10 @@ public:
|
||||
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
|
||||
inline bool isNotEmpty() const {return len > 0;}
|
||||
|
||||
//! \~english Returns \c true if string contains character "c".
|
||||
//! \~russian Возвращает \c true если строка содержит символ "c".
|
||||
bool contains(char c) const;
|
||||
|
||||
//! \~english Returns characters length of string.
|
||||
//! \~russian Возвращает длину строки в символах.
|
||||
inline size_t length() const {return len;}
|
||||
|
||||
@@ -108,7 +108,7 @@ class NotifierObject: public PIObject {
|
||||
PIOBJECT(NotifierObject)
|
||||
public:
|
||||
NotifierObject() {}
|
||||
EVENT2(finished, int, id, PIString*, buffer)
|
||||
EVENT2(finished, int, id, PIString*, buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -320,10 +320,10 @@ PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v)
|
||||
|
||||
#define PICOUTTOTARGET(v) { \
|
||||
if (buffer_) {\
|
||||
(*buffer_) << (v);\
|
||||
(*buffer_) += (v);\
|
||||
} else {\
|
||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += (v);\
|
||||
}\
|
||||
}
|
||||
|
||||
@@ -386,52 +386,52 @@ PICout PICout::operator <<(const PICoutSpecialChar v) {
|
||||
switch (v) {
|
||||
case Null:
|
||||
if (buffer_) {
|
||||
(*buffer_) << PIChar();
|
||||
(*buffer_) += PIChar();
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar();
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar();
|
||||
}
|
||||
break;
|
||||
case NewLine:
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\n";
|
||||
(*buffer_) += "\n";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '\n';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
|
||||
}
|
||||
fo_ = true;
|
||||
break;
|
||||
case Tab:
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\t";
|
||||
(*buffer_) += "\t";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '\t';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\t";
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\t";
|
||||
}
|
||||
break;
|
||||
case Esc:
|
||||
#ifdef CC_VC
|
||||
if (buffer_) {
|
||||
(*buffer_) << PIChar(27);
|
||||
(*buffer_) += PIChar(27);
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << char(27);
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar(27);
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar(27);
|
||||
}
|
||||
#else
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\e";
|
||||
(*buffer_) += "\e";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '\e';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\e";
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\e";
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case Quote:
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\"";
|
||||
(*buffer_) += "\"";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
|
||||
}
|
||||
break;
|
||||
};
|
||||
@@ -469,10 +469,10 @@ PICout & PICout::space() {
|
||||
if (!act_) return *this;
|
||||
if (!fo_ && co_[AddSpaces]) {
|
||||
if (buffer_) {
|
||||
(*buffer_) << " ";
|
||||
(*buffer_) += " ";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << ' ';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << " ";
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += " ";
|
||||
}
|
||||
}
|
||||
fo_ = false;
|
||||
@@ -489,10 +489,10 @@ PICout & PICout::quote() {
|
||||
if (!act_) return *this;
|
||||
if (co_[AddQuotes]) {
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\"";
|
||||
(*buffer_) += "\"";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
|
||||
}
|
||||
}
|
||||
fo_ = false;
|
||||
@@ -509,10 +509,10 @@ PICout & PICout::newLine() {
|
||||
if (!act_) return *this;
|
||||
if (co_[AddNewLine]) {
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\n";
|
||||
(*buffer_) += "\n";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << std::endl;
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
|
||||
}
|
||||
}
|
||||
fo_ = false;
|
||||
|
||||
@@ -311,16 +311,6 @@ inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDateTime & v) {s << v.year << v.month << v.day << v.hours << v.minutes << v.seconds << v.milliseconds; return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDateTime & v) {s >> v.year >> v.month >> v.day >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;}
|
||||
|
||||
//! \relatesalso PICout
|
||||
//! \~english \brief Output operator to PICout
|
||||
//! \~russian \brief Оператор вывода в PICout
|
||||
|
||||
@@ -38,6 +38,7 @@ class PIMutexLocker;
|
||||
class PIObject;
|
||||
class PIString;
|
||||
class PIByteArray;
|
||||
template <typename P> class PIBinaryStream;
|
||||
#ifndef MICRO_PIP
|
||||
class PIInit;
|
||||
#endif
|
||||
|
||||
63
libs/main/core/pimemoryblock.h
Normal file
63
libs/main/core/pimemoryblock.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*! \file pimemoryblock.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Base types and functions
|
||||
* \~russian Базовые типы и методы
|
||||
*/
|
||||
/*
|
||||
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 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 PIMEMORYBLOCK_H
|
||||
#define PIMEMORYBLOCK_H
|
||||
|
||||
|
||||
//! \ingroup Core
|
||||
//! \include pimemoryblock.h
|
||||
//! \brief
|
||||
//! \~english Help struct to store/restore custom blocks of data to/from PIBinaryStream
|
||||
//! \~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(const void * data_, const int size_) {d = const_cast<void * >(data_); s = size_;}
|
||||
|
||||
PIMemoryBlock(const PIMemoryBlock & o) {d = o.d; s = o.s;}
|
||||
|
||||
PIMemoryBlock & operator =(const PIMemoryBlock & o) {d = o.d; s = o.s; return *this;}
|
||||
|
||||
void * data() {return d;}
|
||||
const void * data() const {return d;}
|
||||
int size() const {return s;}
|
||||
|
||||
private:
|
||||
void * d;
|
||||
int s;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
PIMemoryBlock createMemoryBlock(const T * ptr) {return PIMemoryBlock(ptr, sizeof(T));}
|
||||
|
||||
#endif // PIMEMORYBLOCK_H
|
||||
@@ -23,6 +23,7 @@
|
||||
#ifndef MICRO_PIP
|
||||
# include "pisysteminfo.h"
|
||||
# include "pifile.h"
|
||||
# include "piiostream.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -753,7 +754,8 @@ bool dumpApplicationToFile(const PIString & path, bool with_objects) {
|
||||
bool ba = PICout::isBufferActive();
|
||||
PICout::setBufferActive(true, true);
|
||||
dumpApplication(with_objects);
|
||||
f << PICout::buffer();
|
||||
PIIOTextStream ts(&f);
|
||||
ts << PICout::buffer();
|
||||
f.close();
|
||||
PICout::setBufferActive(ba, true);
|
||||
PIFile::rename(path + "_tmp", path);
|
||||
|
||||
@@ -49,7 +49,7 @@ class PIP_EXPORT PIObject {
|
||||
typedef PIObject __PIObject__;
|
||||
typedef void __Parent__;
|
||||
public:
|
||||
NO_COPY_CLASS(PIObject)
|
||||
NO_COPY_CLASS(PIObject);
|
||||
|
||||
//! \~english Contructs %PIObject with name "name"
|
||||
//! \~russian Создает %PIObject с именем "name"
|
||||
@@ -518,7 +518,7 @@ protected:
|
||||
//! \~russian Виртуальная функция, вызывается после изменения любого свойства.
|
||||
virtual void propertyChanged(const char * name) {}
|
||||
|
||||
EVENT1(deleted, PIObject *, o)
|
||||
EVENT1(deleted, PIObject *, o);
|
||||
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
@@ -271,10 +271,11 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage::Property & v) {s << v.name << v.value << v.comment << v.flags; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage::Property & v) {s >> v.name >> v.value >> v.comment >> v.flags; return s;}
|
||||
BINARY_STREAM_WRITE(PIPropertyStorage::Property) {s << v.name << v.value << v.comment << v.flags; return s;}
|
||||
BINARY_STREAM_READ (PIPropertyStorage::Property) {s >> v.name >> v.value >> v.comment >> v.flags; return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(PIPropertyStorage) {s << v.properties(); return s;}
|
||||
BINARY_STREAM_READ (PIPropertyStorage) {s >> v.properties(); return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage & v) {s << v.properties(); return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage & v) {s >> v.properties(); return s;}
|
||||
|
||||
#endif // PIPROPERTYSTORAGE_H
|
||||
|
||||
@@ -215,6 +215,13 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) {
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::fromConsole(const PIByteArray & ba) {
|
||||
PIString ret;
|
||||
if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __sysoemname__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::fromConsole(const char * s) {
|
||||
PIString ret;
|
||||
if (!s) return ret;
|
||||
@@ -224,6 +231,13 @@ PIString PIString::fromConsole(const char * s) {
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::fromSystem(const PIByteArray & ba) {
|
||||
PIString ret;
|
||||
if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __syslocname__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::fromSystem(const char * s) {
|
||||
PIString ret;
|
||||
if (!s) return ret;
|
||||
@@ -361,6 +375,13 @@ uint PIString::hash() const {
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIString::toSystem() const {
|
||||
if (isEmpty()) return PIByteArray();
|
||||
buildData(__syslocname__);
|
||||
return PIByteArray(data_, strlen(data_));
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIString::toUTF8() const {
|
||||
if (isEmpty()) return PIByteArray();
|
||||
buildData(__utf8name__);
|
||||
|
||||
@@ -40,8 +40,7 @@ class PIStringList;
|
||||
//! \~russian Класс строки.
|
||||
class PIP_EXPORT PIString
|
||||
{
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIString & v);
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIString & v);
|
||||
BINARY_STREAM_FRIEND(PIString);
|
||||
public:
|
||||
typedef PIDeque<PIChar>::iterator iterator;
|
||||
typedef PIDeque<PIChar>::const_iterator const_iterator;
|
||||
@@ -242,94 +241,6 @@ public:
|
||||
//! \~russian Оператор сравнения.
|
||||
bool operator >=(const char * str) const {return *this >= PIString(str);}
|
||||
|
||||
//! \~english Append string "str" at the end of string.
|
||||
//! \~russian Добавляет в конец строку "str".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("this"), s1(" is"), s2(" string");
|
||||
//! s << s1 << s2; // s = "this is string"
|
||||
//! \endcode
|
||||
PIString & operator <<(const PIString & str) {*this += str; return *this;}
|
||||
|
||||
//! \~english Append character "c" at the end of string.
|
||||
//! \~russian Добавляет в конец символ "c".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("stri");
|
||||
//! s << PIChar('n') << PIChar('g'); // s = "string"
|
||||
//! \endcode
|
||||
PIString & operator <<(const PIChar c) {d.append(c); return *this;}
|
||||
|
||||
//! \~english Append character `c` at the end of string.
|
||||
//! \~russian Добавляет в конец символ `c`.
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("stri");
|
||||
//! s << 'n' << 'g'; // s = "string"
|
||||
//! \endcode
|
||||
PIString & operator <<(const char c) {d.append(PIChar(c)); return *this;}
|
||||
|
||||
//! \~english Append С-string "str" at the end of string.
|
||||
//! \~russian Добавляет в конец C-строку "str".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("this");
|
||||
//! s << " is" << " string"; // s = "this is string"
|
||||
//! \endcode
|
||||
PIString & operator <<(const char * str) {*this += str; return *this;}
|
||||
|
||||
//! \~english Append \c wchar_t C-string "str" at the end of string.
|
||||
//! \~russian Добавляет в конец \c wchar_t C-строку "str".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s;
|
||||
//! s << L"№ -" << " number"; // s = "№ - number"
|
||||
//! \endcode
|
||||
PIString & operator <<(const wchar_t * str) {*this += str; return *this;}
|
||||
|
||||
PIString & operator <<(const PIConstChars & str) {*this += str; return *this;}
|
||||
|
||||
//! \~english Append string representation of "num" at the end of string.
|
||||
//! \~russian Добавляет в конец строковое представление "num".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("ten - ");
|
||||
//! s << 10; // s = "ten - 10"
|
||||
//! \endcode
|
||||
PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
//! \~english Append string representation of "num" at the end of string.
|
||||
//! \~russian Добавляет в конец строковое представление "num".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("ten - ");
|
||||
//! s << 10; // s = "ten - 10"
|
||||
//! \endcode
|
||||
PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
//! \~english Append string representation of "num" at the end of string.
|
||||
//! \~russian Добавляет в конец строковое представление "num".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("1/10 - ");
|
||||
//! s << 0.1; // s = "1/10 - 0.1"
|
||||
//! \endcode
|
||||
PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
//! \~english Append string representation of "num" at the end of string.
|
||||
//! \~russian Добавляет в конец строковое представление "num".
|
||||
//! \~\details
|
||||
//! \~\code
|
||||
//! PIString s("1/10 - ");
|
||||
//! s << 0.1; // s = "1/10 - 0.1"
|
||||
//! \endcode
|
||||
PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
//! \~english Iterator to the first element.
|
||||
//! \~russian Итератор на первый элемент.
|
||||
//! \~\details
|
||||
@@ -909,6 +820,10 @@ public:
|
||||
//! \~russian Тоже самое, что \a toUTF8().
|
||||
PIByteArray toByteArray() const {return toUTF8();}
|
||||
|
||||
//! \~english Returns \a PIByteArray contains \a data() of this string without terminating null-char.
|
||||
//! \~russian Возвращает \a PIByteArray содержащий \a data() строки без завершающего нулевого байта.
|
||||
PIByteArray toSystem() const;
|
||||
|
||||
//! \~english Returns \a PIByteArray contains \a dataUTF8() of this string without terminating null-char.
|
||||
//! \~russian Возвращает \a PIByteArray содержащий \a dataUTF8() строки без завершающего нулевого байта.
|
||||
PIByteArray toUTF8() const;
|
||||
@@ -1507,10 +1422,18 @@ public:
|
||||
//! \~english Returns "true" or "false"
|
||||
//! \~russian Возвращает "true" или "false"
|
||||
static PIString fromBool(const bool value) {return PIString(value ? PIStringAscii("true") : PIStringAscii("false"));}
|
||||
|
||||
//! \~english Returns string constructed from terminal codepage.
|
||||
//! \~russian Возвращает строку созданную из кодировки консоли.
|
||||
static PIString fromConsole(const PIByteArray & s);
|
||||
|
||||
//! \~english Returns string constructed from terminal codepage.
|
||||
//! \~russian Возвращает строку созданную из кодировки консоли.
|
||||
static PIString fromConsole(const char * s);
|
||||
|
||||
//! \~english Returns string constructed from system codepage.
|
||||
//! \~russian Возвращает строку созданную из кодировки системы.
|
||||
static PIString fromSystem(const PIByteArray & s);
|
||||
|
||||
//! \~english Returns string constructed from system codepage.
|
||||
//! \~russian Возвращает строку созданную из кодировки системы.
|
||||
@@ -1583,12 +1506,12 @@ PIP_EXPORT PICout operator <<(PICout s, const PIString & v);
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator.
|
||||
//! \~russian Оператор сохранения.
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.d; return s;}
|
||||
BINARY_STREAM_WRITE(PIString) {s << v.d; return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator.
|
||||
//! \~russian Оператор извлечения.
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {v.d.clear(); s >> v.d; return s;}
|
||||
BINARY_STREAM_READ(PIString) {s >> v.d; return s;}
|
||||
|
||||
|
||||
//! \~english Returns concatenated string.
|
||||
|
||||
@@ -126,15 +126,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIStringList & v) {s << int(v.size_s()); for (int i = 0; i < v.size_s(); ++i) s << v[i]; return s;}
|
||||
BINARY_STREAM_WRITE(PIStringList) {
|
||||
s << static_cast<const PIDeque<PIString> &>(v);
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ(PIStringList) {
|
||||
s >> static_cast<PIDeque<PIString> &>(v);
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIStringList & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
|
||||
|
||||
//! \relatesalso PICout
|
||||
//! \~english Output operator to \a PICout
|
||||
|
||||
341
libs/main/core/pitextstream.h
Normal file
341
libs/main/core/pitextstream.h
Normal file
@@ -0,0 +1,341 @@
|
||||
/*! \file pitextstream.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Text serialization functionality over PIBinaryStream
|
||||
* \~russian Функциональность текстовой сериализации поверх PIBinaryStream
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Text serialization functionality over PIBinaryStream
|
||||
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 PITEXTSTREAM_H
|
||||
#define PITEXTSTREAM_H
|
||||
|
||||
#include "pistring.h"
|
||||
|
||||
|
||||
//! \ingroup Core
|
||||
//! \~\brief
|
||||
//! \~english Text serialization functionality over PIBinaryStream.
|
||||
//! \~russian Функциональность текстовой сериализации поверх PIBinaryStream.
|
||||
template<typename P>
|
||||
class PITextStream {
|
||||
public:
|
||||
|
||||
//! \~english Floating-point numbers write format
|
||||
//! \~russian Формат записи чисел с плавающей точкой
|
||||
enum FloatFormat {
|
||||
DecimalFormat /** \~english Decimal format, "*.*" \~russian Десятичный формат, "*.*" */ = 'f',
|
||||
ExponentFormat /** \~english Exponential format, "*e+-<E>" \~russian Экспонентный формат, "*e+-<E>" */ = 'e'
|
||||
};
|
||||
|
||||
//! \~english String encoding
|
||||
//! \~russian Кодировка строк
|
||||
enum Encoding {
|
||||
System /** \~english System encoding \~russian Системная кодировка */,
|
||||
UTF8 /** \~english UTF-8 encoding \~russian Кодировка UTF-8 */,
|
||||
};
|
||||
|
||||
//! \~english Construct text stream binded to "stream_"
|
||||
//! \~russian Возвращает привязанный к "stream_" текстовый поток
|
||||
PITextStream(PIBinaryStream<P> * stream_) {setStream(stream_);}
|
||||
|
||||
//! \~english Returns binded PIBinaryStream
|
||||
//! \~russian Возвращает привязанный PIBinaryStream
|
||||
PIBinaryStream<P> * stream() const {return s;}
|
||||
void setStream(PIBinaryStream<P> * stream_) {
|
||||
s = stream_;
|
||||
is_end = false;
|
||||
}
|
||||
|
||||
//! \~english Returns if end of stream reached
|
||||
//! \~russian Возвращает достигнут ли конец потока
|
||||
bool isEnd() const {return is_end;}
|
||||
|
||||
//! \~english Returns read/write encoding
|
||||
//! \~russian Возвращает кодировку чтения/записи
|
||||
Encoding encoding() const {return enc;}
|
||||
|
||||
//! \~english Set read/write encoding, default UTF8
|
||||
//! \~russian Устанавливает кодировку чтения/записи, по умолчанию UTF8
|
||||
void setEncoding(Encoding e) {enc = e;}
|
||||
|
||||
//! \~english Returns float numbers write format
|
||||
//! \~russian Возвращает формат записи чисел с плавающей точкой
|
||||
FloatFormat floatFormat() const {return format_;}
|
||||
|
||||
//! \~english Set float numbers write format, default DecimalFormat
|
||||
//! \~russian Устанавливает формат записи чисел с плавающей точкой, по умолчанию DecimalFormat
|
||||
void setFloatFormat(FloatFormat format) {format_ = format;}
|
||||
|
||||
//! \~english Returns float numbers write precision
|
||||
//! \~russian Возвращает точность записи чисел с плавающей точкой
|
||||
int floatPrecision() const {return prec_;}
|
||||
|
||||
//! \~english Set float numbers write precision to "prec_" digits, default 5
|
||||
//! \~russian Устанавливает точность записи чисел с плавающей точкой, по умолчанию 5
|
||||
void setFloatPrecision(int prec) {prec_ = prec;}
|
||||
|
||||
//! \~english Append space
|
||||
//! \~russian Добавляет пробел
|
||||
PITextStream<P> & space() {s->binaryStreamAppend(' '); return *this;}
|
||||
|
||||
//! \~english Append new line
|
||||
//! \~russian Добавляет новую строку
|
||||
PITextStream<P> & newLine() {s->binaryStreamAppend('\n'); return *this;}
|
||||
|
||||
//! \~english Append "v" string
|
||||
//! \~russian Добавляет строку "v"
|
||||
void append(const PIString & v) {
|
||||
if (v.isEmpty()) return;
|
||||
PIByteArray d;
|
||||
switch (enc) {
|
||||
case System: d = v.toSystem(); break;
|
||||
case UTF8 : d = v.toUTF8(); break;
|
||||
}
|
||||
s->binaryStreamAppend(d.data(), d.size());
|
||||
}
|
||||
|
||||
//! \~english Append "v" as ASCII
|
||||
//! \~russian Добавляет "v" как ASCII
|
||||
void append(const PIConstChars & v) {if (!v.isEmpty()) s->binaryStreamAppend(v.data(), v.size());}
|
||||
|
||||
//! \~english Append "v" char as character
|
||||
//! \~russian Добавляет "v" как символ
|
||||
void append(char v) {s->binaryStreamAppend(v);}
|
||||
|
||||
//! \~english Append "v" as ASCII
|
||||
//! \~russian Добавляет "v" как ASCII
|
||||
void append(const char * v) {append(PIConstChars(v));}
|
||||
|
||||
//! \~english Append boolean, "true" of "false"
|
||||
//! \~russian Добавляет логическое, "true" of "false"
|
||||
void append(bool v) {append(v ? "true" : "false");}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
void append(int v) {append(PIString::fromNumber(v));}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
void append(llong v) {append(PIString::fromNumber(v));}
|
||||
|
||||
//! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision()
|
||||
//! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision()
|
||||
void append(float v) {append(PIString::fromNumber(v, (char)format_, prec_));}
|
||||
|
||||
//! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision()
|
||||
//! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision()
|
||||
void append(double v) {append(PIString::fromNumber(v, (char)format_, prec_));}
|
||||
|
||||
|
||||
//! \~english Read character
|
||||
//! \~russian Читает символ
|
||||
char takeChar(bool * rok) {
|
||||
char ret;
|
||||
bool ok = s->binaryStreamTake(&ret, sizeof(ret));
|
||||
if (!ok) is_end = true;
|
||||
if (rok) *rok = ok;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! \~english Read line
|
||||
//! \~russian Читает строку
|
||||
PIString takeLine() {
|
||||
PIByteArray ret;
|
||||
bool ok = true;
|
||||
for (;;) {
|
||||
char b = takeChar(&ok);
|
||||
if (!ok || b == '\n') break;
|
||||
if (b != '\r')
|
||||
ret.append((uchar)b);
|
||||
}
|
||||
return fromBytes(ret);
|
||||
}
|
||||
|
||||
//! \~english Read word, skip leading whitespaces, until next whitespace
|
||||
//! \~russian Читает слово, пропуская начальные пробельные символы, до следующего пробельного символа
|
||||
PIString takeWord() {
|
||||
static PIConstChars spaces(" \t\n\r");
|
||||
return takeUntil(spaces);
|
||||
}
|
||||
|
||||
//! \~english
|
||||
//! \~russian
|
||||
PIString takeCWord() {
|
||||
static PIConstChars chars(" \t\n\r:;%$&#@!?~/*-+=.,\\\"'`[](){}<>");
|
||||
return takeUntil(chars);
|
||||
}
|
||||
|
||||
private:
|
||||
PIString fromBytes(const PIByteArray & ba) {
|
||||
switch (enc) {
|
||||
case System: return PIString::fromSystem(ba);
|
||||
case UTF8 : return PIString::fromUTF8(ba);
|
||||
}
|
||||
return PIString();
|
||||
}
|
||||
PIString takeUntil(const PIConstChars & chars) {
|
||||
//static PIConstChars spaces(" \t\n\r");
|
||||
bool ok = true;
|
||||
char c = skipWhile(chars, &ok);
|
||||
if (!ok) return PIString();
|
||||
PIByteArray ret;
|
||||
ret.append((uchar)c);
|
||||
for (;;) {
|
||||
c = takeChar(&ok);
|
||||
if (!ok || chars.contains(c)) break;
|
||||
ret.append((uchar)c);
|
||||
}
|
||||
return fromBytes(ret);
|
||||
}
|
||||
// returns first non-"chars" char
|
||||
char skipWhile(const PIConstChars & chars, bool * rok) {
|
||||
bool ok = true;
|
||||
char c = 0;
|
||||
for (;;) {
|
||||
c = takeChar(&ok);
|
||||
if (!ok || !chars.contains(c)) break;
|
||||
}
|
||||
if (rok) *rok = ok;
|
||||
return c;
|
||||
}
|
||||
|
||||
PIBinaryStream<P> * s;
|
||||
Encoding enc = UTF8;
|
||||
FloatFormat format_ = DecimalFormat;
|
||||
bool is_end = false;
|
||||
int prec_ = 5;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! \~english Returns PITextStream for binary stream "stream"
|
||||
//! \~russian Возвращает PITextStream для бинарного потока "stream"
|
||||
template<typename P>
|
||||
inline PITextStream<P> createPITextStream(PIBinaryStream<P> * stream) {return PITextStream<P>(stream);}
|
||||
|
||||
|
||||
//! \~english Append boolean
|
||||
//! \~russian Добавляет логическое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, bool v) {s.append(v); return s;}
|
||||
|
||||
//! \~english Append character
|
||||
//! \~russian Добавляет символ
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, char v) {s.append(v); return s;}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, uchar v) {s.append((int)v); return s;}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, short v) {s.append((int)v); return s;}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, ushort v) {s.append((int)v); return s;}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, int v) {s.append((int)v); return s;}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, uint v) {s.append((int)v); return s;}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, llong v) {s.append((llong)v); return s;}
|
||||
|
||||
//! \~english Append integer
|
||||
//! \~russian Добавляет целое
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, ullong v) {s.append((llong)v); return s;}
|
||||
|
||||
//! \~english Append floating-point number
|
||||
//! \~russian Добавляет число с плавающей точкой
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, float v) {s.append(v); return s;}
|
||||
|
||||
//! \~english Append floating-point number
|
||||
//! \~russian Добавляет число с плавающей точкой
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, double v) {s.append(v); return s;}
|
||||
|
||||
|
||||
//! \~english Append string
|
||||
//! \~russian Добавляет строку
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const char * v) {s.append(v); return s;}
|
||||
|
||||
//! \~english Append string
|
||||
//! \~russian Добавляет строку
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const PIConstChars & v) {s.append(v); return s;}
|
||||
|
||||
//! \~english Append string
|
||||
//! \~russian Добавляет строку
|
||||
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const PIString & v) {s.append(v); return s;}
|
||||
|
||||
|
||||
//! \~english Read word as bool
|
||||
//! \~russian Читает слово как логическое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, bool & v) {v = s.takeWord().toBool(); return s;}
|
||||
|
||||
//! \~english Read character
|
||||
//! \~russian Читает символ
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, char & v) {v = s.takeChar(); return s;}
|
||||
|
||||
//! \~english Read word as integer
|
||||
//! \~russian Читает слово как целое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, uchar & v) {v = s.takeWord().toUInt(); return s;}
|
||||
|
||||
//! \~english Read word as integer
|
||||
//! \~russian Читает слово как целое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, short & v) {v = s.takeWord().toInt(); return s;}
|
||||
|
||||
//! \~english Read word as integer
|
||||
//! \~russian Читает слово как целое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, ushort & v) {v = s.takeWord().toUInt(); return s;}
|
||||
|
||||
//! \~english Read word as integer
|
||||
//! \~russian Читает слово как целое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, int & v) {v = s.takeWord().toInt(); return s;}
|
||||
|
||||
//! \~english Read word as integer
|
||||
//! \~russian Читает слово как целое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, uint & v) {v = s.takeWord().toUInt(); return s;}
|
||||
|
||||
//! \~english Read word as integer
|
||||
//! \~russian Читает слово как целое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, llong & v) {v = s.takeWord().toLLong(); return s;}
|
||||
|
||||
//! \~english Read word as integer
|
||||
//! \~russian Читает слово как целое
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, ullong & v) {v = s.takeWord().toULLong(); return s;}
|
||||
|
||||
//! \~english Read word as floating-point number
|
||||
//! \~russian Читает слово как число с плавающей точкой
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, float & v) {v = s.takeWord().toFloat(); return s;}
|
||||
|
||||
//! \~english Read word as floating-point number
|
||||
//! \~russian Читает слово как число с плавающей точкой
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, double & v) {v = s.takeWord().toDouble(); return s;}
|
||||
|
||||
|
||||
//! \~english Read word
|
||||
//! \~russian Читает слово
|
||||
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, PIString & v) {v = s.takeWord(); return s;}
|
||||
|
||||
#endif
|
||||
@@ -206,8 +206,7 @@ classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(c
|
||||
//! \~english Variant type.
|
||||
class PIP_EXPORT PIVariant {
|
||||
friend PICout operator <<(PICout s, const PIVariant & v);
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIVariant & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIVariant & v);
|
||||
BINARY_STREAM_FRIEND(PIVariant);
|
||||
public:
|
||||
|
||||
//! Type of %PIVariant content
|
||||
@@ -773,8 +772,9 @@ REGISTER_VARIANT(PILined)
|
||||
REGISTER_VARIANT(PIMathVectord)
|
||||
REGISTER_VARIANT(PIMathMatrixd)
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariant & v) {
|
||||
s << v._content << int(v._type);
|
||||
|
||||
BINARY_STREAM_WRITE(PIVariant) {
|
||||
s << v._content << v._type;
|
||||
if (v._type == PIVariant::pivCustom) {
|
||||
#ifdef CUSTOM_PIVARIANT
|
||||
if (v._info) {
|
||||
@@ -788,10 +788,8 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVariant & v) {
|
||||
}
|
||||
return s;
|
||||
}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariant & v) {
|
||||
int t(0);
|
||||
s >> v._content >> t;
|
||||
v._type = (PIVariant::Type)t;
|
||||
BINARY_STREAM_READ(PIVariant) {
|
||||
s >> v._content >> v._type;
|
||||
if (v._type == PIVariant::pivCustom) {
|
||||
PIString tn;
|
||||
s >> tn;
|
||||
|
||||
@@ -110,25 +110,25 @@ PIPropertyStorage PIVariantTypes::IODevice::get() const {
|
||||
|
||||
PIString PIVariantTypes::IODevice::toPICout() const {
|
||||
PIString s;
|
||||
s << "IODevice(" << prefix << ", mode=";
|
||||
s += "IODevice(" + prefix + ", mode=";
|
||||
int rwc = 0;
|
||||
if (mode & 1) {s << "r"; ++rwc;}
|
||||
if (mode & 2) {s << "w"; ++rwc;}
|
||||
if (rwc == 1) s << "o";
|
||||
s << ", flags=";
|
||||
if (mode & 1) {s += "r"; ++rwc;}
|
||||
if (mode & 2) {s += "w"; ++rwc;}
|
||||
if (rwc == 1) s += "o";
|
||||
s += ", flags=";
|
||||
#ifndef MICRO_PIP // TODO: PIIODevice for MICRO PIP
|
||||
if (options != 0) {
|
||||
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingRead])
|
||||
s << " br";
|
||||
s += " br";
|
||||
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite])
|
||||
s << " bw";
|
||||
s += " bw";
|
||||
}
|
||||
#endif // MICRO_PIP
|
||||
PIPropertyStorage ps = get();
|
||||
piForeachC (PIPropertyStorage::Property & p, ps) {
|
||||
s << ", " << p.name << "=\"" << p.value.toString() << "\"";
|
||||
s += ", " + p.name + "=\"" + p.value.toString() + "\"";
|
||||
}
|
||||
s << ")";
|
||||
s += ")";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,28 +164,34 @@ struct PIP_EXPORT IODevice {
|
||||
|
||||
}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Enumerator & v) {s << v.value << v.name; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Enumerator & v) {s >> v.value >> v.name; return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::Enumerator & v) {s << v.name << "(" << v.value << ")"; return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Enum & v) {s << v.enum_name << v.selected << v.enum_list; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Enum & v) {s >> v.enum_name >> v.selected >> v.enum_list; return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::Enum & v) {s << "Enum(" << v.selectedValue() << "=" << v.selectedName() << ")"; return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::File & v) {s << v.file << v.filter << uchar((v.is_abs ? 1 : 0) + (v.is_save ? 2 : 0)); return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::File & v) {uchar f(0); s >> v.file >> v.filter >> f; v.is_abs = ((f & 1) == 1); v.is_save = ((f & 2) == 2); return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::File & v) {s << "File(\"" << v.file << "\")"; return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Dir & v) {s << v.dir << v.is_abs; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Dir & v) {s >> v.dir >> v.is_abs; return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::Dir & v) {s << "Dir(\"" << v.dir << "\")"; return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Color & v) {s << v.rgba; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Color & v) {s >> v.rgba; return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::Color & v) {s.saveControl(); s << PICoutManipulators::Hex << "Color(#" << v.rgba << ")"; s.restoreControl(); return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::IODevice & v) {s << v.prefix << v.mode << v.options << v.props; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::IODevice & v) {s >> v.prefix >> v.mode >> v.options >> v.props; return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::IODevice & v) {s << v.toPICout(); return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(PIVariantTypes::Enumerator) {s << v.value << v.name; return s;}
|
||||
BINARY_STREAM_READ (PIVariantTypes::Enumerator) {s >> v.value >> v.name; return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(PIVariantTypes::Enum) {s << v.enum_name << v.selected << v.enum_list; return s;}
|
||||
BINARY_STREAM_READ (PIVariantTypes::Enum) {s >> v.enum_name >> v.selected >> v.enum_list; return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(PIVariantTypes::File) {s << v.file << v.filter << uchar((v.is_abs ? 1 : 0) + (v.is_save ? 2 : 0)); return s;}
|
||||
BINARY_STREAM_READ (PIVariantTypes::File) {uchar f(0); s >> v.file >> v.filter >> f; v.is_abs = ((f & 1) == 1); v.is_save = ((f & 2) == 2); return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(PIVariantTypes::Dir) {s << v.dir << v.is_abs; return s;}
|
||||
BINARY_STREAM_READ (PIVariantTypes::Dir) {s >> v.dir >> v.is_abs; return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(PIVariantTypes::Color) {s << v.rgba; return s;}
|
||||
BINARY_STREAM_READ (PIVariantTypes::Color) {s >> v.rgba; return s;}
|
||||
|
||||
BINARY_STREAM_WRITE(PIVariantTypes::IODevice) {s << v.prefix << v.mode << v.options << v.props; return s;}
|
||||
BINARY_STREAM_READ (PIVariantTypes::IODevice) {s >> v.prefix >> v.mode >> v.options >> v.props; return s;}
|
||||
|
||||
#endif // PIVARIANTYPES_H
|
||||
|
||||
@@ -76,19 +76,19 @@ public:
|
||||
|
||||
|
||||
//! Disconneted event
|
||||
EVENT1(disconnected, PIString, reason)
|
||||
EVENT1(disconnected, PIString, reason);
|
||||
|
||||
//! Conneted event
|
||||
EVENT1(connected, PIString, info)
|
||||
EVENT1(connected, PIString, info);
|
||||
|
||||
//! Client event for authorize new server
|
||||
EVENT2(authorize, PIByteArray, info, bool *, ok)
|
||||
EVENT2(authorize, PIByteArray, info, bool *, ok);
|
||||
|
||||
//! Client event for input server password
|
||||
EVENT1(passwordRequest, PIString *, pass)
|
||||
EVENT1(passwordRequest, PIString *, pass);
|
||||
|
||||
//! Server event on check client password
|
||||
EVENT1(passwordCheck, bool, result)
|
||||
EVENT1(passwordCheck, bool, result);
|
||||
|
||||
private:
|
||||
enum Role {Client, Server};
|
||||
|
||||
@@ -96,15 +96,3 @@ PIVector<PIIntrospectionContainers::TypeInfo> PIIntrospectionContainers::getInfo
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v) {
|
||||
s << PIByteArray::RawData(&v, sizeof(PIIntrospectionContainers::_Type)) << v.name;
|
||||
return s;
|
||||
}
|
||||
PIByteArray & operator >>(PIByteArray & s, PIIntrospectionContainers::TypeInfo & v) {
|
||||
s >> PIByteArray::RawData(&v, sizeof(PIIntrospectionContainers::_Type)) >> v.name;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,14 @@ public:
|
||||
mutable PISpinlock mutex;
|
||||
};
|
||||
|
||||
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v);
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIIntrospectionContainers::TypeInfo & v);
|
||||
|
||||
BINARY_STREAM_WRITE(PIIntrospectionContainers::TypeInfo) {
|
||||
s << PIMemoryBlock(&v, sizeof(PIIntrospectionContainers::_Type)) << v.name;
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ(PIIntrospectionContainers::TypeInfo) {
|
||||
s >> PIMemoryBlock(&v, sizeof(PIIntrospectionContainers::_Type)) >> v.name;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // PIINTROSPECTION_CONTAINERS_P_H
|
||||
|
||||
@@ -56,7 +56,7 @@ void PIIntrospectionServer::start(const PIString & server_name) {
|
||||
sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID());
|
||||
if (sysmon) {
|
||||
piCoutObj << "using existing sysmon";
|
||||
CONNECTU(sysmon, deleted, this, sysmonDeleted);
|
||||
CONNECT1(void, PIObject *, sysmon, deleted, this, sysmonDeleted);
|
||||
} else {
|
||||
piCoutObj << "create own sysmon";
|
||||
sysmon = new PISystemMonitor();
|
||||
|
||||
@@ -46,7 +46,7 @@ class PISystemMonitor;
|
||||
# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
|
||||
|
||||
class PIP_EXPORT PIIntrospectionServer: public PIPeer {
|
||||
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer)
|
||||
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer);
|
||||
public:
|
||||
static PIIntrospectionServer * instance();
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
private:
|
||||
PIIntrospectionServer();
|
||||
~PIIntrospectionServer();
|
||||
NO_COPY_CLASS(PIIntrospectionServer)
|
||||
NO_COPY_CLASS(PIIntrospectionServer);
|
||||
|
||||
PIString genName();
|
||||
virtual void dataReceived(const PIString & from, const PIByteArray & data);
|
||||
|
||||
@@ -77,82 +77,6 @@ PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() {
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) {
|
||||
PIChunkStream cs;
|
||||
cs.add(1, v.types);
|
||||
b << cs.data();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) {
|
||||
PIByteArray csba; b >> csba;
|
||||
PIChunkStream cs(csba);
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(v.types); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) {
|
||||
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);
|
||||
b << cs.data();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) {
|
||||
PIByteArray csba; b >> csba;
|
||||
PIChunkStream cs(csba);
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(v.architecture); break;
|
||||
case 2: cs.get(v.execCommand); break;
|
||||
case 3: cs.get(v.execDateTime); break;
|
||||
case 4: cs.get(v.hostname); break;
|
||||
case 5: cs.get(v.OS_name); break;
|
||||
case 6: cs.get(v.OS_version); break;
|
||||
case 7: cs.get(v.processorsCount); break;
|
||||
case 8: cs.get(v.user); break;
|
||||
case 9: cs.get(v.build_options); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) {
|
||||
PIChunkStream cs;
|
||||
cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events);
|
||||
b << cs.data();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) {
|
||||
PIByteArray csba; b >> csba;
|
||||
PIChunkStream cs(csba);
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(v.classname); break;
|
||||
case 2: cs.get(v.name); break;
|
||||
case 3: cs.get(v.parents); break;
|
||||
case 4: cs.get(v.properties); break;
|
||||
case 5: cs.get(v.queued_events); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIByteArray PIIntrospection::packInfo() {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "piintrospection_containers_p.h"
|
||||
#include "piintrospection_threads.h"
|
||||
#include "piintrospection_threads_p.h"
|
||||
#include "pichunkstream.h"
|
||||
#include "pisystemmonitor.h"
|
||||
|
||||
|
||||
@@ -91,13 +92,72 @@ public:
|
||||
|
||||
};
|
||||
|
||||
PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v);
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v);
|
||||
|
||||
PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v);
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v);
|
||||
BINARY_STREAM_WRITE(PIIntrospection::RequiredInfo) {
|
||||
PIChunkStream cs;
|
||||
cs.add(1, v.types);
|
||||
s << cs.data();
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ(PIIntrospection::RequiredInfo) {
|
||||
PIByteArray csba; s >> csba;
|
||||
PIChunkStream cs(csba);
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(v.types); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v);
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v);
|
||||
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);
|
||||
s << cs.data();
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ(PIIntrospection::ProcessInfo) {
|
||||
PIByteArray csba; s >> csba;
|
||||
PIChunkStream cs(csba);
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(v.architecture); break;
|
||||
case 2: cs.get(v.execCommand); break;
|
||||
case 3: cs.get(v.execDateTime); break;
|
||||
case 4: cs.get(v.hostname); break;
|
||||
case 5: cs.get(v.OS_name); break;
|
||||
case 6: cs.get(v.OS_version); break;
|
||||
case 7: cs.get(v.processorsCount); break;
|
||||
case 8: cs.get(v.user); break;
|
||||
case 9: cs.get(v.build_options); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
BINARY_STREAM_WRITE(PIIntrospection::ObjectInfo) {
|
||||
PIChunkStream cs;
|
||||
cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events);
|
||||
s << cs.data();
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ(PIIntrospection::ObjectInfo) {
|
||||
PIByteArray csba; s >> csba;
|
||||
PIChunkStream cs(csba);
|
||||
while (!cs.atEnd()) {
|
||||
switch (cs.read()) {
|
||||
case 1: cs.get(v.classname); break;
|
||||
case 2: cs.get(v.name); break;
|
||||
case 3: cs.get(v.parents); break;
|
||||
case 4: cs.get(v.properties); break;
|
||||
case 5: cs.get(v.queued_events); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // PIINTROSPECTION_SERVER_P_H
|
||||
|
||||
@@ -81,19 +81,3 @@ void PIIntrospectionThreads::threadRunDone(PIThread * t, ullong us) {
|
||||
ThreadInfo & ti(threads[t]);
|
||||
ti.run_us = (ti.run_us * 0.8) + (us * 0.2); /// WARNING
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIByteArray & operator <<(PIByteArray & b, const PIIntrospectionThreads::ThreadInfo & v) {
|
||||
b << v.classname << v.name << v.id << int(v.state) << v.priority << v.delay << v.run_us << v.run_count;
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray & operator >>(PIByteArray & b, PIIntrospectionThreads::ThreadInfo & v) {
|
||||
int st(0);
|
||||
b >> v.classname >> v.name >> v.id >> st >> v.priority >> v.delay >> v.run_us >> v.run_count;
|
||||
v.state = (PIIntrospectionThreads::ThreadState)st;
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,14 @@ public:
|
||||
|
||||
};
|
||||
|
||||
PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospectionThreads::ThreadInfo & v);
|
||||
PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospectionThreads::ThreadInfo & v);
|
||||
|
||||
BINARY_STREAM_WRITE(PIIntrospectionThreads::ThreadInfo) {
|
||||
s << v.classname << v.name << v.id << v.state << v.priority << v.delay << v.run_us << v.run_count;
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ(PIIntrospectionThreads::ThreadInfo) {
|
||||
s >> v.classname >> v.name >> v.id >> v.state >> v.priority >> v.delay >> v.run_us >> v.run_count;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // PIINTROSPECTION_THREADS_P_H
|
||||
|
||||
@@ -61,6 +61,7 @@ PIBinaryLog::PIBinaryLog() {
|
||||
is_started = is_indexed = is_pause = false;
|
||||
current_index = -1;
|
||||
log_size = 0;
|
||||
f_new_path = nullptr;
|
||||
setPlaySpeed(1.);
|
||||
setDefaultID(1);
|
||||
setPlaySpeed(1.0);
|
||||
@@ -100,7 +101,8 @@ bool PIBinaryLog::openDevice() {
|
||||
return false;
|
||||
}
|
||||
if (path().isEmpty() && mode_ == WriteOnly) {
|
||||
setPath(getLogfilePath());
|
||||
if (f_new_path) setPath(f_new_path());
|
||||
else setPath(getLogfilePath(logDir(), filePrefix()));
|
||||
}
|
||||
if (path().isEmpty() && mode_ == ReadOnly) {
|
||||
PIDir ld(logDir());
|
||||
@@ -168,7 +170,7 @@ bool PIBinaryLog::closeDevice() {
|
||||
}
|
||||
|
||||
|
||||
bool PIBinaryLog::threadedRead(uchar *readed, int size) {
|
||||
bool PIBinaryLog::threadedRead(const uchar *readed, int size) {
|
||||
// piCout << "binlog threaded read";
|
||||
if (!canRead() || isEnd()) return PIIODevice::threadedRead(readed, size);
|
||||
is_thread_ok = false;
|
||||
@@ -243,18 +245,18 @@ bool PIBinaryLog::threadedRead(uchar *readed, int size) {
|
||||
}
|
||||
|
||||
|
||||
PIString PIBinaryLog::getLogfilePath() const {
|
||||
PIDir dir(logDir());
|
||||
PIString PIBinaryLog::getLogfilePath(const PIString & log_dir, const PIString & prefix) {
|
||||
PIDir dir(log_dir);
|
||||
dir.setDir(dir.absolutePath());
|
||||
if (!dir.isExists()) {
|
||||
piCoutObj << "Creating directory" << dir.path();
|
||||
piCout << "[PIBinaryLog]" << "Creating directory" << dir.path();
|
||||
dir.make(true);
|
||||
}
|
||||
PIString npath = logDir() + "/" + filePrefix() + 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;
|
||||
while (PIFile::isExists(cnpath)) {
|
||||
cnpath = npath + "_" + PIString::fromNumber(i) + ".binlog";
|
||||
cnpath = npath + '_' + PIString::fromNumber(i) + ".binlog";
|
||||
i++;
|
||||
}
|
||||
return cnpath;
|
||||
@@ -262,12 +264,14 @@ PIString PIBinaryLog::getLogfilePath() const {
|
||||
|
||||
PIString PIBinaryLog::createNewFile() {
|
||||
if (!file.close()) return PIString();
|
||||
PIString cnpath = getLogfilePath();
|
||||
PIString cnpath;
|
||||
if (f_new_path) cnpath = f_new_path();
|
||||
else cnpath = getLogfilePath(logDir(), filePrefix());
|
||||
if (open(cnpath, PIIODevice::WriteOnly)) {
|
||||
newFile(file.path());
|
||||
return file.path();
|
||||
}
|
||||
piCoutObj << "Can't create new file, maybe LogDir is invalid.";
|
||||
piCoutObj << "Can't create new file, maybe LogDir" << ("\"" + logDir() + "\"") << "is invalid.";
|
||||
return PIString();
|
||||
}
|
||||
|
||||
@@ -276,7 +280,7 @@ void PIBinaryLog::createNewFile(const PIString &path) {
|
||||
if (open(path, PIIODevice::WriteOnly)) {
|
||||
newFile(file.path());
|
||||
}
|
||||
else piCoutObj << "Can't create new file, maybe path is invalid.";
|
||||
else piCoutObj << "Can't create new file, maybe path" << ("\"" + path + "\"") << "is invalid.";
|
||||
}
|
||||
|
||||
|
||||
@@ -295,13 +299,20 @@ void PIBinaryLog::setPause(bool pause) {
|
||||
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!";
|
||||
piCoutObj << "Error: can`t write with id = 0! Id must be > 0";
|
||||
return -1;
|
||||
}
|
||||
if (is_pause) return 0;
|
||||
logmutex.lock();
|
||||
PIByteArray logdata;
|
||||
logdata << id << size << (PISystemTime::current() - startlogtime) << PIMemoryBlock(data, size);
|
||||
int res = file.write(logdata.data(), logdata.size());
|
||||
file.flush();
|
||||
write_count++;
|
||||
log_size = file.size();
|
||||
switch (split_mode) {
|
||||
case SplitSize:
|
||||
if (file.size() > split_size) createNewFile();
|
||||
if (log_size > split_size) createNewFile();
|
||||
break;
|
||||
case SplitTime:
|
||||
if ((PISystemTime::current() - startlogtime) > split_time) createNewFile();
|
||||
@@ -311,16 +322,6 @@ int PIBinaryLog::writeBinLog(int id, const void *data, int size) {
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (is_pause) {
|
||||
logmutex.unlock();
|
||||
return 0;
|
||||
}
|
||||
PIByteArray logdata;
|
||||
logdata << id << size << (PISystemTime::current() - startlogtime) << PIByteArray::RawData(data, size);
|
||||
int res = file.write(logdata.data(), logdata.size());
|
||||
file.flush();
|
||||
write_count++;
|
||||
log_size = file.size();
|
||||
logmutex.unlock();
|
||||
if (res > 0) return size;
|
||||
else return res;
|
||||
@@ -330,7 +331,7 @@ int PIBinaryLog::writeBinLog(int id, 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 << PIByteArray::RawData(data, size);
|
||||
logdata << id << size << time << PIMemoryBlock(data, size);
|
||||
logmutex.lock();
|
||||
int res = file.write(logdata.data(), logdata.size());
|
||||
file.flush();
|
||||
@@ -408,8 +409,9 @@ int PIBinaryLog::readDevice(void *read_to, int max_size) {
|
||||
if (max_size <= 0 || read_to == 0) return -1;
|
||||
BinLogRecord br;
|
||||
br.id = 0;
|
||||
if (filterID.isEmpty()) br = readRecord();
|
||||
else {
|
||||
if (filterID.isEmpty()) {
|
||||
br = readRecord();
|
||||
} else {
|
||||
while (!filterID.contains(br.id) && !isEnd()) br = readRecord();
|
||||
}
|
||||
if (br.id == -1) {
|
||||
@@ -428,6 +430,11 @@ int PIBinaryLog::readDevice(void *read_to, int max_size) {
|
||||
}
|
||||
|
||||
|
||||
int PIBinaryLog::writeDevice(const void * data, int size) {
|
||||
return writeBinLog(default_id, data, size);
|
||||
}
|
||||
|
||||
|
||||
void PIBinaryLog::restart() {
|
||||
bool th = isRunning();
|
||||
if (th) stopThreadedRead();
|
||||
@@ -543,15 +550,33 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
|
||||
}
|
||||
uchar read_sig[PIBINARYLOG_SIGNATURE_SIZE];
|
||||
for (uint i=0; i<PIBINARYLOG_SIGNATURE_SIZE; i++) read_sig[i] = 0;
|
||||
bool ok = true;
|
||||
if (f->read(read_sig, PIBINARYLOG_SIGNATURE_SIZE) < 0) {if (info) info->records_count = -1; ok = false;}
|
||||
for (uint i=0; i<PIBINARYLOG_SIGNATURE_SIZE; i++)
|
||||
if (read_sig[i] != binlog_sig[i]) {if (info) info->records_count = -2; ok = false;}
|
||||
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++) {
|
||||
if (read_sig[i] != binlog_sig[i]) {
|
||||
if (info) info->records_count = -2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
uchar read_version = 0;
|
||||
if (f->read(&read_version, 1) < 0) {if (info) info->records_count = -3; ok = false;}
|
||||
if (read_version == 0) {if (info) info->records_count = -4; ok = false;}
|
||||
if (read_version < PIBINARYLOG_VERSION_OLD) {if (info) info->records_count = -5; ok = false;}
|
||||
if (read_version > PIBINARYLOG_VERSION) {if (info) info->records_count = -6; ok = false;}
|
||||
if (f->read(&read_version, 1) < 0) {
|
||||
if (info) info->records_count = -3;
|
||||
return;
|
||||
}
|
||||
if (read_version == 0) {
|
||||
if (info) info->records_count = -4;
|
||||
return;
|
||||
}
|
||||
if (read_version < PIBINARYLOG_VERSION_OLD) {
|
||||
if (info) info->records_count = -5;
|
||||
return;
|
||||
}
|
||||
if (read_version > PIBINARYLOG_VERSION) {
|
||||
if (info) info->records_count = -6;
|
||||
return;
|
||||
}
|
||||
if (read_version == PIBINARYLOG_VERSION) {
|
||||
uint32_t sz = 0;
|
||||
f->read(&sz, 4);
|
||||
@@ -559,9 +584,10 @@ void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector<
|
||||
info->user_header = f->read(sz);
|
||||
}
|
||||
}
|
||||
if (!ok) return;
|
||||
PIByteArray ba;
|
||||
BinLogRecord br;
|
||||
br.id = 0;
|
||||
br.size = 0;
|
||||
bool first = true;
|
||||
size_t hdr_size = sizeof(BinLogRecord) - sizeof(PIByteArray);
|
||||
ba.resize(hdr_size);
|
||||
@@ -570,15 +596,16 @@ 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;
|
||||
if (info->log_size - f->pos() >= br.size)
|
||||
f->seek(f->pos() + br.size);
|
||||
else
|
||||
break;
|
||||
} else break;
|
||||
if (info) {
|
||||
if (info->log_size - f->pos() >= br.size) {
|
||||
f->seek(f->pos() + br.size);
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
if (br.id > 0) {
|
||||
if (info) {
|
||||
if (index) {
|
||||
BinLogIndex bl_ind;
|
||||
bl_ind.id = br.id;
|
||||
bl_ind.data_size = br.size;
|
||||
@@ -631,14 +658,22 @@ 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)) return false;
|
||||
if (!slog.open(src.path, PIIODevice::ReadOnly)) {
|
||||
piCout << "[PIBinaryLog]" << "Error, can't open" << src.path;
|
||||
return false;
|
||||
}
|
||||
PIVector<int> ids = src.records.keys();
|
||||
slog.seekTo(from);
|
||||
PIBinaryLog dlog;
|
||||
dlog.createNewFile(dst);
|
||||
if (!dlog.isOpened()) {
|
||||
piCout << "[PIBinaryLog]" << "Error, can't create" << dst;
|
||||
return false;
|
||||
}
|
||||
bool first = true;
|
||||
BinLogRecord br;
|
||||
PISystemTime st;
|
||||
PITimeMeasurer tm;
|
||||
while (!slog.isEnd() && ((slog.pos() <= to) || to < 0)) {
|
||||
br = slog.readRecord();
|
||||
if (first) {
|
||||
@@ -646,9 +681,74 @@ bool PIBinaryLog::cutBinLog(const PIBinaryLog::BinLogInfo & src, const PIString
|
||||
first = false;
|
||||
}
|
||||
if (ids.contains(br.id)) {
|
||||
dlog.writeBinLog_raw(br.id, br.timestamp - st, br.data);
|
||||
if (dlog.writeBinLog_raw(br.id, br.timestamp - st, br.data) <= 0) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
if (!slog.open(fn, PIIODevice::ReadOnly)) {
|
||||
piCout << "[PIBinaryLog]" << "Error, can't open" << fn;
|
||||
return false;
|
||||
}
|
||||
if (first) {
|
||||
first = false;
|
||||
dlog.setHeader(slog.getHeader());
|
||||
dlog.createNewFile(dst);
|
||||
if (!dlog.isOpened()) {
|
||||
piCout << "[PIBinaryLog]" << "Error, can't create" << dst;
|
||||
return false;
|
||||
}
|
||||
piCout << "[PIBinaryLog]" << "Start join binlogs to" << dst;
|
||||
} else {
|
||||
dtime = lt;
|
||||
}
|
||||
tm.reset();
|
||||
BinLogRecord br;
|
||||
PISystemTime st;
|
||||
while (!slog.isEnd()) {
|
||||
br = slog.readRecord();
|
||||
if (br.data.isEmpty() || br.id < 1) continue;
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
if (tm.elapsed_s() > 0.1) {
|
||||
tm.reset();
|
||||
if (progress) {
|
||||
if (!progress(fn, lt)) {
|
||||
slog.close();
|
||||
dlog.close();
|
||||
PIFile::remove(dlog.path());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
piCout << "[PIBinaryLog]" << "process" << PITime::fromSystemTime(lt).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
slog.close();
|
||||
//piCout << "[PIBinaryLog]" << "complete" << fn;
|
||||
}
|
||||
piCout << "[PIBinaryLog]" << "Finish join binlogs, total time" << PITime::fromSystemTime(lt).toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -728,19 +828,19 @@ bool PIBinaryLog::seek(llong filepos) {
|
||||
|
||||
PIString PIBinaryLog::constructFullPathDevice() const {
|
||||
PIString ret;
|
||||
ret << logDir() << ":" << filePrefix() << ":" << defaultID() << ":";
|
||||
ret += logDir() + ":" + filePrefix() + ":" + PIString::fromNumber(defaultID()) + ":";
|
||||
switch (play_mode) {
|
||||
case PlayRealTime:
|
||||
ret << "RT";
|
||||
ret += "RT";
|
||||
break;
|
||||
case PlayVariableSpeed:
|
||||
ret << PIString::fromNumber(playSpeed()) << "X";
|
||||
ret += PIString::fromNumber(playSpeed()) + "X";
|
||||
break;
|
||||
case PlayStaticDelay:
|
||||
ret << PIString::fromNumber(playDelay().toMilliseconds()) << "M";
|
||||
ret += PIString::fromNumber(playDelay().toMilliseconds()) + "M";
|
||||
break;
|
||||
default:
|
||||
ret << "RT";
|
||||
ret += "RT";
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -28,10 +28,13 @@
|
||||
|
||||
#include "pifile.h"
|
||||
|
||||
|
||||
//! \ingroup IO
|
||||
//! \~\brief
|
||||
//! \~english Binary log
|
||||
//! \~russian Бинарный лог
|
||||
class PIP_EXPORT PIBinaryLog: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PIBinaryLog, "binlog")
|
||||
PIIODEVICE(PIBinaryLog, "binlog");
|
||||
public:
|
||||
explicit PIBinaryLog();
|
||||
virtual ~PIBinaryLog();
|
||||
@@ -165,6 +168,11 @@ public:
|
||||
//! Set pause while playing via \a threadedRead or writing via write
|
||||
void setPause(bool pause);
|
||||
|
||||
//! 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;}
|
||||
|
||||
//! 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());}
|
||||
|
||||
@@ -278,28 +286,33 @@ public:
|
||||
//! \}
|
||||
|
||||
EVENT_HANDLER(PIString, createNewFile);
|
||||
EVENT(fileEnd)
|
||||
EVENT(fileError)
|
||||
EVENT1(newFile, const PIString &, filename)
|
||||
EVENT1(posChanged, int, pos)
|
||||
EVENT(fileEnd);
|
||||
EVENT(fileError);
|
||||
EVENT1(newFile, const PIString &, filename);
|
||||
EVENT1(posChanged, int, pos);
|
||||
|
||||
//! Get binlog info and statistic
|
||||
static BinLogInfo getLogInfo(const PIString & path);
|
||||
|
||||
//! Create new binlog from part of "src" with allowed IDs and "from" to "to" file position
|
||||
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);
|
||||
|
||||
protected:
|
||||
PIString constructFullPathDevice() const;
|
||||
void configureFromFullPathDevice(const PIString & full_path);
|
||||
PIPropertyStorage constructVariantDevice() const;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d);
|
||||
int readDevice(void *read_to, int max_size);
|
||||
int writeDevice(const void * data, int size) {return writeBinLog(default_id, data, size);}
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
void propertyChanged(const char * s);
|
||||
bool threadedRead(uchar *readed, int size);
|
||||
void threadedReadTerminated() {pausemutex.unlock();}
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString & full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
int readDevice(void *read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int size) override;
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
void propertyChanged(const char * s) override;
|
||||
bool threadedRead(const uchar *readed, int size) override;
|
||||
void threadedReadTerminated() override {pausemutex.unlock();}
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
|
||||
|
||||
private:
|
||||
struct PIP_EXPORT BinLogRecord {
|
||||
@@ -314,7 +327,7 @@ private:
|
||||
BinLogRecord readRecord();
|
||||
static void parseLog(PIFile *f, BinLogInfo *info, PIVector<BinLogIndex> * index);
|
||||
void moveIndex(int i);
|
||||
PIString getLogfilePath() const;
|
||||
static PIString getLogfilePath(const PIString & log_dir, const PIString & prefix);
|
||||
|
||||
PIVector<BinLogIndex> index;
|
||||
PIMap<llong, int> index_pos;
|
||||
@@ -331,6 +344,7 @@ private:
|
||||
int write_count, split_count, default_id, current_index;
|
||||
bool is_started, is_thread_ok, is_indexed, rapid_start, is_pause;
|
||||
PIByteArray user_header;
|
||||
std::function<PIString()> f_new_path;
|
||||
};
|
||||
|
||||
//! \relatesalso PICout \brief Output operator PIBinaryLog::BinLogInfo to PICout
|
||||
|
||||
@@ -148,7 +148,7 @@ int PICAN::readedCANID() const {
|
||||
|
||||
PIString PICAN::constructFullPathDevice() const {
|
||||
PIString ret;
|
||||
ret << path() << ":" << PIString::fromNumber(CANID(),16);
|
||||
ret += path() + ":" + PIString::fromNumber(CANID(), 16);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
class PIP_EXPORT PICAN: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PICAN, "can")
|
||||
PIIODEVICE(PICAN, "can");
|
||||
public:
|
||||
explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
||||
virtual ~PICAN();
|
||||
@@ -41,15 +41,15 @@ public:
|
||||
int readedCANID() const;
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int max_size);
|
||||
PIString constructFullPathDevice() const;
|
||||
void configureFromFullPathDevice(const PIString & full_path);
|
||||
PIPropertyStorage constructVariantDevice() const;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d);
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int max_size) override;
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString & full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
|
||||
|
||||
private:
|
||||
int sock;
|
||||
|
||||
@@ -400,7 +400,7 @@ PIString PIConfig::_readLineDev() {
|
||||
void PIConfig::_writeDev(const PIString & l) {
|
||||
//piCout << "write \"" << l << "\"";
|
||||
if (!dev) return;
|
||||
if (PIString(dev->className()) == "PIFile") {*((PIFile*)dev) << (l); return;}
|
||||
if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->write(l.toUTF8()); return;}
|
||||
if (PIString(dev->className()) == "PIIOString") {((PIIOString*)dev)->writeString(l); return;}
|
||||
dev->write(l.toByteArray());
|
||||
}
|
||||
|
||||
@@ -116,9 +116,9 @@ PIEthernet::Address::Address(const PIString & _ip, ushort _port) {
|
||||
|
||||
PIString PIEthernet::Address::ipString() const {
|
||||
PIString ret = PIString::fromNumber(ip_b[0]);
|
||||
ret << "." << PIString::fromNumber(ip_b[1]);
|
||||
ret << "." << PIString::fromNumber(ip_b[2]);
|
||||
ret << "." << PIString::fromNumber(ip_b[3]);
|
||||
ret += "." + PIString::fromNumber(ip_b[1]);
|
||||
ret += "." + PIString::fromNumber(ip_b[2]);
|
||||
ret += "." + PIString::fromNumber(ip_b[3]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -901,7 +901,7 @@ void PIEthernet::server_func(void * eth) {
|
||||
ip += ":" + PIString::fromNumber(htons(client_addr.sin_port));
|
||||
PIEthernet * e = new PIEthernet(s, ip);
|
||||
ce->clients_mutex.lock();
|
||||
CONNECTU(e, deleted, ce, clientDeleted)
|
||||
CONNECT1(void, PIObject *, e, deleted, ce, clientDeleted)
|
||||
ce->clients_ << e;
|
||||
ce->clients_mutex.unlock();
|
||||
ce->newConnection(e);
|
||||
@@ -930,11 +930,12 @@ void PIEthernet::propertyChanged(const char * name) {
|
||||
|
||||
PIString PIEthernet::constructFullPathDevice() const {
|
||||
PIString ret;
|
||||
ret << (type() == PIEthernet::UDP ? "UDP" : "TCP") << ":" << readIP() << ":" << readPort();
|
||||
ret += (type() == PIEthernet::UDP ? "UDP" : "TCP");
|
||||
ret += ":" + readIP() + ":" + PIString::fromNumber(readPort());
|
||||
if (type() == PIEthernet::UDP) {
|
||||
ret << ":" << sendIP() << ":" << sendPort();
|
||||
ret += ":" + sendIP() + ":" + PIString::fromNumber(sendPort());
|
||||
piForeachC (PIString & m, multicastGroups())
|
||||
ret << ":mcast:" << m;
|
||||
ret += ":mcast:" + m;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class
|
||||
|
||||
class PIP_EXPORT PIEthernet: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PIEthernet, "eth")
|
||||
PIIODEVICE(PIEthernet, "eth");
|
||||
friend class PIPeer;
|
||||
public:
|
||||
|
||||
@@ -317,9 +317,9 @@ public:
|
||||
|
||||
int socket() const {return sock;}
|
||||
|
||||
EVENT1(newConnection, PIEthernet * , client)
|
||||
EVENT0(connected)
|
||||
EVENT1(disconnected, bool, withError)
|
||||
EVENT1(newConnection, PIEthernet * , client);
|
||||
EVENT0(connected);
|
||||
EVENT1(disconnected, bool, withError);
|
||||
|
||||
|
||||
//! Flags of network interface
|
||||
@@ -462,24 +462,24 @@ public:
|
||||
protected:
|
||||
explicit PIEthernet(int sock, PIString ip_port);
|
||||
|
||||
void propertyChanged(const char * name);
|
||||
void propertyChanged(const char * name) override;
|
||||
|
||||
PIString constructFullPathDevice() const;
|
||||
void configureFromFullPathDevice(const PIString & full_path);
|
||||
PIPropertyStorage constructVariantDevice() const;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d);
|
||||
bool configureDevice(const void * e_main, const void * e_parent = 0);
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int max_size);
|
||||
DeviceInfoFlags deviceInfoFlags() const;
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString & full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
bool configureDevice(const void * e_main, const void * e_parent = 0) override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int max_size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override;
|
||||
|
||||
//! Executes when any read function was successful. Default implementation does nothing
|
||||
virtual void received(const void * data, int size) {;}
|
||||
|
||||
void construct();
|
||||
bool init();
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
bool init() override;
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
void closeSocket(int & sd);
|
||||
void applyTimeouts();
|
||||
void applyTimeout(int fd, int opt, double ms);
|
||||
|
||||
@@ -452,7 +452,8 @@ void PIFile::setPrecision(int prec) {
|
||||
|
||||
|
||||
PIFile & PIFile::put(const PIByteArray & v) {
|
||||
writeBinary((int)v.size_s());
|
||||
int sz = (int)v.size_s();
|
||||
write(createMemoryBlock(&sz));
|
||||
write(v);
|
||||
return *this;
|
||||
}
|
||||
@@ -461,7 +462,7 @@ PIFile & PIFile::put(const PIByteArray & v) {
|
||||
PIByteArray PIFile::get() {
|
||||
PIByteArray ret;
|
||||
int sz(0);
|
||||
read(&sz, sizeof(sz));
|
||||
read(createMemoryBlock(&sz));
|
||||
if (sz > 0) {
|
||||
ret.resize(sz);
|
||||
read(ret.data(), sz);
|
||||
@@ -470,156 +471,6 @@ PIByteArray PIFile::get() {
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(double v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, ("%" + prec_str + "lf").data(), v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(double & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%lf", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(float & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%f", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(ullong & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%lln", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(ulong & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%ln", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(uint & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%n", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(ushort & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%hn", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(uchar & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%hhn", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(llong & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%lln", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(long & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%ln", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(int & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%n", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(short & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%hn", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator >>(char & v) {
|
||||
if (canRead() && PRIVATE->fd != 0) ret = fscanf(PRIVATE->fd, "%hhn", &v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(float v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, ("%" + prec_str + "f").data(), v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(ullong v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%llu", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(ulong v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%lu", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(uint v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%u", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(ushort v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%hu", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(uchar v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%u", int(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(llong v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%lld", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(long v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%ld", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(int v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%d", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(short v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) ret = fprintf(PRIVATE->fd, "%hd", v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(const PIByteArray & v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) write(v.data(), v.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(const char v) {
|
||||
if (canWrite() && PRIVATE->fd != 0) write(&v, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
int PIFile::readDevice(void * read_to, int max_size) {
|
||||
if (!canRead() || PRIVATE->fd == 0) return -1;
|
||||
return fread(read_to, 1, max_size, PRIVATE->fd);
|
||||
@@ -632,13 +483,6 @@ int PIFile::writeDevice(const void * data, int max_size) {
|
||||
}
|
||||
|
||||
|
||||
PIFile &PIFile::operator <<(const PIString & v) {
|
||||
if (canWrite() && v.isNotEmpty() && PRIVATE->fd != 0)
|
||||
*this << v.toCharset(defaultCharset());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void PIFile::clear() {
|
||||
close();
|
||||
PRIVATE->fd = fopen(path().data(), "w");
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
//! \~russian Локальный файл.
|
||||
class PIP_EXPORT PIFile: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PIFile, "file")
|
||||
PIIODEVICE(PIFile, "file");
|
||||
public:
|
||||
|
||||
//! \~english Constructs file with empty path
|
||||
@@ -180,7 +180,7 @@ public:
|
||||
|
||||
//! \~english Immediate write all buffered data to disk
|
||||
//! \~russian Немедленно записывает все буферизированные данные на диск
|
||||
void flush();
|
||||
void flush() override;
|
||||
|
||||
//! \~english Move read/write position to "position"
|
||||
//! \~russian Перемещает позицию чтения/записи на "position"
|
||||
@@ -226,6 +226,8 @@ public:
|
||||
//! \~english Returns file size in bytes
|
||||
//! \~russian Возвращает размер файла в байтах
|
||||
llong size() const;
|
||||
|
||||
ssize_t bytesAvailable() const override {return size() - pos();}
|
||||
|
||||
//! \~english Returns read/write position
|
||||
//! \~russian Возвращает позицию чтения/записи
|
||||
@@ -260,161 +262,6 @@ public:
|
||||
//! \~russian Читает из файла размер байтового массива и его содержимое (десериализация)
|
||||
PIByteArray get();
|
||||
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const llong v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const ullong v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
//! \~english Write to file binary content of "v"
|
||||
//! \~russian Пишет в файл байтовое содержимое "v"
|
||||
PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;}
|
||||
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(const char v);
|
||||
|
||||
//! \~english Write to file string "v"
|
||||
//! \~russian Пишет в файл строку "v"
|
||||
PIFile & operator <<(const PIString & v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(const PIByteArray & v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(short v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(int v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(long v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(llong v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(uchar v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(ushort v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(uint v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(ulong v);
|
||||
|
||||
//! \~english Write to file text representation of "v"
|
||||
//! \~russian Пишет в файл текстовое представление "v"
|
||||
PIFile & operator <<(ullong v);
|
||||
|
||||
//! \~english Write to file text representation of "v" with precision \a precision()
|
||||
//! \~russian Пишет в файл текстовое представление "v" с точностью \a precision()
|
||||
PIFile & operator <<(float v);
|
||||
|
||||
//! \~english Write to file text representation of "v" with precision \a precision()
|
||||
//! \~russian Пишет в файл текстовое представление "v" с точностью \a precision()
|
||||
PIFile & operator <<(double v);
|
||||
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(char & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(short & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(int & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(long & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(llong & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(uchar & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(ushort & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(uint & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(ulong & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(ullong & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(float & v);
|
||||
|
||||
//! \~english Read from file text representation of "v"
|
||||
//! \~russian Читает из файла текстовое представление "v"
|
||||
PIFile & operator >>(double & v);
|
||||
|
||||
EVENT_HANDLER(void, clear);
|
||||
EVENT_HANDLER(void, remove);
|
||||
EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);}
|
||||
@@ -479,15 +326,15 @@ public:
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
PIString constructFullPathDevice() const;
|
||||
void configureFromFullPathDevice(const PIString & full_path);
|
||||
PIPropertyStorage constructVariantDevice() const;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d);
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int max_size);
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Sequential | PIIODevice::Reliable;}
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString & full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int max_size) override;
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Sequential | PIIODevice::Reliable;}
|
||||
|
||||
private:
|
||||
PIString strType(const PIIODevice::DeviceMode type);
|
||||
@@ -518,14 +365,19 @@ inline PICout operator <<(PICout s, const PIFile::FileInfo & v) {
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIFile::FileInfo & v) {s << v.path << v.size << v.time_access << v.time_modification <<
|
||||
(int)v.flags << v.id_user << v.id_group << v.perm_user.raw << v.perm_group.raw << v.perm_other.raw; return s;}
|
||||
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;
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIFile::FileInfo & v) {s >> v.path >> v.size >> v.time_access >> v.time_modification >>
|
||||
*(int*)(&(v.flags)) >> v.id_user >> v.id_group >> v.perm_user.raw >> v.perm_group.raw >> v.perm_other.raw; return s;}
|
||||
|
||||
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;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // PIFILE_H
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
//! \~russian Поддержка GPIO.
|
||||
class PIP_EXPORT PIGPIO: public PIThread
|
||||
{
|
||||
PIOBJECT_SUBCLASS(PIGPIO, PIThread)
|
||||
PIOBJECT_SUBCLASS(PIGPIO, PIThread);
|
||||
public:
|
||||
|
||||
//! \~english Work mode for pin
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
//! \~russian Заканчивает наблюдение за всеми пинами
|
||||
void clearWatch();
|
||||
|
||||
EVENT2(pinChanged, int, gpio_num, bool, new_value)
|
||||
EVENT2(pinChanged, int, gpio_num, bool, new_value);
|
||||
|
||||
//! \events
|
||||
//! \{
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
private:
|
||||
PIGPIO();
|
||||
virtual ~PIGPIO();
|
||||
NO_COPY_CLASS(PIGPIO)
|
||||
NO_COPY_CLASS(PIGPIO);
|
||||
|
||||
struct PIP_EXPORT GPIOData {
|
||||
GPIOData() {dir = PIGPIO::In; num = fd = -1;}
|
||||
@@ -112,9 +112,9 @@ private:
|
||||
void exportGPIO(int gpio_num);
|
||||
void openGPIO(GPIOData & g);
|
||||
bool getPinState(int gpio_num);
|
||||
void begin();
|
||||
void run();
|
||||
void end();
|
||||
void begin() override;
|
||||
void run() override;
|
||||
void end() override;
|
||||
|
||||
static PIString GPIOName(int gpio_num);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
//! \~russian Обёртка PIIODevice вокруг PIByteArray
|
||||
class PIP_EXPORT PIIOByteArray: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PIIOByteArray, "")
|
||||
PIIODEVICE(PIIOByteArray, "");
|
||||
public:
|
||||
|
||||
//! \~english Contructs %PIIOByteArray with "buffer" content and "mode" open mode
|
||||
@@ -83,12 +83,17 @@ public:
|
||||
//! \~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;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
int readDevice(void * read_to, int size);
|
||||
int writeDevice(const void * data_, int size);
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Sequential | PIIODevice::Reliable;}
|
||||
bool openDevice() override;
|
||||
int readDevice(void * read_to, int size) override;
|
||||
int writeDevice(const void * data_, int size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Sequential | PIIODevice::Reliable;}
|
||||
|
||||
ssize_t pos;
|
||||
PIByteArray * data_;
|
||||
|
||||
@@ -159,7 +159,7 @@ bool PIIODevice::setOption(PIIODevice::DeviceOption o, bool yes) {
|
||||
//! после каждого успешного потокового чтения. Метод должен быть
|
||||
//! в формате "bool func(void * data, uchar * readed, int size)"
|
||||
void PIIODevice::setThreadedReadSlot(ReadRetFunc func) {
|
||||
ret_func_ = func;
|
||||
func_read = func;
|
||||
}
|
||||
|
||||
|
||||
@@ -230,8 +230,7 @@ void PIIODevice::stop(bool hard) {
|
||||
PIByteArray PIIODevice::read(int max_size) {
|
||||
buffer_in.resize(max_size);
|
||||
int ret = readDevice(buffer_in.data(), max_size);
|
||||
if (ret < 0)
|
||||
return PIByteArray();
|
||||
if (ret < 0) return PIByteArray();
|
||||
return buffer_in.resized(ret);
|
||||
}
|
||||
|
||||
@@ -239,8 +238,8 @@ PIByteArray PIIODevice::read(int max_size) {
|
||||
void PIIODevice::_init() {
|
||||
opened_ = init_ = thread_started_ = false;
|
||||
raise_threaded_read_ = true;
|
||||
ret_func_ = 0;
|
||||
ret_data_ = 0;
|
||||
func_read = nullptr;
|
||||
ret_data_ = nullptr;
|
||||
tri = 0;
|
||||
setOptions(0);
|
||||
setReopenEnabled(true);
|
||||
@@ -596,9 +595,9 @@ PIMap<PIConstChars, PIIODevice::FabricInfo> & PIIODevice::fabrics() {
|
||||
}
|
||||
|
||||
|
||||
bool PIIODevice::threadedRead(uchar *readed, int size) {
|
||||
bool PIIODevice::threadedRead(const uchar *readed, int size) {
|
||||
// piCout << "iodevice threaded read";
|
||||
if (ret_func_ != 0) return ret_func_(ret_data_, readed, size);
|
||||
if (func_read != 0) return func_read(readed, size, ret_data_);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
#include "pitimer.h"
|
||||
#include "piqueue.h"
|
||||
|
||||
|
||||
// function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData
|
||||
typedef bool (*ReadRetFunc)(void * , uchar * , int );
|
||||
/// TODO: написать документацию, тут ничего не понятно
|
||||
// function executed from threaded read, pass readedData, sizeOfData, ThreadedReadData
|
||||
typedef bool (*ReadRetFunc)(const uchar *, int, void *);
|
||||
|
||||
|
||||
#ifdef DOXYGEN
|
||||
@@ -64,9 +64,9 @@ typedef bool (*ReadRetFunc)(void * , uchar * , int );
|
||||
|
||||
# define PIIODEVICE(name, prefix) \
|
||||
PIOBJECT_SUBCLASS(name, PIIODevice) \
|
||||
PIIODevice * copy() const {return new name();} \
|
||||
PIIODevice * copy() const override {return new name();} \
|
||||
public: \
|
||||
virtual PIConstChars fullPathPrefix() const {return prefix;} \
|
||||
PIConstChars fullPathPrefix() const override {return prefix;} \
|
||||
static PIConstChars fullPathPrefixS() {return prefix;} \
|
||||
private:
|
||||
|
||||
@@ -79,10 +79,10 @@ typedef bool (*ReadRetFunc)(void * , uchar * , int );
|
||||
//! \~russian Базовый класс утройств ввода/вывода.
|
||||
class PIP_EXPORT PIIODevice: public PIThread
|
||||
{
|
||||
PIOBJECT_SUBCLASS(PIIODevice, PIThread)
|
||||
PIOBJECT_SUBCLASS(PIIODevice, PIThread);
|
||||
friend void __DevicePool_threadReadDP(void * ddp);
|
||||
public:
|
||||
NO_COPY_CLASS(PIIODevice)
|
||||
NO_COPY_CLASS(PIIODevice);
|
||||
|
||||
//! \~english Constructs a empty %PIIODevice
|
||||
//! \~russian Создает пустой %PIIODevice
|
||||
@@ -239,7 +239,7 @@ public:
|
||||
|
||||
//! \~english Start threaded read and assign threaded read callback to "func"
|
||||
//! \~russian Запускает потоковое чтение и устанавливает callback потокового чтения в "func"
|
||||
void startThreadedRead(ReadRetFunc func) {ret_func_ = func; startThreadedRead();}
|
||||
void startThreadedRead(ReadRetFunc func) {func_read = func; startThreadedRead();}
|
||||
|
||||
//! \~english Stop threaded read. Hard stop terminate thread, otherwise wait fo 10 seconds
|
||||
//! \~russian Останавливает потоковое чтение. Жесткая остановка убивает поток, иначе ожидает 10 секунд
|
||||
@@ -276,10 +276,25 @@ public:
|
||||
//! \~russian Читает из устройства не более "max_size" байт в "read_to"
|
||||
int read(void * read_to, int max_size) {return readDevice(read_to, max_size);}
|
||||
|
||||
//! \~english Read from device to memory block "mb"
|
||||
//! \~russian Читает из устройства в блок памяти "mb"
|
||||
int read(PIMemoryBlock mb) {return readDevice(mb.data(), mb.size());}
|
||||
|
||||
//! \~english Read from device maximum "max_size" bytes and returns them as PIByteArray
|
||||
//! \~russian Читает из устройства не более "max_size" байт и возвращает данные как PIByteArray
|
||||
PIByteArray read(int max_size);
|
||||
|
||||
//! \~english Returns the number of bytes that are available for reading.
|
||||
//! \~russian Возвращает количество байт доступных для чтения
|
||||
//! \~\details
|
||||
//! \~english This function is commonly used with sequential devices
|
||||
//! to determine the number of bytes to allocate in a buffer before reading.
|
||||
//! If function returns -1 it mean that number of bytes undefined.
|
||||
//! \~russian Эта функция как правило используется чтобы знать какой
|
||||
//! размер буфера нужен в памяти для чтения.
|
||||
//! Если функция возвращает -1 это значит что количество байт для чтения не известно.
|
||||
virtual ssize_t bytesAvailable() const {return -1;}
|
||||
|
||||
//! \~english Write maximum "max_size" bytes of "data" to device
|
||||
//! \~russian Пишет в устройство не более "max_size" байт из "data"
|
||||
int write(const void * data, int max_size) {return writeDevice(data, max_size);}
|
||||
@@ -357,12 +372,16 @@ public:
|
||||
EVENT_HANDLER(bool, close);
|
||||
EVENT_HANDLER1(int, write, PIByteArray, data);
|
||||
|
||||
//! \~english Write memory block "mb" to device
|
||||
//! \~russian Пишет в устройство блок памяти "mb"
|
||||
int write(const PIMemoryBlock & mb) {return write(mb.data(), mb.size());}
|
||||
|
||||
EVENT_VHANDLER(void, flush) {;}
|
||||
|
||||
EVENT(opened)
|
||||
EVENT(closed)
|
||||
EVENT2(threadedReadEvent, uchar * , readed, int, size)
|
||||
EVENT2(threadedWriteEvent, ullong, id, int, written_size)
|
||||
EVENT(opened);
|
||||
EVENT(closed);
|
||||
EVENT2(threadedReadEvent, const uchar * , readed, int, size);
|
||||
EVENT2(threadedWriteEvent, ullong, id, int, written_size);
|
||||
|
||||
//! \handlers
|
||||
//! \{
|
||||
@@ -411,7 +430,7 @@ public:
|
||||
//! \~english Raise if succesfull close
|
||||
//! \~russian Вызывается при успешном закрытии
|
||||
|
||||
//! \fn void threadedReadEvent(uchar * readed, int size)
|
||||
//! \fn void threadedReadEvent(const uchar * readed, int size)
|
||||
//! \~english Raise if read thread succesfull read some data
|
||||
//! \~russian Вызывается при успешном потоковом чтении данных
|
||||
|
||||
@@ -467,7 +486,7 @@ protected:
|
||||
|
||||
//! \~english Function executed when thread read some data, default implementation execute external callback "ret_func_"
|
||||
//! \~russian Метод вызывается после каждого успешного потокового чтения, по умолчанию вызывает callback "ret_func_"
|
||||
virtual bool threadedRead(uchar * readed, int size);
|
||||
virtual bool threadedRead(const uchar * readed, int size);
|
||||
|
||||
//! \~english Reimplement to construct full unambiguous string, describes this device.
|
||||
//! Default implementation returns \a path()
|
||||
@@ -520,7 +539,7 @@ protected:
|
||||
|
||||
DeviceMode mode_;
|
||||
DeviceOptions options_;
|
||||
ReadRetFunc ret_func_;
|
||||
ReadRetFunc func_read;
|
||||
bool opened_;
|
||||
void * ret_data_;
|
||||
|
||||
@@ -528,12 +547,12 @@ private:
|
||||
EVENT_HANDLER2(void, check_start, void * , data, int, delim);
|
||||
EVENT_HANDLER(void, write_func);
|
||||
|
||||
virtual PIIODevice * copy() const {return 0;}
|
||||
virtual PIIODevice * copy() const {return nullptr;}
|
||||
PIString fullPathOptions() const;
|
||||
void _init();
|
||||
void begin();
|
||||
void run();
|
||||
void end() {terminate();}
|
||||
void begin() override;
|
||||
void run() override;
|
||||
void end() override {terminate();}
|
||||
static void cacheFullPath(const PIString & full_path, const PIIODevice * d);
|
||||
static PIMap<PIConstChars, FabricInfo> & fabrics();
|
||||
|
||||
|
||||
104
libs/main/io_devices/piiostream.h
Normal file
104
libs/main/io_devices/piiostream.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*! \file piiostream.h
|
||||
* \ingroup IO
|
||||
* \~\brief
|
||||
* \~english PIBinaryStream functionality for PIIODevice
|
||||
* \~russian Функциональность PIBinaryStream для PIIODevice
|
||||
*/
|
||||
/*
|
||||
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 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 PIIOSTREAM_H
|
||||
#define PIIOSTREAM_H
|
||||
|
||||
#include "piiostring.h"
|
||||
#include "pitextstream.h"
|
||||
|
||||
|
||||
//! \ingroup IO
|
||||
//! \~\brief
|
||||
//! \~english PIBinaryStream functionality for PIIODevice.
|
||||
//! \~russian Функциональность PIBinaryStream для PIIODevice.
|
||||
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;}
|
||||
|
||||
bool binaryStreamAppendImp(const void * d, size_t s) {
|
||||
if (!dev) return false;
|
||||
return (dev->write(d, s) == (int)s);
|
||||
}
|
||||
|
||||
bool binaryStreamTakeImp(void * d, size_t s) {
|
||||
if (!dev) return false;
|
||||
return (dev->read(d, s) == (int)s);
|
||||
}
|
||||
|
||||
ssize_t binaryStreamSizeImp() const {
|
||||
if (!dev) return 0;
|
||||
return dev->bytesAvailable();
|
||||
}
|
||||
|
||||
private:
|
||||
PIIODevice * dev;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! \ingroup IO
|
||||
//! \~\brief
|
||||
//! \~english PITextStream functionality for PIIODevice.
|
||||
//! \~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) {}
|
||||
|
||||
//! \~english Contructs %PIIOTextStream for "string" string
|
||||
//! \~russian Создает %PIIOTextStream для строки "string"
|
||||
PIIOTextStream(PIString * string): PITextStream<PIIOBinaryStream>(&bin_stream) {
|
||||
io_string = new PIIOString(string);
|
||||
bin_stream.setDevice(io_string);
|
||||
}
|
||||
|
||||
~PIIOTextStream() {
|
||||
if (io_string)
|
||||
delete io_string;
|
||||
}
|
||||
|
||||
void setDevice(PIIODevice * device) {
|
||||
bin_stream = PIIOBinaryStream(device);
|
||||
setStream(&bin_stream);
|
||||
}
|
||||
|
||||
private:
|
||||
PIIOString * io_string = nullptr;
|
||||
PIIOBinaryStream bin_stream;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // PIIOSTREAM_H
|
||||
@@ -56,9 +56,9 @@ bool PIIOString::open(const PIString & string) {
|
||||
PIString PIIOString::readLine() {
|
||||
if (!canRead() || !str) return PIString();
|
||||
int np = pos;
|
||||
while (++np < str->size_s())
|
||||
if ((*str)[np] == '\n')
|
||||
break;
|
||||
while (++np < str->size_s()) {
|
||||
if ((*str)[np] == '\n') break;
|
||||
}
|
||||
PIString ret = str->mid(pos, np - pos);
|
||||
pos = piMini(np + 1, str->size_s());
|
||||
return ret;
|
||||
@@ -66,7 +66,7 @@ PIString PIIOString::readLine() {
|
||||
|
||||
|
||||
int PIIOString::readDevice(void * read_to, int max_size) {
|
||||
if (!canRead() || !str) return -1;
|
||||
if (!canRead() || !str || max_size <= 0) return -1;
|
||||
PIString rs = str->mid(pos, max_size);
|
||||
pos += max_size;
|
||||
if (pos > str->size_s()) pos = str->size_s();
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
//! \~russian Обёртка PIIODevice вокруг PIString.
|
||||
class PIP_EXPORT PIIOString: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PIIOString, "")
|
||||
PIIODEVICE(PIIOString, "");
|
||||
public:
|
||||
|
||||
//! \~english Contructs %PIIOString with "string" content and "mode" open mode
|
||||
@@ -88,11 +88,16 @@ public:
|
||||
//! \~russian Вставляет строку "string" в содержимое буфера в текущую позицию
|
||||
int writeString(const PIString & string);
|
||||
|
||||
ssize_t bytesAvailable() const override {
|
||||
if (str) return str->size() - pos;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int max_size);
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Sequential | PIIODevice::Reliable;}
|
||||
bool openDevice() override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int max_size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Sequential | PIIODevice::Reliable;}
|
||||
|
||||
ssize_t pos;
|
||||
PIString * str;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#define _PIPEER_PING_TIMEOUT 5.0
|
||||
|
||||
class PIPeer::PeerData: public PIObject {
|
||||
PIOBJECT_SUBCLASS(PeerData, PIObject)
|
||||
PIOBJECT_SUBCLASS(PeerData, PIObject);
|
||||
public:
|
||||
PeerData(const PIString & n);
|
||||
~PeerData();
|
||||
@@ -45,8 +45,8 @@ public:
|
||||
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)
|
||||
EVENT2(received, const PIString &, from, const PIByteArray &, data);
|
||||
EVENT2(sendRequest, const PIString &, to, const PIByteArray &, data);
|
||||
bool send(const PIByteArray & d);
|
||||
void receivedPacket(uchar type, const PIByteArray & d);
|
||||
void setDist(int dist);
|
||||
@@ -61,11 +61,11 @@ PIPeer::PeerData::PeerData(const PIString & n): PIObject(n) {
|
||||
dt_out.setPacketSize(_PIPEER_MSG_SIZE);
|
||||
dt_in.setCRCEnabled(false);
|
||||
dt_out.setCRCEnabled(false);
|
||||
CONNECTU(&dt_in, sendRequest, this, dtSendRequestIn)
|
||||
CONNECTU(&dt_out, sendRequest, this, dtSendRequestOut)
|
||||
CONNECTU(&dt_in, receiveFinished, this, dtReceiveFinishedIn)
|
||||
CONNECTU(&dt_out, receiveFinished, this, dtReceiveFinishedOut)
|
||||
CONNECTU(&t, started, this, dtThread)
|
||||
CONNECT1(void, PIByteArray &, &dt_in, sendRequest, this, dtSendRequestIn);
|
||||
CONNECT1(void, PIByteArray &, &dt_out, sendRequest, this, dtSendRequestOut);
|
||||
CONNECT1(void, bool, &dt_in, receiveFinished, this, dtReceiveFinishedIn);
|
||||
CONNECT1(void, bool, &dt_out, receiveFinished, this, dtReceiveFinishedOut);
|
||||
CONNECT0(void, &t, started, this, dtThread);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ PIPeer::PIPeer(const PIString & n): PIIODevice(), inited__(false), eth_tcp_srv(P
|
||||
self_info.dist = 0;
|
||||
self_info.time = PISystemTime::current();
|
||||
randomize();
|
||||
CONNECTU(&sync_timer, tickEvent, this, timerEvent);
|
||||
CONNECT2(void, void *, int, &sync_timer, tickEvent, this, timerEvent);
|
||||
prev_ifaces = PIEthernet::interfaces();
|
||||
no_timer = false;
|
||||
sync_timer.addDelimiter(5);
|
||||
@@ -247,7 +247,7 @@ void PIPeer::initEths(PIStringList al) {
|
||||
eths_traffic << ce;
|
||||
cint = prev_ifaces.getByAddress(a);
|
||||
self_info.addresses << PeerInfo::PeerAddress(ce->path(), cint == 0 ? "255.255.255.0" : cint->netmask);
|
||||
CONNECTU(ce, threadedReadEvent, this, dataRead);
|
||||
CONNECT2(void, const uchar *, int, ce, threadedReadEvent, this, dataRead);
|
||||
ce->startThreadedRead();
|
||||
// piCoutObj << "dc binded to" << ce->path();
|
||||
// piCoutObj << "add eth" << a;
|
||||
@@ -282,7 +282,7 @@ void PIPeer::initMBcasts(PIStringList al) {
|
||||
ce->joinMulticastGroup(_PIPEER_MULTICAST_IP);
|
||||
if (ce->open()) {
|
||||
eths_mcast << ce;
|
||||
CONNECTU(ce, threadedReadEvent, this, mbcastRead);
|
||||
CONNECT2(void, const uchar *, int, ce, threadedReadEvent, this, mbcastRead);
|
||||
ce->startThreadedRead();
|
||||
// piCout << "mcast bind to" << a << ce->sendIP();
|
||||
} else {
|
||||
@@ -302,7 +302,7 @@ void PIPeer::initMBcasts(PIStringList al) {
|
||||
ce->setReadAddress(a, _PIPEER_BROADCAST_PORT);
|
||||
if (ce->open()) {
|
||||
eths_bcast << ce;
|
||||
CONNECTU(ce, threadedReadEvent, this, mbcastRead);
|
||||
CONNECT2(void, const uchar *, int, ce, threadedReadEvent, this, mbcastRead);
|
||||
ce->startThreadedRead();
|
||||
// piCout << "mc BC try" << a << nm << ce->sendIP();
|
||||
// piCout << "bcast bind to" << a << nm;
|
||||
@@ -319,7 +319,7 @@ void PIPeer::initMBcasts(PIStringList al) {
|
||||
eth_lo.setReadAddress("127.0.0.1", p);
|
||||
if (eth_lo.open()) {
|
||||
eth_lo.setSendIP("127.0.0.1");
|
||||
CONNECTU(ð_lo, threadedReadEvent, this, mbcastRead);
|
||||
CONNECT2(void, const uchar *, int, ð_lo, threadedReadEvent, this, mbcastRead);
|
||||
eth_lo.startThreadedRead();
|
||||
// piCout << "lo binded to" << eth_lo.readAddress() << eth_lo.sendAddress();
|
||||
//piCout << "add eth" << ta;
|
||||
@@ -330,13 +330,13 @@ void PIPeer::initMBcasts(PIStringList al) {
|
||||
eth_tcp_srv.init();
|
||||
eth_tcp_srv.listen("0.0.0.0", _PIPEER_TCP_PORT, true);
|
||||
eth_tcp_srv.setDebug(false);
|
||||
CONNECTU(ð_tcp_srv, newConnection, this, newTcpClient);
|
||||
CONNECT1(void, PIEthernet *, ð_tcp_srv, newConnection, this, newTcpClient);
|
||||
eth_tcp_srv.startThreadedRead();
|
||||
eth_tcp_cli.setName("__S__PIPeer_eth_TCP_Client");
|
||||
eth_tcp_cli.init();
|
||||
eth_tcp_cli.setDebug(false);
|
||||
tcpClientReconnect();
|
||||
CONNECTU(ð_tcp_cli, threadedReadEvent, this, mbcastRead);
|
||||
CONNECT2(void, const uchar *, int, ð_tcp_cli, threadedReadEvent, this, mbcastRead);
|
||||
CONNECTU(ð_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!";
|
||||
@@ -444,7 +444,7 @@ void PIPeer::dtReceived(const PIString & from, const PIByteArray & data) {
|
||||
}
|
||||
|
||||
|
||||
bool PIPeer::dataRead(uchar * readed, int size) {
|
||||
bool PIPeer::dataRead(const uchar * readed, int size) {
|
||||
if (destroyed) {
|
||||
//piCout << "[PIPeer] SegFault";
|
||||
return true;
|
||||
@@ -561,7 +561,7 @@ bool PIPeer::dataRead(uchar * readed, int size) {
|
||||
}
|
||||
|
||||
|
||||
bool PIPeer::mbcastRead(uchar * data, int size) {
|
||||
bool PIPeer::mbcastRead(const uchar * data, int size) {
|
||||
if (destroyed) {
|
||||
//piCout << "[PIPeer] SegFault";
|
||||
return true;
|
||||
@@ -573,7 +573,7 @@ bool PIPeer::mbcastRead(uchar * data, int size) {
|
||||
if (type <= 0 || type >= 4) return true;
|
||||
PeerInfo pi;
|
||||
ba >> pi.name;
|
||||
// piCoutObj << "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);
|
||||
@@ -765,8 +765,8 @@ void PIPeer::addPeer(const PIPeer::PeerInfo & pd) {
|
||||
peers << pd;
|
||||
PeerInfo & p(peers.back());
|
||||
p.init();
|
||||
CONNECTU(p._data, sendRequest, this, sendInternal)
|
||||
CONNECTU(p._data, received, this, dtReceived)
|
||||
CONNECT2(void, const PIString &, const PIByteArray &, p._data, sendRequest, this, sendInternal)
|
||||
CONNECT2(void, const PIString &, const PIByteArray &, p._data, received, this, dtReceived)
|
||||
}
|
||||
|
||||
|
||||
@@ -789,6 +789,7 @@ void PIPeer::sendPeerInfo(const PeerInfo & info) {
|
||||
|
||||
|
||||
void PIPeer::sendPeerRemove(const PIString & peer) {
|
||||
//piCout << name() << "sendPeerRemove" << peer;
|
||||
PIByteArray ba;
|
||||
ba << int(2) << peer;
|
||||
sendMBcast(ba);
|
||||
@@ -858,7 +859,7 @@ void PIPeer::syncPeers() {
|
||||
PeerInfo & cp(peers[i]);
|
||||
if (cp.sync > 3) {
|
||||
pn = cp.name;
|
||||
//piCoutObj << "sync: remove " << pn;
|
||||
//piCout << "sync: remove " << pn;
|
||||
cp.destroy();
|
||||
addToRemoved(cp);
|
||||
peers.remove(i);
|
||||
@@ -923,6 +924,15 @@ void PIPeer::changeName(const PIString &new_name) {
|
||||
}
|
||||
|
||||
|
||||
ssize_t PIPeer::bytesAvailable() const {
|
||||
ssize_t ret = 0;
|
||||
read_buffer_mutex.lock();
|
||||
if (!read_buffer.isEmpty()) ret = read_buffer.back().size();
|
||||
read_buffer_mutex.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int PIPeer::readDevice(void *read_to, int max_size) {
|
||||
read_buffer_mutex.lock();
|
||||
bool empty = read_buffer.isEmpty();
|
||||
@@ -960,14 +970,14 @@ int PIPeer::writeDevice(const void *data, int size) {
|
||||
void PIPeer::newTcpClient(PIEthernet *client) {
|
||||
client->setName("__S__PIPeer_eth_TCP_ServerClient" + client->path());
|
||||
piCoutObj << "client" << client->path();
|
||||
CONNECTU(client, threadedReadEvent, this, mbcastRead);
|
||||
CONNECT2(void, const uchar *, int, client, threadedReadEvent, this, mbcastRead);
|
||||
client->startThreadedRead();
|
||||
}
|
||||
|
||||
|
||||
PIString PIPeer::constructFullPathDevice() const {
|
||||
PIString ret;
|
||||
ret << self_info.name << ":" << trustPeerName();
|
||||
ret += self_info.name + ":" + trustPeerName();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1008,8 +1018,9 @@ void PIPeer::initNetwork() {
|
||||
self_info.addresses.clear();
|
||||
PIVector<PIEthernet::Address> al = PIEthernet::allAddresses();
|
||||
PIStringList sl;
|
||||
piForeachC (PIEthernet::Address & a, al)
|
||||
for (const PIEthernet::Address & a : al) {
|
||||
sl << a.ipString();
|
||||
}
|
||||
initEths(sl);
|
||||
// piCoutObj << sl << self_info.addresses.size();
|
||||
sl.removeAll("127.0.0.1");
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
class PIP_EXPORT PIPeer: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PIPeer, "peer")
|
||||
PIIODEVICE(PIPeer, "peer");
|
||||
private:
|
||||
class PeerData;
|
||||
|
||||
@@ -41,8 +41,7 @@ public:
|
||||
|
||||
class PIP_EXPORT PeerInfo {
|
||||
friend class PIPeer;
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v);
|
||||
BINARY_STREAM_FRIEND(PIPeer::PeerInfo);
|
||||
public:
|
||||
PeerInfo() {dist = sync = cnt = 0; trace = -1; was_update = false; _data = 0;}
|
||||
~PeerInfo() {}
|
||||
@@ -80,9 +79,8 @@ public:
|
||||
PeerData * _data;
|
||||
|
||||
};
|
||||
|
||||
friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v);
|
||||
friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v);
|
||||
|
||||
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());}
|
||||
@@ -118,10 +116,12 @@ public:
|
||||
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)
|
||||
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();}
|
||||
@@ -134,8 +134,8 @@ protected:
|
||||
virtual void peerConnected(const PIString & name) {;}
|
||||
virtual void peerDisconnected(const PIString & name) {;}
|
||||
|
||||
EVENT_HANDLER2(bool, dataRead, uchar *, readed, int, size);
|
||||
EVENT_HANDLER2(bool, mbcastRead, uchar *, readed, int, size);
|
||||
EVENT_HANDLER2(bool, dataRead, const uchar *, readed, int, size);
|
||||
EVENT_HANDLER2(bool, mbcastRead, const uchar *, readed, int, size);
|
||||
|
||||
private:
|
||||
EVENT_HANDLER2(void, timerEvent, void * , data, int, delim);
|
||||
@@ -166,15 +166,15 @@ private:
|
||||
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();
|
||||
bool closeDevice();
|
||||
PIString constructFullPathDevice() const;
|
||||
void configureFromFullPathDevice(const PIString &full_path);
|
||||
PIPropertyStorage constructVariantDevice() const;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d);
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int size);
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString &full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
|
||||
|
||||
PeerInfo * quickestPeer(const PIString & to);
|
||||
bool sendToNeighbour(PeerInfo * peer, const PIByteArray & ba);
|
||||
@@ -200,7 +200,7 @@ private:
|
||||
bool destroyed, no_timer;
|
||||
PIString trust_peer;
|
||||
PIString server_ip;
|
||||
PIMutex read_buffer_mutex;
|
||||
mutable PIMutex read_buffer_mutex;
|
||||
PIQueue<PIByteArray> read_buffer;
|
||||
int read_buffer_size;
|
||||
PIMutex mc_mutex, eth_mutex, peers_mutex, send_mutex, send_mc_mutex;
|
||||
@@ -209,10 +209,10 @@ private:
|
||||
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 PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo::PeerAddress & v) {s << v.address << v.netmask << v.ping; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo::PeerAddress & v) {s >> v.address >> v.netmask >> v.ping; return s;}
|
||||
BINARY_STREAM_WRITE(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;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v) {s << v.name << v.addresses << v.dist << v.neighbours << v.cnt << v.time; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v) {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;}
|
||||
BINARY_STREAM_READ (PIPeer::PeerInfo) {s >> v.name >> v.addresses >> v.dist >> v.neighbours >> v.cnt >> v.time; return s;}
|
||||
|
||||
#endif // PIPEER_H
|
||||
|
||||
@@ -433,8 +433,13 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
|
||||
case S4000000: return B4000000;
|
||||
default: break;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
piCoutObj << "Warning: Custom speed" << (int)speed;
|
||||
return (int)speed;
|
||||
#else
|
||||
piCoutObj << "Warning: Unknown speed" << (int)speed << ", using 115200";
|
||||
return B115200;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -516,14 +521,14 @@ PIString PISerial::readString(int size, double timeout_ms) {
|
||||
while (tm_.elapsed_m() < timeout_ms) {
|
||||
ret = readDevice(td, 1024);
|
||||
if (ret <= 0) piMinSleep();
|
||||
else str << PIString((char*)td, ret);
|
||||
else str += PIString((char*)td, ret);
|
||||
}
|
||||
} else {
|
||||
while (all < size && tm_.elapsed_m() < timeout_ms) {
|
||||
ret = readDevice(td, size - all);
|
||||
if (ret <= 0) piMinSleep();
|
||||
else {
|
||||
str << PIString((char*)td, ret);
|
||||
str += PIString((char*)td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
@@ -532,12 +537,12 @@ PIString PISerial::readString(int size, double timeout_ms) {
|
||||
} else {
|
||||
bool br = setOption(BlockingRead, true);
|
||||
all = readDevice(td, 1);
|
||||
str << PIString((char*)td, all);
|
||||
str += PIString((char*)td, all);
|
||||
while (all < size) {
|
||||
ret = readDevice(td, size - all);
|
||||
if (ret <= 0) piMinSleep();
|
||||
else {
|
||||
str << PIString((char*)td, ret);
|
||||
str += PIString((char*)td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
@@ -857,13 +862,13 @@ bool PISerial::configureDevice(const void * e_main, const void * e_parent) {
|
||||
|
||||
PIString PISerial::constructFullPathDevice() const {
|
||||
PIString ret;
|
||||
ret << path() << ":" << int(inSpeed()) << ":" << dataBitsCount();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
//! \~russian Последовательный порт.
|
||||
class PIP_EXPORT PISerial: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PISerial, "ser")
|
||||
PIIODEVICE(PISerial, "ser");
|
||||
public:
|
||||
|
||||
//! \~english Contructs an empty %PISerial
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
|
||||
//! \~english Discard all buffered input and output data
|
||||
//! \~russian Откидывает все буферизированные данные для передачи и приема
|
||||
void flush();
|
||||
virtual void flush() override;
|
||||
|
||||
int read(void * read_to, int max_size) {return readDevice(read_to, max_size);}
|
||||
|
||||
@@ -282,19 +282,19 @@ public:
|
||||
//! \}
|
||||
|
||||
protected:
|
||||
PIString constructFullPathDevice() const;
|
||||
void configureFromFullPathDevice(const PIString & full_path);
|
||||
PIPropertyStorage constructVariantDevice() const;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d);
|
||||
bool configureDevice(const void * e_main, const void * e_parent = 0);
|
||||
void optionsChanged();
|
||||
void threadedReadBufferSizeChanged();
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString & full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
bool configureDevice(const void * e_main, const void * e_parent = 0) override;
|
||||
void optionsChanged() override;
|
||||
void threadedReadBufferSizeChanged() override;
|
||||
|
||||
//! \~english Basic read function
|
||||
//! \~russian Базовое чтение
|
||||
int readDevice(void * read_to, int max_size);
|
||||
int writeDevice(const void * data, int max_size);
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Sequential;}
|
||||
int readDevice(void * read_to, int max_size) override;
|
||||
int writeDevice(const void * data, int max_size) override;
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Sequential;}
|
||||
|
||||
//! Executes when any read function was successful. Default implementation does nothing
|
||||
virtual void received(const void * data, int size) {;}
|
||||
@@ -306,8 +306,8 @@ protected:
|
||||
bool setBit(int bit, bool on, const PIString & bname);
|
||||
bool isBit(int bit, const PIString & bname) const;
|
||||
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
int fd, vtime;
|
||||
@@ -336,12 +336,12 @@ inline bool operator !=(const PISerial::DeviceInfo & v0, const PISerial::DeviceI
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PISerial::DeviceInfo & v) {s << v.vID << v.pID << v.path << v.description << v.manufacturer; return s;}
|
||||
BINARY_STREAM_WRITE(PISerial::DeviceInfo) {s << v.vID << v.pID << v.path << v.description << v.manufacturer; return s;}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator
|
||||
//! \~russian Оператор извлечения
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PISerial::DeviceInfo & v) {s >> v.vID >> v.pID >> v.path >> v.description >> v.manufacturer; return s;}
|
||||
BINARY_STREAM_READ (PISerial::DeviceInfo) {s >> v.vID >> v.pID >> v.path >> v.description >> v.manufacturer; return s;}
|
||||
|
||||
|
||||
#endif // PISERIAL_H
|
||||
|
||||
@@ -170,7 +170,7 @@ bool PISharedMemory::closeDevice() {
|
||||
|
||||
PIString PISharedMemory::constructFullPathDevice() const {
|
||||
PIString ret;
|
||||
ret << path() << ":" << dsize;
|
||||
ret += path() + ":" + PIString::fromNumber(dsize);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
//! \~russian Разделяемая память.
|
||||
class PIP_EXPORT PISharedMemory: public PIIODevice
|
||||
{
|
||||
PIIODEVICE(PISharedMemory, "shm")
|
||||
PIIODEVICE(PISharedMemory, "shm");
|
||||
public:
|
||||
|
||||
//! \~english Constructs empty %PISharedMemory
|
||||
@@ -91,15 +91,15 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
PIString constructFullPathDevice() const;
|
||||
void configureFromFullPathDevice(const PIString & full_path);
|
||||
PIPropertyStorage constructVariantDevice() const;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d);
|
||||
int readDevice(void * read_to, int max_size) {return read(read_to, max_size, 0);}
|
||||
int writeDevice(const void * data, int max_size) {return write(data, max_size, 0);}
|
||||
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||
bool openDevice() override;
|
||||
bool closeDevice() override;
|
||||
PIString constructFullPathDevice() const override;
|
||||
void configureFromFullPathDevice(const PIString & full_path) override;
|
||||
PIPropertyStorage constructVariantDevice() const override;
|
||||
void configureFromVariantDevice(const PIPropertyStorage & d) override;
|
||||
int readDevice(void * read_to, int max_size) override {return read(read_to, max_size, 0);}
|
||||
int writeDevice(const void * data, int max_size) override {return write(data, max_size, 0);}
|
||||
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
|
||||
|
||||
private:
|
||||
void initPrivate();
|
||||
|
||||
@@ -88,6 +88,11 @@ bool PISPI::isParameterSet(PISPI::Parameters parameter) const {
|
||||
}
|
||||
|
||||
|
||||
ssize_t PISPI::bytesAvailable() const {
|
||||
return recv_buf.size();
|
||||
}
|
||||
|
||||
|
||||
bool PISPI::openDevice() {
|
||||
#ifdef PIP_SPI
|
||||
int ret = 0;
|
||||
@@ -126,7 +131,7 @@ bool PISPI::closeDevice() {
|
||||
int PISPI::readDevice(void * read_to, int max_size) {
|
||||
int sz = piMini(recv_buf.size_s(), max_size);
|
||||
memcpy(read_to, recv_buf.data(), sz);
|
||||
recv_buf.resize(recv_buf.size_s() - sz);
|
||||
recv_buf.remove(0, sz);
|
||||
return sz;
|
||||
}
|
||||
|
||||
@@ -157,7 +162,7 @@ int PISPI::writeDevice(const void * data, int max_size) {
|
||||
|
||||
PIString PISPI::constructFullPathDevice() const {
|
||||
PIString ret;
|
||||
ret << path() << ":" << int(speed()) << ":" << int(bits()) << ":" << (int)parameters();
|
||||
ret += path() + ":" + PIString::fromNumber((int)speed()) + ":" + PIString::fromNumber((int)bits()) + ":" + PIString::fromNumber((int)parameters());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user