10 Commits

Author SHA1 Message Date
6ed7befa47 Doxygen generated by local qwen3-coder-next 2026-02-28 18:32:00 +03:00
0878891cd8 more ai generated doc with human review 2026-02-28 12:29:00 +03:00
077f12c9e5 Merge branch 'master' into doc_ai 2026-02-27 23:59:05 +03:00
9588b48105 PIVector2D - add funcs, optimize, tests, fixes, doxygen (#194)
Reviewed-on: #194
Co-authored-by: andrey.bychkov <andrey@signalmodelling.ru>
Co-committed-by: andrey.bychkov <andrey@signalmodelling.ru>
2026-02-27 23:58:44 +03:00
b53ef184dc add doxygen via opencode 2026-02-27 23:54:48 +03:00
1739836a18 fix pistatistic mean calc 2026-02-25 17:50:56 +03:00
7195734765 add more tests 2026-02-17 21:53:18 +03:00
8ecec6b914 add more funcs 2026-02-17 21:40:36 +03:00
9029bcf099 Vibecoding PIVector2D - add funcs and doc
Добавь в файл pivector2d.h комментарии для Doxygen ко всем классам и
всем функциям.
Комментарии должны быть в таком же стиле как в файле pivector.h.

Проанализируй функциональность классов pivector2d в файле pivector2d.h и
класс pivector в файле pivector.h и добавь недостающую функциональность
в pivector2d по аналогии с pivector.
2026-02-17 21:04:40 +03:00
6f1660fd9e version 5.5.5
fix PIHIDevice enumeration for Windows
2026-02-13 18:47:33 +03:00
140 changed files with 10330 additions and 1942 deletions

4
.gitignore vendored
View File

@@ -1,8 +1,10 @@
/.*
/src_main/piversion.h /src_main/piversion.h
/.svn
/doc/rtf /doc/rtf
_unsused _unsused
CMakeLists.txt.user* CMakeLists.txt.user*
/include /include
/release /release
/build* /build*
/AGENTS.md
/plans

View File

@@ -5,8 +5,8 @@ if (POLICY CMP0177)
endif() endif()
project(PIP) project(PIP)
set(PIP_MAJOR 5) set(PIP_MAJOR 5)
set(PIP_MINOR 5) set(PIP_MINOR 6)
set(PIP_REVISION 4) set(PIP_REVISION 0)
set(PIP_SUFFIX ) set(PIP_SUFFIX )
set(PIP_COMPANY SHS) set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS) set(PIP_DOMAIN org.SHS)
@@ -72,9 +72,11 @@ option(COVERAGE "Build project with coverage info" OFF)
option(PIP_FFTW_F "Support fftw module for float" ON) option(PIP_FFTW_F "Support fftw module for float" ON)
option(PIP_FFTW_L "Support fftw module for long double" ON) option(PIP_FFTW_L "Support fftw module for long double" ON)
option(PIP_FFTW_Q "Support fftw module for quad double" OFF) option(PIP_FFTW_Q "Support fftw module for quad double" OFF)
set(PIP_UTILS 1) set(PIP_UTILS 1)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
shstk_is_parent_exists(_pe) shstk_is_parent_exists(_pe)
if (_pe) if (_pe)

115
README.md
View File

@@ -40,3 +40,118 @@ You should add ${<out_var>} to your target.
[🇷🇺 Онлайн документация](https://shstk.ru/pip/html/ru/index.html) [🇷🇺 Онлайн документация](https://shstk.ru/pip/html/ru/index.html)
[🇷🇺 Qt-help](https://shstk.ru/pip/pip_ru.qch) [🇷🇺 Qt-help](https://shstk.ru/pip/pip_ru.qch)
## Основные опции сборки
### Стандартные опции (option())
| Опция | Описание | По умолчанию |
|-------|----------|--------------|
| `ICU` | ICU support для конвертации кодовых страниц | ON (кроме Win/Android/Apple) |
| `STD_IOSTREAM` | Поддержка std::iostream операторов | OFF |
| `INTROSPECTION` | Сборка с интроспекцией | OFF |
| `TESTS` | Сборка тестов | OFF |
| `COVERAGE` | Сборка с информацией о покрытии | OFF |
| `PIP_FFTW_F` | Поддержка FFTW для float | ON |
| `PIP_FFTW_L` | Поддержка FFTW для long double | ON |
| `PIP_FFTW_Q` | Поддержка FFTW для quad double | OFF |
### Опции модулей (PIP_BUILD_*)
| Опция | Модуль |
|-------|--------|
| `PIP_BUILD_CONSOLE` | console |
| `PIP_BUILD_CRYPT` | crypt (требует libsodium) |
| `PIP_BUILD_COMPRESS` | compress (требует zlib) |
| `PIP_BUILD_USB` | usb |
| `PIP_BUILD_FFTW` | fftw |
| `PIP_BUILD_OPENCL` | opencl |
| `PIP_BUILD_IO_UTILS` | io_utils |
| `PIP_BUILD_CLIENT_SERVER` | client_server |
| `PIP_BUILD_CLOUD` | cloud |
| `PIP_BUILD_LUA` | lua |
| `PIP_BUILD_HTTP_CLIENT` | http_client (требует libcurl) |
| `PIP_BUILD_HTTP_SERVER` | http_server (требует libmicrohttpd) |
### Дополнительные переменные
| Переменная | Описание |
|------------|----------|
| `PIP_BUILD_DEBUG` | Сборка debug версии |
| `PIP_FREERTOS` | Режим сборки для FreeRTOS |
| `CROSSTOOLS` | Собрать инструменты кросс-сборки под хостовую систему (pip_cmg, pip_rc, ...) |
| `LOCAL` | Локальная установка (bin/lib/include) |
| `PIP_CONTAINERS_MIN_ALLOC` | Переопределить минимальный размер аллокации контейнеров |
| `PIP_CONTAINERS_MAX_POT_ALLOC` | Переопределить максимальный размер дополнительной аллокации (поддерживает X_KiB, X_MiB) |
### Примеры использования
```bash
# Базовая сборка с тестами
cmake -B build -DTESTS=ON
# Сборка с покрытием и ICU
cmake -B build -DTESTS=ON -DCOVERAGE=ON -DICU=ON
# Отключение отдельных модулей
cmake -B build -DPIP_BUILD_CRYPT=OFF -DPIP_BUILD_OPENCL=OFF
# Переопределение параметров контейнеров
cmake -B build -DPIP_CONTAINERS_MIN_ALLOC=64
# Локальная установка
cmake -B build -DLOCAL=ON
```
## PIP Dependencies
### Встроенные (included in 3rd/)
| Библиотека | Назначение | Модуль PIP |
|------------|------------|------------|
| **PCRE2** | Регулярные выражения | main (internal) |
| **BLAKE2** | Хеширование | main (internal) |
| **SipHash** | Хеширование | main (internal) |
| **Lua** | Lua scripting | lua |
| **LuaBridge** | Lua bindings | lua |
### Внешние (системные)
| Библиотека | Опция | Модуль PIP |
|------------|-------|------------|
| **ICU** | `-DICU=ON` | main (string conversion) |
| **zlib** | `PIP_BUILD_COMPRESS` | compress |
| **libsodium** | `PIP_BUILD_CRYPT` | crypt, io_utils, cloud |
| **libusb** | `PIP_BUILD_USB` | usb |
| **FFTW3** (+ threads) | `PIP_BUILD_FFTW` | fftw |
| **OpenCL** | `PIP_BUILD_OPENCL` | opencl |
| **libmicrohttpd** | `PIP_BUILD_HTTP_SERVER` | http_server |
| **libcurl** | `PIP_BUILD_HTTP_CLIENT` | http_client |
### Опциональные (тесты/документация)
| Инструмент | Назначение |
|------------|------------|
| **Google Test** | Тестирование (fetched automatically) |
| **Doxygen** | Генерация документации |
### Схема зависимостей модулей
```
main (core)
├── PCRE2 (встроен)
├── BLAKE2 (встроен)
├── SipHash (встроен)
└── ICU (опционально)
console → main
compress → zlib
crypt → libsodium
usb → libusb
fftw → FFTW3
opencl → OpenCL
io_utils → [crypt, если доступен]
client_server → io_utils
cloud → io_utils, crypt
lua → Lua (встроен), LuaBridge (встроен)
http_server → libmicrohttpd
http_client → libcurl
```

View File

@@ -64,13 +64,25 @@ public:
//! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command. //! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command.
//! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы. //! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы.
PIString rawArgument(int index); PIString rawArgument(int index);
//! \~english Returns mandatory command-line argument by index "index".
//! \~russian Возвращает обязательный аргумент командной строки по индексу "index".
PIString mandatoryArgument(int index); PIString mandatoryArgument(int index);
//! \~english Returns optional command-line argument by index "index".
//! \~russian Возвращает опциональный аргумент командной строки по индексу "index".
PIString optionalArgument(int index); PIString optionalArgument(int index);
//! \~english Returns unparsed command-line arguments. //! \~english Returns unparsed command-line arguments.
//! \~russian Возвращает исходные аргументы командной строки. //! \~russian Возвращает исходные аргументы командной строки.
const PIStringList & rawArguments(); const PIStringList & rawArguments();
//! \~english Returns mandatory command-line arguments.
//! \~russian Возвращает обязательные аргументы командной строки.
const PIStringList & mandatoryArguments(); const PIStringList & mandatoryArguments();
//! \~english Returns optional command-line arguments.
//! \~russian Возвращает опциональные аргументы командной строки.
const PIStringList & optionalArguments(); const PIStringList & optionalArguments();
//! \~english Returns program execute command without arguments. //! \~english Returns program execute command without arguments.
@@ -93,18 +105,52 @@ public:
//! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет. //! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет.
PIString argumentFullKey(const PIString & name); PIString argumentFullKey(const PIString & name);
//! \~english Returns short key prefix.
//! \~russian Возвращает префикс короткого ключа.
const PIString & shortKeyPrefix() const { return _prefix_short; } const PIString & shortKeyPrefix() const { return _prefix_short; }
//! \~english Returns full key prefix.
//! \~russian Возвращает префикс полного ключа.
const PIString & fullKeyPrefix() const { return _prefix_full; } const PIString & fullKeyPrefix() const { return _prefix_full; }
//! \~english Returns mandatory arguments count.
//! \~russian Возвращает количество обязательных аргументов.
int mandatoryArgumentsCount() const { return _count_mand; } int mandatoryArgumentsCount() const { return _count_mand; }
//! \~english Returns optional arguments count.
//! \~russian Возвращает количество опциональных аргументов.
int optionalArgumentsCount() const { return _count_opt; } int optionalArgumentsCount() const { return _count_opt; }
//! \~english Sets short key prefix.
//! \~russian Устанавливает префикс короткого ключа.
void setShortKeyPrefix(const PIString & prefix); void setShortKeyPrefix(const PIString & prefix);
//! \~english Sets full key prefix.
//! \~russian Устанавливает префикс полного ключа.
void setFullKeyPrefix(const PIString & prefix); void setFullKeyPrefix(const PIString & prefix);
//! \~english Sets mandatory arguments count.
//! \~russian Устанавливает количество обязательных аргументов.
void setMandatoryArgumentsCount(const int count); void setMandatoryArgumentsCount(const int count);
//! \~english Sets optional arguments count.
//! \~russian Устанавливает количество опциональных аргументов.
void setOptionalArgumentsCount(const int count); void setOptionalArgumentsCount(const int count);
//! \~english Returns debug mode state.
//! \~russian Возвращает состояние режима отладки.
bool debug() const { return debug_; } bool debug() const { return debug_; }
//! \~english Sets debug mode state.
//! \~russian Устанавливает состояние режима отладки.
void setDebug(bool debug) { debug_ = debug; } void setDebug(bool debug) { debug_ = debug; }
//! \~english Returns class name.
//! \~russian Возвращает имя класса.
PIConstChars className() const { return "PICLI"; } PIConstChars className() const { return "PICLI"; }
//! \~english Returns object name.
//! \~russian Возвращает имя объекта.
PIString name() const { return PIStringAscii("CLI"); } PIString name() const { return PIStringAscii("CLI"); }
private: private:

View File

@@ -6,7 +6,7 @@
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
High-level log High-level log
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -38,7 +38,12 @@ class PIP_EXPORT PILog: public PIThread {
PIOBJECT_SUBCLASS(PILog, PIThread) PIOBJECT_SUBCLASS(PILog, PIThread)
public: public:
//! \~english Constructs empty %PILog.
//! \~russian Создает пустой %PILog.
PILog(); PILog();
//! \~english Destructor. Calls stop().
//! \~russian Деструктор. Вызывает stop().
~PILog(); ~PILog();
//! \~english Message category //! \~english Message category

View File

@@ -42,6 +42,8 @@ public:
//! \~russian Создает %PISingleApplication с именем "app_name" //! \~russian Создает %PISingleApplication с именем "app_name"
PISingleApplication(const PIString & app_name = PIString()); PISingleApplication(const PIString & app_name = PIString());
//! \~english Destructor.
//! \~russian Деструктор.
~PISingleApplication(); ~PISingleApplication();

View File

@@ -227,23 +227,25 @@ public:
//! \~russian Возвращает статистику потоков наблюдаемого процесса //! \~russian Возвращает статистику потоков наблюдаемого процесса
PIVector<ThreadStats> threadsStatistic() const; PIVector<ThreadStats> threadsStatistic() const;
//! \~english Sets process statistics.
//! \~russian Устанавливает статистику процесса.
void setStatistic(const ProcessStats & s); void setStatistic(const ProcessStats & s);
//! \~english //! \~english Returns total RAM in bytes.
//! \~russian //! \~russian Возвращает общий объем ОЗУ в байтах.
static ullong totalRAM(); static ullong totalRAM();
//! \~english //! \~english Returns free RAM in bytes.
//! \~russian //! \~russian Возвращает свободный объем ОЗУ в байтах.
static ullong freeRAM(); static ullong freeRAM();
//! \~english //! \~english Returns used RAM in bytes.
//! \~russian //! \~russian Возвращает используемый объем ОЗУ в байтах.
static ullong usedRAM(); static ullong usedRAM();
//! \~english //! \~english Event raised when new measurements are available.
//! \~russian //! \~russian Событие вызывается когда доступны новые измерения.
EVENT(measured); EVENT(measured);
private: private:

View File

@@ -6,7 +6,7 @@
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Translation support Translation support
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -38,15 +38,40 @@
//! \~russian Поддержка перевода //! \~russian Поддержка перевода
class PIP_EXPORT PITranslator { class PIP_EXPORT PITranslator {
public: public:
//! \~english Translates string "in" with optional context.
//! \~russian Переводит строку "in" с опциональным контекстом.
static PIString tr(const PIString & in, const PIString & context = {}); static PIString tr(const PIString & in, const PIString & context = {});
//! \~english Translates string "in" with optional context.
//! \~russian Переводит строку "in" с опциональным контекстом.
static PIString tr(const char * in, const PIString & context = {}) { return tr(PIString::fromUTF8(in), context); } static PIString tr(const char * in, const PIString & context = {}) { return tr(PIString::fromUTF8(in), context); }
//! \~english Returns original string without translation.
//! \~russian Возвращает оригинальную строку без перевода.
static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; } static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; }
//! \~english Returns original string without translation.
//! \~russian Возвращает оригинальную строку без перевода.
static PIString trNoOp(const char * in, const PIString & context = {}) { return trNoOp(PIString::fromUTF8(in), context); } static PIString trNoOp(const char * in, const PIString & context = {}) { return trNoOp(PIString::fromUTF8(in), context); }
//! \~english Clears all loaded translations.
//! \~russian Очищает все загруженные переводы.
static void clear(); static void clear();
//! \~english Loads translation for language "short_lang" from directory "dir".
//! \~russian Загружает перевод для языка "short_lang" из директории "dir".
static void loadLang(const PIString & short_lang, PIString dir = {}); static void loadLang(const PIString & short_lang, PIString dir = {});
//! \~english Loads translation from config "content".
//! \~russian Загружает перевод из конфигурации "content".
static void loadConfig(const PIString & content); static void loadConfig(const PIString & content);
//! \~english Loads translation from binary content.
//! \~russian Загружает перевод из бинарного содержимого.
static bool load(const PIByteArray & content); static bool load(const PIByteArray & content);
//! \~english Loads translation from file.
//! \~russian Загружает перевод из файла.
static bool loadFile(const PIString & path); static bool loadFile(const PIString & path);
private: private:
@@ -59,10 +84,20 @@ private:
}; };
//! \~english Context-aware string wrapper for translation.
//! \~russian Контекстно-зависимая обертка строки для перевода.
class PIStringContextTr { class PIStringContextTr {
public: public:
//! \~english Constructs wrapper from string.
//! \~russian Создает обертку из строки.
PIStringContextTr(PIString && s): _s(s) {} PIStringContextTr(PIString && s): _s(s) {}
//! \~english Returns translated string.
//! \~russian Возвращает переведенную строку.
operator PIString() const { return PITranslator::tr(_s); } operator PIString() const { return PITranslator::tr(_s); }
//! \~english Returns translated string with context.
//! \~russian Возвращает переведенную строку с контекстом.
PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); } PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); }
private: private:
@@ -70,10 +105,20 @@ private:
}; };
//! \~english Context-aware string wrapper without translation (no-op).
//! \~russian Контекстно-зависимая обертка строки без перевода (заглушка).
class PIStringContextTrNoOp { class PIStringContextTrNoOp {
public: public:
//! \~english Constructs wrapper from string.
//! \~russian Создает обертку из строки.
PIStringContextTrNoOp(PIString && s): _s(s) {} PIStringContextTrNoOp(PIString && s): _s(s) {}
//! \~english Returns original string.
//! \~russian Возвращает оригинальную строку.
operator PIString() const { return _s; } operator PIString() const { return _s; }
//! \~english Returns original string with context.
//! \~russian Возвращает оригинальную строку с контекстом.
PIString operator()(const PIString & ctx = {}) const { return _s; } PIString operator()(const PIString & ctx = {}) const { return _s; }
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file piclientserver_client.h //! \file piclientserver_client.h
* \ingroup ClientServer //! \ingroup ClientServer
* \~\brief //! \brief
* \~english //! \~english Client and ServerClient classes
* \~russian //! \~russian Классы Client и ServerClient
*/ //! \details
//! \~english Provides client implementation for connecting to servers and server-side client representation.
//! \~russian Обеспечивает реализацию клиента для подключения к серверам и представление клиента на стороне сервера.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -33,13 +35,18 @@ namespace PIClientServer {
// ServerClient // ServerClient
//! ~english Server-side client implementation //! \details
//! ~russian Серверная реализация клиента //! \~english Server-side client representation. Created and managed by Server. Used to communicate with remote clients connected to the
//! server.
//! \~russian Представление клиента на стороне сервера. Создаётся и управляется сервером. Используется для коммуникации с удалёнными
//! клиентами, подключёнными к серверу.
class PIP_CLIENT_SERVER_EXPORT ServerClient: public ClientBase { class PIP_CLIENT_SERVER_EXPORT ServerClient: public ClientBase {
friend class Server; friend class Server;
NO_COPY_CLASS(ServerClient); NO_COPY_CLASS(ServerClient);
public: public:
//! \~english Creates empty ServerClient instance
//! \~russian Создает пустой экземпляр ServerClient
ServerClient() {} ServerClient() {}
protected: protected:
@@ -54,13 +61,20 @@ private:
// Client // Client
//! ~english Client implementation for connecting to servers //! \details
//! ~russian Клиентская реализация для подключения к серверам //! \~english Client implementation for connecting to servers. Provides TCP connection to remote server with diagnostics and packet
//! streaming support.
//! \~russian Реализация клиента для подключения к серверам. Обеспечивает TCP-соединение с удалённым сервером с поддержкой диагностики и
//! потоковой передачи пакетов.
class PIP_CLIENT_SERVER_EXPORT Client: public ClientBase { class PIP_CLIENT_SERVER_EXPORT Client: public ClientBase {
NO_COPY_CLASS(Client); NO_COPY_CLASS(Client);
public: public:
//! \~english Creates Client instance
//! \~russian Создает экземпляр Client
Client(); Client();
//! \~english Destroys Client instance
//! \~russian Уничтожает экземпляр Client
~Client(); ~Client();
//! ~english Connects to specified server address //! ~english Connects to specified server address

View File

@@ -1,9 +1,11 @@
/*! \file piclientserver_client_base.h //! \file piclientserver_client_base.h
* \ingroup ClientServer //! \ingroup ClientServer
* \~\brief //! \brief
* \~english //! \~english Base class for client-server communication
* \~russian //! \~russian Базовый класс для клиент-серверного взаимодействия
*/ //! \details
//! \~english Provides base functionality for client-server communication with diagnostics support.
//! \~russian Обеспечивает базовую функциональность для клиент-серверного взаимодействия с поддержкой диагностики.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -37,77 +39,117 @@ class Server;
class ClientInterface {}; class ClientInterface {};
//! ~english Base class for client-server communication with diagnostics support //! \brief
//! ~russian Базовый класс для клиент-серверного взаимодействия с поддержкой диагностики //! \~english Base class for client and server-side client
//! \~russian Базовый класс для клиента и клиента на стороне сервера
//! \details
//! \~english Base class for client and server-side client communication. Provides TCP connection management, diagnostics, and packet
//! streaming capabilities.
//! \~russian Базовый класс для клиентской и серверной коммуникации. Обеспечивает управление TCP-соединением, диагностику и потоковую
//! передачу пакетов.
// template<bool EnableDiagnostics = false> // template<bool EnableDiagnostics = false>
class PIP_CLIENT_SERVER_EXPORT ClientBase { class PIP_CLIENT_SERVER_EXPORT ClientBase {
friend class Server; friend class Server;
NO_COPY_CLASS(ClientBase); NO_COPY_CLASS(ClientBase);
public: public:
//! \brief
//! \~english Constructs ClientBase
//! \~russian Создает ClientBase
ClientBase(); ClientBase();
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~ClientBase(); virtual ~ClientBase();
//! ~english Gets underlying TCP connection //! \brief
//! ~russian Возвращает TCP-соединение //! \~english Gets underlying TCP connection
//! \~russian Возвращает TCP-соединение
const PIEthernet * getTCP() const { return tcp; } const PIEthernet * getTCP() const { return tcp; }
//! ~english Closes the connection //! \brief
//! ~russian Закрывает соединение //! \~english Closes the connection
//! \~russian Закрывает соединение
void close(); void close();
//! ~english Gracefully stops and waits for completion //! \brief
//! ~russian Плавно останавливает и ожидает завершения //! \~english Gracefully stops and waits for completion
//! \~russian Плавно останавливает и ожидает завершения
void stopAndWait(); void stopAndWait();
//! ~english Writes byte array to the connection //! \brief
//! ~russian Записывает массив байтов в соединение //! \~english Writes byte array to the connection
//! \~russian Записывает массив байтов в соединение
int write(const void * d, const size_t s); int write(const void * d, const size_t s);
//! ~english Writes byte array to the connection //! \brief
//! ~russian Записывает массив байтов в соединение //! \~english Writes byte array to the connection
//! \~russian Записывает массив байтов в соединение
int write(const PIByteArray & ba) { return write(ba.data(), ba.size()); } int write(const PIByteArray & ba) { return write(ba.data(), ba.size()); }
//! ~english Enables diagnostics collection //! \brief
//! ~russian Включает сбор диагностики //! \~english Enables diagnostics collection
//! \~russian Включает сбор диагностики
void enableDiagnostics(); void enableDiagnostics();
//! ~english Gets current diagnostics state //! \brief
//! ~russian Возвращает текущее состояние диагностики //! \~english Gets current diagnostics state
//! \~russian Возвращает текущее состояние диагностики
PIDiagnostics::State diagnostics() const; PIDiagnostics::State diagnostics() const;
//! ~english Gets current received packet bytes already received (all bytes count passed in \a receivePacketStart()) //! \brief
//! ~russian Возвращает сколько байт принимаемого пакета получено (общее количество передается в \a receivePacketStart()) //! \~english Gets current received packet bytes already received (all bytes count passed in \a receivePacketStart())
//! \~russian Возвращает сколько байт принимаемого пакета получено (общее количество передается в \a receivePacketStart())
int receivePacketProgress() const; int receivePacketProgress() const;
//! \brief
//! \~english Returns stream configuration
//! \~russian Возвращает конфигурацию стрима
const PIStreamPackerConfig & configuration() const { return stream.configuration(); } const PIStreamPackerConfig & configuration() const { return stream.configuration(); }
//! \brief
//! \~english Returns stream configuration
//! \~russian Возвращает конфигурацию стрима
PIStreamPackerConfig & configuration() { return stream.configuration(); } PIStreamPackerConfig & configuration() { return stream.configuration(); }
//! \brief
//! \~english Sets stream configuration
//! \~russian Устанавливает конфигурацию стрима
void setConfiguration(const PIStreamPackerConfig & config) { stream.setConfiguration(config); } void setConfiguration(const PIStreamPackerConfig & config) { stream.setConfiguration(config); }
protected: protected:
//! ~english Called when data is received //! \brief
//! ~russian Вызывается при получении данных //! \~english Called when data is received
//! \~russian Вызывается при получении данных
virtual void readed(PIByteArray data) {} virtual void readed(PIByteArray data) {}
//! ~english Called when connection is established //! \brief
//! ~russian Вызывается при установке соединения //! \~english Called when connection is established
//! \~russian Вызывается при установке соединения
virtual void connected() {} virtual void connected() {}
//! ~english Called when connection is closed //! \brief
//! ~russian Вызывается при закрытии соединения //! \~english Called when connection is closed
//! \~russian Вызывается при закрытии соединения
virtual void disconnected() {} virtual void disconnected() {}
//! ~english Called when packet receiving starts //! \brief
//! ~russian Вызывается при начале получения пакета //! \~english Called when packet receiving starts
//! \~russian Вызывается при начале получения пакета
virtual void receivePacketStart(int size) {} virtual void receivePacketStart(int size) {}
//! ~english Called when packet receiving ends //! \brief
//! ~russian Вызывается при завершении получения пакета //! \~english Called when packet receiving ends
//! \~russian Вызывается при завершении получения пакета
virtual void receivePacketEnd() {} virtual void receivePacketEnd() {}
//! \brief
//! \~english Initializes the client
//! \~russian Инициализирует клиента
void init(); void init();
bool own_tcp = false; bool own_tcp = false;

View File

@@ -1,9 +1,11 @@
/*! \file piclientserver_server.h //! \file piclientserver_server.h
* \ingroup ClientServer //! \ingroup ClientServer
* \~\brief //! \brief
* \~english //! \~english TCP Server
* \~russian //! \~russian TCP Сервер
*/ //! \details
//! \~english TCP server implementation for client-server communication.
//! \~russian Реализация TCP сервера для клиент-серверного взаимодействия.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -38,14 +40,21 @@ namespace PIClientServer {
class ServerClient; class ServerClient;
//! ~english TCP server for client-server communication //! \details
//! ~russian TCP сервер для клиент-серверного взаимодействия //! \~english TCP server implementation for client-server communication. Accepts incoming connections and manages multiple clients with
//! configurable factory for client instance creation.
//! \~russian Реализация TCP сервера для клиент-серверного взаимодействия. Принимает входящие соединения и управляет несколькими клиентами с
//! настраиваемой фабрикой для создания экземпляров клиентов.
class PIP_CLIENT_SERVER_EXPORT Server: public PIStreamPackerConfig { class PIP_CLIENT_SERVER_EXPORT Server: public PIStreamPackerConfig {
friend class ServerClient; friend class ServerClient;
NO_COPY_CLASS(Server); NO_COPY_CLASS(Server);
public: public:
//! \~english Creates Server instance
//! \~russian Создает экземпляр Server
Server(); Server();
//! \~english Destroys Server instance
//! \~russian Уничтожает экземпляр Server
virtual ~Server(); virtual ~Server();
//! ~english Starts listening on specified address //! ~english Starts listening on specified address

View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,9 +1,11 @@
/*! \file picloudbase.h //! \file picloudbase.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english Base class for PICloudClient and PICloudServer //! \~english Base class for PICloudClient and PICloudServer
* \~russian Базовый класс для PICloudClient и PICloudServer //! \~russian Базовый класс для PICloudClient и PICloudServer
*/ //! \details
//! \~english Provides common functionality for cloud client and server implementations.
//! \~russian Обеспечивает общую функциональность для реализаций облачного клиента и сервера.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Base - Base class for PICloudClient and PICloud Server PICloud Base - Base class for PICloudClient and PICloud Server
@@ -31,10 +33,20 @@
#include "pistreampacker.h" #include "pistreampacker.h"
//! \brief
//! \~english Base class for cloud client and server
//! \~russian Базовый класс для облачного клиента и сервера
class PIP_CLOUD_EXPORT PICloudBase { class PIP_CLOUD_EXPORT PICloudBase {
public: public:
//! \brief
//! \~english Constructs PICloudBase
//! \~russian Создает PICloudBase
PICloudBase(); PICloudBase();
//! \brief
//! \~english Returns server name
//! \~russian Возвращает имя сервера
PIString serverName() const; PIString serverName() const;
protected: protected:

View File

@@ -1,9 +1,11 @@
/*! \file picloudclient.h //! \file picloudclient.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english PICloud Client //! \~english PICloud Client
* \~russian Клиент PICloud //! \~russian Клиент PICloud
*/ //! \details
//! \~english Client implementation for connecting to PICloud servers over TCP.
//! \~russian Реализация клиента для подключения к серверам PICloud по TCP.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Client PICloud Client
@@ -30,7 +32,9 @@
#include "piconditionvar.h" #include "piconditionvar.h"
//! \brief PICloudClient //! \brief PICloud client implementation
//! \~english PICloud client for connecting to servers
//! \~russian Клиент PICloud для подключения к серверам
class PIP_CLOUD_EXPORT PICloudClient class PIP_CLOUD_EXPORT PICloudClient
: public PIIODevice : public PIIODevice
@@ -38,23 +42,75 @@ class PIP_CLOUD_EXPORT PICloudClient
PIIODEVICE(PICloudClient, ""); PIIODEVICE(PICloudClient, "");
public: public:
//! \brief
//! \~english Constructs PICloudClient
//! \~russian Создает PICloudClient
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PICloudClient(); virtual ~PICloudClient();
//! \brief
//! \~english Sets server name
//! \~russian Устанавливает имя сервера
void setServerName(const PIString & server_name); void setServerName(const PIString & server_name);
//! \brief
//! \~english Sets keep connection mode
//! \~russian Устанавливает режим поддержания соединения
void setKeepConnection(bool on); void setKeepConnection(bool on);
//! \brief
//! \~english Checks if connected to server
//! \~russian Проверяет подключение к серверу
bool isConnected() const { return is_connected; } bool isConnected() const { return is_connected; }
//! \brief
//! \~english Returns number of bytes available
//! \~russian Возвращает количество доступных байт
ssize_t bytesAvailable() const override { return buff.size(); } ssize_t bytesAvailable() const override { return buff.size(); }
//! \brief
//! \~english Interrupts connection
//! \~russian Прерывает соединение
void interrupt() override; void interrupt() override;
//! \brief
//! \~english Raised when connected to server
//! \~russian Вызывается при подключении к серверу
EVENT(connected); EVENT(connected);
//! \brief
//! \~english Raised when disconnected from server
//! \~russian Вызывается при отключении от сервера
EVENT(disconnected); EVENT(disconnected);
protected: protected:
//! \brief
//! \~english Opens device
//! \~russian Открывает устройство
bool openDevice() override; bool openDevice() override;
//! \brief
//! \~english Closes device
//! \~russian Закрывает устройство
bool closeDevice() override; bool closeDevice() override;
//! \brief
//! \~english Reads data from device
//! \~russian Читает данные из устройства
ssize_t readDevice(void * read_to, ssize_t max_size) override; ssize_t readDevice(void * read_to, ssize_t max_size) override;
//! \brief
//! \~english Writes data to device
//! \~russian Записывает данные в устройство
ssize_t writeDevice(const void * data, ssize_t size) override; ssize_t writeDevice(const void * data, ssize_t size) override;
//! \brief
//! \~english Returns device info flags
//! \~russian Возвращает флаги информации об устройстве
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; } DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file picloudserver.h //! \file picloudserver.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english PICloud Server //! \~english PICloud Server
* \~russian Сервер PICloud //! \~russian Сервер PICloud
*/ //! \details
//! \~english Server implementation for accepting PICloud client connections over TCP.
//! \~russian Реализация сервера для приема подключений клиентов PICloud по TCP.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Server PICloud Server
@@ -30,31 +32,79 @@
#include "piconditionvar.h" #include "piconditionvar.h"
//! \brief PICloud server implementation
//! \~english PICloud server for accepting client connections
//! \~russian Сервер PICloud для приема подключений клиентов
class PIP_CLOUD_EXPORT PICloudServer class PIP_CLOUD_EXPORT PICloudServer
: public PIIODevice : public PIIODevice
, public PICloudBase { , public PICloudBase {
PIIODEVICE(PICloudServer, ""); PIIODEVICE(PICloudServer, "");
public: public:
//! PICloudServer //! \brief
//! \~english Constructs PICloudServer
//! \~russian Создает PICloudServer
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PICloudServer(); virtual ~PICloudServer();
//! \brief Connected client representation
//! \~english Represents a client connected to the server
//! \~russian Представляет клиента, подключенного к серверу
class Client: public PIIODevice { class Client: public PIIODevice {
PIIODEVICE(PICloudServer::Client, ""); PIIODEVICE(PICloudServer::Client, "");
friend class PICloudServer; friend class PICloudServer;
public: public:
//! \brief
//! \~english Constructs Client
//! \~russian Создает Client
//! \param srv Parent server / Родительский сервер
//! \param id Client ID / ID клиента
Client(PICloudServer * srv = nullptr, uint id = 0); Client(PICloudServer * srv = nullptr, uint id = 0);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~Client(); virtual ~Client();
protected: protected:
//! \brief
//! \~english Opens device
//! \~russian Открывает устройство
bool openDevice() override; bool openDevice() override;
//! \brief
//! \~english Closes device
//! \~russian Закрывает устройство
bool closeDevice() override; bool closeDevice() override;
//! \brief
//! \~english Reads data from device
//! \~russian Читает данные из устройства
ssize_t readDevice(void * read_to, ssize_t max_size) override; ssize_t readDevice(void * read_to, ssize_t max_size) override;
//! \brief
//! \~english Writes data to device
//! \~russian Записывает данные в устройство
ssize_t writeDevice(const void * data, ssize_t size) override; ssize_t writeDevice(const void * data, ssize_t size) override;
//! \brief
//! \~english Returns device info flags
//! \~russian Возвращает флаги информации об устройстве
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; } DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
//! \brief
//! \~english Returns number of bytes available
//! \~russian Возвращает количество доступных байт
ssize_t bytesAvailable() const override { return buff.size(); } ssize_t bytesAvailable() const override { return buff.size(); }
//! \brief
//! \~english Interrupts connection
//! \~russian Прерывает соединение
void interrupt() override; void interrupt() override;
private: private:
@@ -67,17 +117,45 @@ public:
std::atomic_bool is_connected; std::atomic_bool is_connected;
}; };
//! \brief
//! \~english Sets server name
//! \~russian Устанавливает имя сервера
void setServerName(const PIString & server_name); void setServerName(const PIString & server_name);
//! \brief
//! \~english Returns list of connected clients
//! \~russian Возвращает список подключенных клиентов
PIVector<PICloudServer::Client *> clients() const; PIVector<PICloudServer::Client *> clients() const;
//! \brief
//! \~english Raised when new client connects
//! \~russian Вызывается при подключении нового клиента
EVENT1(newConnection, PICloudServer::Client *, client); EVENT1(newConnection, PICloudServer::Client *, client);
protected: protected:
//! \brief
//! \~english Opens device
//! \~russian Открывает устройство
bool openDevice() override; bool openDevice() override;
//! \brief
//! \~english Closes device
//! \~russian Закрывает устройство
bool closeDevice() override; bool closeDevice() override;
//! \brief
//! \~english Reads data from device
//! \~russian Читает данные из устройства
ssize_t readDevice(void * read_to, ssize_t max_size) override; ssize_t readDevice(void * read_to, ssize_t max_size) override;
//! \brief
//! \~english Writes data to device
//! \~russian Записывает данные в устройство
ssize_t writeDevice(const void * data, ssize_t max_size) override; ssize_t writeDevice(const void * data, ssize_t max_size) override;
//! \brief
//! \~english Interrupts connection
//! \~russian Прерывает соединение
void interrupt() override; void interrupt() override;
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file picloudtcp.h //! \file picloudtcp.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english PICloud TCP transport //! \~english PICloud TCP transport
* \~russian TCP слой PICloud //! \~russian TCP слой PICloud
*/ //! \details
//! \~english Low-level TCP protocol implementation for PICloud communication.
//! \~russian Реализация низкоуровневого TCP-протокола для коммуникации PICloud.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud TCP transport PICloud TCP transport
@@ -36,45 +38,118 @@ class PIStreamPacker;
namespace PICloud { namespace PICloud {
//! \brief TCP transport protocol
//! \~english TCP transport protocol for cloud communication
//! \~russian TCP транспортный протокол для облачной коммуникации
class PIP_CLOUD_EXPORT TCP { class PIP_CLOUD_EXPORT TCP {
public: public:
//! \brief Protocol version
enum Version { enum Version {
Version_1 = 1, Version_1 = 1, //!< Version 1 / Версия 1
Version_2 = 2, Version_2 = 2, //!< Version 2 / Версия 2
}; };
//! \brief Connection role
enum Role { enum Role {
InvalidRole = 0, InvalidRole = 0, //!< Invalid role / Неверная роль
Server = 1, Server = 1, //!< Server role / Роль сервера
Client = 2, Client = 2, //!< Client role / Роль клиента
}; };
//! \brief Message type
enum Type { enum Type {
InvalidType = 0, InvalidType = 0, //!< Invalid type / Неверный тип
Connect = 1, Connect = 1, //!< Connect message / Сообщение о подключении
Disconnect = 2, Disconnect = 2, //!< Disconnect message / Сообщение об отключении
Data = 3, Data = 3, //!< Data message / Сообщение с данными
Ping = 4, Ping = 4, //!< Ping message / Сообщение ping
}; };
//! \brief
//! \~english Constructs TCP transport
//! \~russian Создает TCP транспорт
//! \param s Stream packer instance / Экземпляр стримового упаковщика
TCP(PIStreamPacker * s); TCP(PIStreamPacker * s);
//! \brief
//! \~english Sets connection role
//! \~russian Устанавливает роль соединения
void setRole(Role r); void setRole(Role r);
//! \brief
//! \~english Returns connection role
//! \~russian Возвращает роль соединения
Role role() const { return (Role)header.role; } Role role() const { return (Role)header.role; }
//! \brief
//! \~english Sets server name
//! \~russian Устанавливает имя сервера
void setServerName(const PIString & server_name_); void setServerName(const PIString & server_name_);
//! \brief
//! \~english Returns server name
//! \~russian Возвращает имя сервера
PIString serverName() const; PIString serverName() const;
//! \brief
//! \~english Sends start message
//! \~russian Отправляет сообщение о старте
void sendStart(); void sendStart();
//! \brief
//! \~english Sends connected message
//! \~russian Отправляет сообщение о подключении
void sendConnected(uint client_id); void sendConnected(uint client_id);
//! \brief
//! \~english Sends disconnected message
//! \~russian Отправляет сообщение об отключении
void sendDisconnected(uint client_id); void sendDisconnected(uint client_id);
//! \brief
//! \~english Sends data to all clients
//! \~russian Отправляет данные всем клиентам
int sendData(const PIByteArray & data); int sendData(const PIByteArray & data);
//! \brief
//! \~english Sends data to specific client
//! \~russian Отправляет данные конкретному клиенту
int sendData(const PIByteArray & data, uint client_id); int sendData(const PIByteArray & data, uint client_id);
//! \brief
//! \~english Sends ping message
//! \~russian Отправляет сообщение ping
void sendPing(); void sendPing();
//! \brief
//! \~english Parses header from buffer
//! \~russian Парсит заголовок из буфера
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba);
//! \brief
//! \~english Checks if data can be parsed
//! \~russian Проверяет возможность парсинга данных
bool canParseData(PIByteArray & ba); bool canParseData(PIByteArray & ba);
//! \brief
//! \~english Parses data for server
//! \~russian Парсит данные для сервера
PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba); PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba);
//! \brief
//! \~english Parses connect data
//! \~russian Парсит данные подключения
PIByteArray parseConnect_d(PIByteArray & ba); PIByteArray parseConnect_d(PIByteArray & ba);
//! \brief
//! \~english Parses connect message
//! \~russian Парсит сообщение подключения
uint parseConnect(PIByteArray & ba); uint parseConnect(PIByteArray & ba);
//! \brief
//! \~english Parses disconnect message
//! \~russian Парсит сообщение отключения
uint parseDisconnect(PIByteArray & ba); uint parseDisconnect(PIByteArray & ba);
private: private:

View File

@@ -64,6 +64,8 @@ typedef int (*AccessOffsetFunction)(const char *);
//! \~english Type information //! \~english Type information
//! \~russian Информация о типе //! \~russian Информация о типе
struct PIP_EXPORT TypeInfo { struct PIP_EXPORT TypeInfo {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) { TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {
name = n; name = n;
type = t; type = t;
@@ -121,6 +123,8 @@ struct PIP_EXPORT FunctionInfo {
//! \~english Class or struct information //! \~english Class or struct information
//! \~russian Информация о классе или структуре //! \~russian Информация о классе или структуре
struct PIP_EXPORT ClassInfo { struct PIP_EXPORT ClassInfo {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
ClassInfo() { is_anonymous = false; } ClassInfo() { is_anonymous = false; }
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
@@ -160,10 +164,14 @@ struct PIP_EXPORT ClassInfo {
//! \~english Enumerator information //! \~english Enumerator information
//! \~russian Информация об элементе перечисления //! \~russian Информация об элементе перечисления
struct PIP_EXPORT EnumeratorInfo { struct PIP_EXPORT EnumeratorInfo {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) { EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {
name = n; name = n;
value = v; value = v;
} }
//! \~english Converts to PIVariantTypes::Enumerator
//! \~russian Конвертирует в PIVariantTypes::Enumerator
PIVariantTypes::Enumerator toPIVariantEnumerator() { return PIVariantTypes::Enumerator(value, name.toString()); } PIVariantTypes::Enumerator toPIVariantEnumerator() { return PIVariantTypes::Enumerator(value, name.toString()); }
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
@@ -209,6 +217,8 @@ struct PIP_EXPORT EnumInfo {
}; };
//! \~english Output stream operator for TypeInfo
//! \~russian Оператор вывода для TypeInfo
inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
if (v.flags[Inline]) s << "inline "; if (v.flags[Inline]) s << "inline ";
if (v.flags[Virtual]) s << "virtual "; if (v.flags[Virtual]) s << "virtual ";
@@ -221,11 +231,15 @@ inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
return s; return s;
} }
//! \~english Output stream operator for EnumeratorInfo
//! \~russian Оператор вывода для EnumeratorInfo
inline PICout operator<<(PICout s, const PICodeInfo::EnumeratorInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::EnumeratorInfo & v) {
s << v.name << " = " << v.value << " Meta" << v.meta; s << v.name << " = " << v.value << " Meta" << v.meta;
return s; return s;
} }
//! \~english Output stream operator for ClassInfo
//! \~russian Оператор вывода для ClassInfo
inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
s.saveAndSetControls(0); s.saveAndSetControls(0);
s << "class " << v.name; s << "class " << v.name;
@@ -262,6 +276,8 @@ inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
return s; return s;
} }
//! \~english Output stream operator for EnumInfo
//! \~russian Оператор вывода для EnumInfo
inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) {
s.saveAndSetControls(0); s.saveAndSetControls(0);
s << "enum " << v.name << " Meta" << v.meta << " {\n"; s << "enum " << v.name << " Meta" << v.meta << " {\n";
@@ -279,11 +295,19 @@ inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) {
} }
//! \~english Storage singleton for PICodeInfo
//! \~russian Синглтон хранилища для PICodeInfo
class PIP_EXPORT __Storage__ { class PIP_EXPORT __Storage__ {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
__Storage__(); __Storage__();
//! \~english Destructor
//! \~russian Деструктор
~__Storage__(); ~__Storage__();
public: public:
//! \~english Returns singleton instance
//! \~russian Возвращает экземпляр синглтона
static __Storage__ * instance(); static __Storage__ * instance();
PIMap<PIConstChars, PICodeInfo::ClassInfo *> * classesInfo; PIMap<PIConstChars, PICodeInfo::ClassInfo *> * classesInfo;
@@ -296,71 +320,83 @@ private:
NO_COPY_CLASS(__Storage__) NO_COPY_CLASS(__Storage__)
}; };
class PIP_EXPORT //! \~english Access to singleton storage of PICodeInfo
__StorageAccess__{public: //! \~russian Доступ к синглтону хранилища PICodeInfo
//! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name class PIP_EXPORT __StorageAccess__ {
//! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени public:
static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes(){return *(__Storage__::instance()->classesInfo); //! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name
} // namespace PICodeInfo //! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени
static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes() {
return *(__Storage__::instance()->classesInfo);
} // namespace PICodeInfo
//! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name //! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name
//! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени //! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени
static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { return *(__Storage__::instance()->enumsInfo); }
return *(__Storage__::instance()->enumsInfo);
}
static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() { //! \~english Access to value functions map
return *(__Storage__::instance()->accessValueFunctions); //! \~russian Доступ к карте функций значений
} static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() {
return *(__Storage__::instance()->accessValueFunctions);
}
static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() { //! \~english Access to type functions map
return *(__Storage__::instance()->accessTypeFunctions); //! \~russian Доступ к карте функций типов
} static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() {
return *(__Storage__::instance()->accessTypeFunctions);
}
static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() { //! \~english Access to offset functions map
return *(__Storage__::instance()->accessOffsetFunctions); //! \~russian Доступ к карте функций смещений
} static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() {
} return *(__Storage__::instance()->accessOffsetFunctions);
; }
};
#define PICODEINFO PICodeInfo::__StorageAccess__ #define PICODEINFO PICodeInfo::__StorageAccess__
class PIP_EXPORT //! \~english Deprecated interface for accessing classes info
ClassInfoInterface{public: const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()"){ //! \~russian Устаревший интерфейс для доступа к информации о классах
return __Storage__::instance() -> classesInfo; class PIP_EXPORT ClassInfoInterface {
} public:
} const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()") {
; return __Storage__::instance()->classesInfo;
}
};
static ClassInfoInterface classesInfo; static ClassInfoInterface classesInfo;
class PIP_EXPORT //! \~english Deprecated interface for accessing enums info
EnumsInfoInterface{public: const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()"){ //! \~russian Устаревший интерфейс для доступа к информации о перечислениях
return __Storage__::instance() -> enumsInfo; class PIP_EXPORT EnumsInfoInterface {
} public:
} const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()") {
; return __Storage__::instance()->enumsInfo;
}
};
static EnumsInfoInterface enumsInfo; static EnumsInfoInterface enumsInfo;
class PIP_EXPORT AccessValueFunctionInterface{ //! \~english Deprecated interface for accessing value functions
public: const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() //! \~russian Устаревший интерфейс для доступа к функциям значений
const DEPRECATEDM("use PICODEINFO::accessValueFunctions()"){ class PIP_EXPORT AccessValueFunctionInterface {
return __Storage__::instance() -> accessValueFunctions; public:
} const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessValueFunctions()") {
} return __Storage__::instance()->accessValueFunctions;
; }
};
static AccessValueFunctionInterface accessValueFunctions; static AccessValueFunctionInterface accessValueFunctions;
class PIP_EXPORT AccessTypeFunctionInterface{ //! \~english Deprecated interface for accessing type functions
public: const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() //! \~russian Устаревший интерфейс для доступа к функциям типов
const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()"){ class PIP_EXPORT AccessTypeFunctionInterface {
return __Storage__::instance() -> accessTypeFunctions; public:
} const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()") {
} return __Storage__::instance()->accessTypeFunctions;
; }
};
static AccessTypeFunctionInterface accessTypeFunctions; static AccessTypeFunctionInterface accessTypeFunctions;
@@ -372,6 +408,8 @@ STATIC_INITIALIZER_BEGIN
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
//! \~english Gets member value as PIByteArray
//! \~russian Получает значение члена как PIByteArray
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) { inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {
if (!p || !class_name || !member_name) return PIByteArray(); if (!p || !class_name || !member_name) return PIByteArray();
AccessValueFunction af = PICODEINFO::accessValueFunctions().value(class_name, (AccessValueFunction)0); AccessValueFunction af = PICODEINFO::accessValueFunctions().value(class_name, (AccessValueFunction)0);
@@ -379,6 +417,8 @@ inline PIByteArray getMemberValue(const void * p, const char * class_name, const
return af(p, member_name); return af(p, member_name);
} }
//! \~english Gets member type as string
//! \~russian Получает тип члена как строку
inline const char * getMemberType(const char * class_name, const char * member_name) { inline const char * getMemberType(const char * class_name, const char * member_name) {
if (!class_name || !member_name) return ""; if (!class_name || !member_name) return "";
AccessTypeFunction af = PICODEINFO::accessTypeFunctions().value(class_name, (AccessTypeFunction)0); AccessTypeFunction af = PICODEINFO::accessTypeFunctions().value(class_name, (AccessTypeFunction)0);
@@ -386,14 +426,20 @@ inline const char * getMemberType(const char * class_name, const char * member_n
return af(member_name); return af(member_name);
} }
//! \~english Gets member value as PIVariant
//! \~russian Получает значение члена как PIVariant
PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name); PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name);
//! \~english Serializes value to PIByteArray (for assignable types)
//! \~russian Сериализует значение в PIByteArray (для назначаемых типов)
template<typename T, typename std::enable_if<std::is_assignable<T &, const T &>::value, int>::type = 0> template<typename T, typename std::enable_if<std::is_assignable<T &, const T &>::value, int>::type = 0>
void serialize(PIByteArray & ret, const T & v) { void serialize(PIByteArray & ret, const T & v) {
ret << v; ret << v;
} }
//! \~english Empty serialization (for non-assignable types)
//! \~russian Пустая сериализация (для неназначаемых типов)
template<typename T, typename std::enable_if<!std::is_assignable<T &, const T &>::value, int>::type = 0> template<typename T, typename std::enable_if<!std::is_assignable<T &, const T &>::value, int>::type = 0>
void serialize(PIByteArray & ret, const T & v) {} void serialize(PIByteArray & ret, const T & v) {}

View File

@@ -1,8 +1,13 @@
/*! \file picodeparser.h /*! \file picodeparser.h
* \ingroup Code * \addtogroup Code
* \~\brief * \{
* \~
* \brief
* \~english C++ code parser * \~english C++ code parser
* \~russian Разбор C++ кода * \~russian Разбор C++ кода
* \details
* \~english Parser for analyzing C++ source files. Extracts information about classes, structures, enums, macros, functions, and members.
* \~russian Парсер для анализа C++ исходных файлов. Извлекает информацию о классах, структурах, перечислениях, макросах, функциях и членах.
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -39,6 +44,8 @@ inline bool _isCChar(const PIString & c) {
class PIP_EXPORT PICodeParser { class PIP_EXPORT PICodeParser {
public: public:
//! \~english Default constructor.
//! \~russian Конструктор по умолчанию.
PICodeParser(); PICodeParser();
enum Visibility { enum Visibility {
@@ -63,18 +70,27 @@ public:
typedef PIPair<PIString, PIString> Typedef; typedef PIPair<PIString, PIString> Typedef;
typedef PIMap<PIString, PIString> MetaMap; typedef PIMap<PIString, PIString> MetaMap;
//! \~english Represents a preprocessor macro.
//! \~russian Представляет препроцессорный макрос.
struct PIP_EXPORT Macro { struct PIP_EXPORT Macro {
Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) { Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) {
name = n; name = n;
value = v; value = v;
args = a; args = a;
} }
//! \~english Expand macro with given arguments.
//! \~russian Раскрыть макрос с заданными аргументами.
//! \param args_ Arguments string
//! \param ok Output flag indicating success
//! \return Expanded macro value
PIString expand(PIString args_, bool * ok = 0) const; PIString expand(PIString args_, bool * ok = 0) const;
PIString name; PIString name;
PIString value; PIString value;
PIStringList args; PIStringList args;
}; };
//! \~english Represents a class/struct member variable or function.
//! \~russian Представляет переменную-член или функцию класса/структуры.
struct PIP_EXPORT Member { struct PIP_EXPORT Member {
Member() { Member() {
visibility = Global; visibility = Global;
@@ -83,6 +99,8 @@ public:
is_type_ptr = false; is_type_ptr = false;
attributes = NoAttributes; attributes = NoAttributes;
} }
//! \~english Check if member is a bitfield.
//! \~russian Проверить, является ли член битовым полем.
bool isBitfield() const { return bits > 0; } bool isBitfield() const { return bits > 0; }
MetaMap meta; MetaMap meta;
PIString type; PIString type;
@@ -97,6 +115,8 @@ public:
int bits; int bits;
}; };
//! \~english Represents a parsed entity (class, struct, namespace, etc.).
//! \~russian Представляет разобранную сущность (класс, структуру, пространство имен и т.д.).
struct PIP_EXPORT Entity { struct PIP_EXPORT Entity {
Entity() { Entity() {
visibility = Global; visibility = Global;
@@ -118,6 +138,8 @@ public:
PIVector<Typedef> typedefs; PIVector<Typedef> typedefs;
}; };
//! \~english Represents an enumerator value.
//! \~russian Представляет значение перечисления.
struct PIP_EXPORT EnumeratorInfo { struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) { EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {
name = n; name = n;
@@ -129,6 +151,8 @@ public:
int value; int value;
}; };
//! \~english Represents a parsed enum type.
//! \~russian Представляет разобранный тип перечисления.
struct PIP_EXPORT Enum { struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()) { name = n; } Enum(const PIString & n = PIString()) { name = n; }
MetaMap meta; MetaMap meta;
@@ -136,25 +160,89 @@ public:
PIVector<EnumeratorInfo> members; PIVector<EnumeratorInfo> members;
}; };
//! \~english Parse C++ source file.
//! \~russian Разбор C++ исходного файла.
//! \param file Path to source file
//! \param follow_includes Whether to follow include directives
void parseFile(const PIString & file, bool follow_includes = true); void parseFile(const PIString & file, bool follow_includes = true);
//! \~english Parse multiple C++ source files.
//! \~russian Разбор нескольких C++ исходных файлов.
//! \param files List of file paths
//! \param follow_includes Whether to follow include directives
void parseFiles(const PIStringList & files, bool follow_includes = true); void parseFiles(const PIStringList & files, bool follow_includes = true);
//! \~english Parse C++ source from string content.
//! \~russian Разбор C++ исходного кода из строки.
//! \param fc Source code content
void parseFileContent(PIString fc); void parseFileContent(PIString fc);
//! \~english Add directory to search for include files.
//! \~russian Добавить директорию для поиска включаемых файлов.
//! \param dir Directory path
void includeDirectory(const PIString & dir) { includes << dir; } void includeDirectory(const PIString & dir) { includes << dir; }
//! \~english Add custom macro definition.
//! \~russian Добавить пользовательское определение макроса.
//! \param def_name Macro name
//! \param def_value Macro value
void addDefine(const PIString & def_name, const PIString & def_value) { custom_defines << Define(def_name, def_value); } void addDefine(const PIString & def_name, const PIString & def_value) { custom_defines << Define(def_name, def_value); }
//! \~english Check if name refers to an enum type.
//! \~russian Проверить, является ли имя типом перечисления.
//! \param name Name to check
//! \return true if name is an enum
bool isEnum(const PIString & name); bool isEnum(const PIString & name);
//! \~english Find entity by name.
//! \~russian Найти сущность по имени.
//! \param en Entity name
//! \return Pointer to entity or nullptr
Entity * findEntityByName(const PIString & en); Entity * findEntityByName(const PIString & en);
//! \~english Get list of parsed files.
//! \~russian Получить список разобранных файлов.
//! \return List of file paths
PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); } PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); }
//! \~english Get main file path.
//! \~russian Получить путь к главному файлу.
//! \return Main file path
PIString mainFile() const { return main_file; } PIString mainFile() const { return main_file; }
//! \~english Get global scope entity.
//! \~russian Получить сущность глобальной области видимости.
//! \return Pointer to global entity
const PICodeParser::Entity * global() const { return &root_; } const PICodeParser::Entity * global() const { return &root_; }
//! \~english Get maximum iterations for macros substitution.
//! \~russian Получить максимальное количество итераций для подстановки макросов.
//! \return Maximum iterations count
int macrosSubstitutionMaxIterations() const { return macros_iter; } int macrosSubstitutionMaxIterations() const { return macros_iter; }
//! \~english Set maximum iterations for macros substitution.
//! \~russian Установить максимальное количество итераций для подстановки макросов.
//! \param value Maximum iterations count
void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; } void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; }
//! \~english List of defined macros.
//! \~russian Список определенных макросов.
PIVector<Define> defines, custom_defines; PIVector<Define> defines, custom_defines;
//! \~english List of macro definitions with expansion.
//! \~russian Список определений макросов с подстановкой.
PIVector<Macro> macros; PIVector<Macro> macros;
//! \~english List of enumerated types.
//! \~russian Список типов перечислений.
PIVector<Enum> enums; PIVector<Enum> enums;
//! \~english List of type definitions.
//! \~russian Список определений типов.
PIVector<Typedef> typedefs; PIVector<Typedef> typedefs;
//! \~english List of parsed entities (classes, structs, etc.).
//! \~russian Список разобранных сущностей (классов, структур и т.д.).
PIVector<Entity *> entities; PIVector<Entity *> entities;
private: private:
@@ -195,4 +283,7 @@ private:
PIMap<PIString, MetaMap> tmp_meta; PIMap<PIString, MetaMap> tmp_meta;
}; };
/*! \}
*/
#endif // PICODEPARSER_H #endif // PICODEPARSER_H

View File

@@ -29,12 +29,12 @@
#include "pithread.h" #include "pithread.h"
#include "pitime.h" #include "pitime.h"
#define WAIT_FOR_EXIT \ #define WAIT_FOR_EXIT \
while (!PIKbdListener::exiting) \ while (!PIKbdListener::exiting) \
piMSleep(PIP_MIN_MSLEEP * 5); \ piMSleep(PIP_MIN_MSLEEP * 5); \
if (PIKbdListener::instance()) { \ if (PIKbdListener::instance()) { \
if (!PIKbdListener::instance()->stopAndWait(PISystemTime::fromSeconds(1))) PIKbdListener::instance()->terminate(); \ if (!PIKbdListener::instance()->stopAndWait(PISystemTime::fromSeconds(1))) PIKbdListener::instance()->terminate(); \
} }
class PIP_EXPORT PIKbdListener: public PIThread { class PIP_EXPORT PIKbdListener: public PIThread {
@@ -177,13 +177,29 @@ public:
//! Returns exit key, default 'Q' //! Returns exit key, default 'Q'
int exitKey() const { return exit_key; } int exitKey() const { return exit_key; }
//! \brief
//! \~english Returns double click interval in seconds
//! \~russian Возвращает интервал двойного клика в секундах
double doubleClickInterval() const { return dbl_interval; } double doubleClickInterval() const { return dbl_interval; }
//! \brief
//! \~english Sets double click interval
//! \~russian Устанавливает интервал двойного клика
void setDoubleClickInterval(double v) { dbl_interval = v; } void setDoubleClickInterval(double v) { dbl_interval = v; }
//! \brief
//! \~english Reads keyboard input
//! \~russian Читает ввод с клавиатуры
void readKeyboard(); void readKeyboard();
//! \brief
//! \~english Stops keyboard listening
//! \~russian Останавливает прослушивание клавиатуры
void stop(); void stop();
//! \brief
//! \~english Stops and waits for completion
//! \~russian Останавливает и ожидает завершения
bool stopAndWait(PISystemTime timeout = {}); bool stopAndWait(PISystemTime timeout = {});
//! Returns if keyboard listening is active (not running!) //! Returns if keyboard listening is active (not running!)

View File

@@ -1,9 +1,11 @@
/*! \file piscreen.h //! \file piscreen.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Console tiling manager //! \~english Console tiling manager
* \~russian Консольный тайловый менеджер //! \~russian Консольный тайловый менеджер
*/ //! \details
//! \~english Main console screen manager providing tile-based UI rendering and keyboard input.
//! \~russian Основной менеджер консольного экрана, обеспечивающий отрисовку UI на основе тайлов и ввод с клавиатуры.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console GUI Console GUI
@@ -31,6 +33,9 @@
#include "piscreentile.h" #include "piscreentile.h"
//! \brief
//! \~english Console tiling manager
//! \~russian Консольный тайловый менеджер
class PIP_CONSOLE_EXPORT PIScreen class PIP_CONSOLE_EXPORT PIScreen
: public PIThread : public PIThread
, public PIScreenTypes::PIScreenBase { , public PIScreenTypes::PIScreenBase {
@@ -38,46 +43,126 @@ class PIP_CONSOLE_EXPORT PIScreen
class SystemConsole; class SystemConsole;
public: public:
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it //! \brief
//! \~english Constructs PIScreen
//! \~russian Создает PIScreen
//! \param startNow Start immediately / Запустить немедленно
//! \param slot Keyboard handler function / Обработчик клавиатуры
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0); PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
~PIScreen(); ~PIScreen();
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Enables exit capture with key
//! \~russian Включает захват выхода по клавише
void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); } void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); }
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Disables exit capture
//! \~russian Отключает захват выхода
void disableExitCapture() { listener->disableExitCapture(); } void disableExitCapture() { listener->disableExitCapture(); }
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Checks if exit is captured
//! \~russian Проверяет, захвачен ли выход
bool exitCaptured() const { return listener->exitCaptured(); } bool exitCaptured() const { return listener->exitCaptured(); }
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Returns exit key
//! \~russian Возвращает клавишу выхода
int exitKey() const { return listener->exitKey(); } int exitKey() const { return listener->exitKey(); }
//! \brief
//! \~english Returns window width
//! \~russian Возвращает ширину окна
int windowWidth() const { return console.width; } int windowWidth() const { return console.width; }
//! \brief
//! \~english Returns window height
//! \~russian Возвращает высоту окна
int windowHeight() const { return console.height; } int windowHeight() const { return console.height; }
//! \brief
//! \~english Checks if mouse is enabled
//! \~russian Проверяет, включена ли мышь
bool isMouseEnabled() const { return mouse_; } bool isMouseEnabled() const { return mouse_; }
//! \brief
//! \~english Sets mouse enabled state
//! \~russian Устанавливает состояние мыши
void setMouseEnabled(bool on); void setMouseEnabled(bool on);
//! \brief
//! \~english Returns root tile
//! \~russian Возвращает корневой тайл
PIScreenTile * rootTile() { return &root; } PIScreenTile * rootTile() { return &root; }
//! \brief
//! \~english Finds tile by name
//! \~russian Находит тайл по имени
PIScreenTile * tileByName(const PIString & name); PIScreenTile * tileByName(const PIString & name);
//! \brief
//! \~english Sets dialog tile
//! \~russian Устанавливает диалоговый тайл
void setDialogTile(PIScreenTile * t); void setDialogTile(PIScreenTile * t);
//! \brief
//! \~english Returns current dialog tile
//! \~russian Возвращает текущий диалоговый тайл
PIScreenTile * dialogTile() const { return tile_dialog; } PIScreenTile * dialogTile() const { return tile_dialog; }
//! \brief
//! \~english Returns screen drawer
//! \~russian Возвращает отрисовщик экрана
PIScreenDrawer * drawer() { return &drawer_; } PIScreenDrawer * drawer() { return &drawer_; }
//! \brief
//! \~english Clears the screen
//! \~russian Очищает экран
void clear() { drawer_.clear(); } void clear() { drawer_.clear(); }
//! \brief
//! \~english Resizes screen
//! \~russian Изменяет размер экрана
void resize(int w, int h) { console.resize(w, h); } void resize(int w, int h) { console.resize(w, h); }
//! \brief
//! \~english Waits for finish
//! \~russian Ожидает завершения
EVENT_HANDLER0(void, waitForFinish); EVENT_HANDLER0(void, waitForFinish);
//! \brief
//! \~english Starts screen
//! \~russian Запускает экран
EVENT_HANDLER0(void, start) { start(false); } EVENT_HANDLER0(void, start) { start(false); }
//! \brief
//! \~english Starts screen
//! \~russian Запускает экран
EVENT_HANDLER1(void, start, bool, wait); EVENT_HANDLER1(void, start, bool, wait);
//! \brief
//! \~english Stops screen
//! \~russian Останавливает экран
EVENT_HANDLER0(void, stop) { stop(false); } EVENT_HANDLER0(void, stop) { stop(false); }
//! \brief
//! \~english Stops screen
//! \~russian Останавливает экран
EVENT_HANDLER1(void, stop, bool, clear); EVENT_HANDLER1(void, stop, bool, clear);
//! \brief
//! \~english Raised on key pressed
//! \~russian Вызывается при нажатии клавиши
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data); EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
//! \brief
//! \~english Raised on tile event
//! \~russian Вызывается при событии тайла
EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e); EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e);
//! \handlers //! \handlers

View File

@@ -1,9 +1,11 @@
/*! \file piscreenconsole.h //! \file piscreenconsole.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Tile for PIScreen with PIConsole API //! \~english Tile for PIScreen with PIConsole API
* \~russian Тайл для PIScreen с API PIConsole //! \~russian Тайл для PIScreen с API PIConsole
*/ //! \details
//! \~english Provides tiles for displaying variable data and console-like content.
//! \~russian Обеспечивает тайлы для отображения данных переменных и консольного контента.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API Tile for PIScreen with PIConsole API
@@ -32,17 +34,36 @@
/// NOTE: incomplete class /// NOTE: incomplete class
/// TODO: write TileVars /// TODO: write TileVars
//! \brief
//! \~english Tile for displaying variable data
//! \~russian Тайл для отображения данных переменных
//! \addtogroup Console
//! \{
//! \brief
//! \~english Tile for displaying variable data
//! \~russian Тайл для отображения данных переменных
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile { class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
public: public:
TileVars(const PIString & n = PIString()); //! \brief
//! \~english Constructs TileVars
//! \~russian Создает TileVars
//! \param n Tile name / Имя тайла
explicit TileVars(const PIString & n = PIString());
protected: protected:
//! \brief Variable data structure
struct PIP_CONSOLE_EXPORT Variable { struct PIP_CONSOLE_EXPORT Variable {
Variable() { Variable() {
nx = ny = type = offset = bitFrom = bitCount = size = 0; nx = ny = type = offset = bitFrom = bitCount = size = 0;
format = PIScreenTypes::CellFormat(); format = PIScreenTypes::CellFormat();
ptr = 0; ptr = 0;
} }
//! \brief
//! \~english Checks if variable is empty
//! \~russian Проверяет, пустая ли переменная
bool isEmpty() const { return (ptr == 0); } bool isEmpty() const { return (ptr == 0); }
PIString name; PIString name;
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
@@ -67,16 +88,38 @@ protected:
ptr = src.ptr; ptr = src.ptr;
}*/ }*/
}; };
//! \brief
//! \~english Returns variables
//! \~russian Возвращает переменные
PIVector<Variable> variables; PIVector<Variable> variables;
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
}; };
//! \brief
//! \~english Console-style tile for PIScreen
//! \~russian Консольный тайл для PIScreen
//! \brief
//! \~english Console-style tile for PIScreen
//! \~russian Консольный тайл для PIScreen
class PIP_CONSOLE_EXPORT PIScreenConsoleTile: public PIScreenTile { class PIP_CONSOLE_EXPORT PIScreenConsoleTile: public PIScreenTile {
public: public:
PIScreenConsoleTile(); //! \brief
//! \~english Constructs PIScreenConsoleTile
//! \~russian Создает PIScreenConsoleTile
explicit PIScreenConsoleTile();
}; };
#endif // PISCREENCONSOLE_H #endif // PISCREENCONSOLE_H

View File

@@ -1,9 +1,11 @@
/*! \file piscreendrawer.h //! \file piscreendrawer.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Drawer for PIScreen //! \~english Drawer for PIScreen
* \~russian Отрисовщик для PIScreen //! \~russian Отрисовщик для PIScreen
*/ //! \details
//! \~english Provides drawing primitives for console screen rendering.
//! \~russian Обеспечивает примитивы отрисовки для рендеринга консольного экрана.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Drawer for PIScreen Drawer for PIScreen
@@ -30,31 +32,54 @@
#include "piscreentypes.h" #include "piscreentypes.h"
#include "pistring.h" #include "pistring.h"
//! \brief Screen drawer for console rendering
//! \~english Console screen drawer for rendering graphics
//! \~russian Отрисовщик консольного экрана для рендеринга графики
//! \brief
//! \~english Console screen drawer for rendering graphics
//! \~russian Отрисовщик консольного экрана для рендеринга графики
class PIP_CONSOLE_EXPORT PIScreenDrawer { class PIP_CONSOLE_EXPORT PIScreenDrawer {
friend class PIScreen; friend class PIScreen;
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell>> & c); PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell>> & c);
public: public:
//! \brief ASCII art characters
enum ArtChar { enum ArtChar {
LineVertical = 1, LineVertical = 1, //!< Vertical line / Вертикальная линия
LineHorizontal, LineHorizontal, //!< Horizontal line / Горизонтальная линия
Cross, Cross, //!< Cross / Крест
CornerTopLeft, CornerTopLeft, //!< Top-left corner / Угол сверху-слева
CornerTopRight, CornerTopRight, //!< Top-right corner / Угол сверху-справа
CornerBottomLeft, CornerBottomLeft, //!< Bottom-left corner / Угол снизу-слева
CornerBottomRight, CornerBottomRight, //!< Bottom-right corner / Угол снизу-справа
Unchecked, Unchecked, //!< Unchecked box / Неотмеченная клетка
Checked Checked //!< Checked box / Отмеченная клетка
}; };
//! \brief
//! \~english Clears the screen
//! \~russian Очищает экран
void clear(); void clear();
//! \brief
//! \~english Clears rectangle
//! \~russian Очищает прямоугольник
void clearRect(int x0, int y0, int x1, int y1) { fillRect(x0, y0, x1, y1, ' '); } void clearRect(int x0, int y0, int x1, int y1) { fillRect(x0, y0, x1, y1, ' '); }
//! \brief
//! \~english Draws pixel
//! \~russian Рисует пиксель
void drawPixel(int x, void drawPixel(int x,
int y, int y,
const PIChar & c, const PIChar & c,
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws line
//! \~russian Рисует линию
void drawLine(int x0, void drawLine(int x0,
int y0, int y0,
int x1, int x1,
@@ -63,6 +88,10 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws rectangle
//! \~russian Рисует прямоугольник
void drawRect(int x0, void drawRect(int x0,
int y0, int y0,
int x1, int x1,
@@ -71,6 +100,10 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws frame
//! \~russian Рисует рамку
void drawFrame(int x0, void drawFrame(int x0,
int y0, int y0,
int x1, int x1,
@@ -78,12 +111,20 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws text
//! \~russian Рисует текст
void drawText(int x, void drawText(int x,
int y, int y,
const PIString & s, const PIString & s,
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Transparent, PIScreenTypes::Color col_back = PIScreenTypes::Transparent,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Fills rectangle
//! \~russian Заполняет прямоугольник
void fillRect(int x0, void fillRect(int x0,
int y0, int y0,
int x1, int x1,
@@ -92,10 +133,20 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Fills rectangle with content
//! \~russian Заполняет прямоугольник содержимым
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell>> & content); void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell>> & content);
//! \brief
//! \~english Returns art character by type
//! \~russian Возвращает символ искусства по типу
PIChar artChar(const ArtChar type) const { return arts_.value(type, PIChar(' ')); } PIChar artChar(const ArtChar type) const { return arts_.value(type, PIChar(' ')); }
//! \brief
//! \~english Clears cell matrix
//! \~russian Очищает матрицу ячеек
static void clear(PIVector<PIVector<PIScreenTypes::Cell>> & cells); static void clear(PIVector<PIVector<PIScreenTypes::Cell>> & cells);
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file piscreentile.h //! \file piscreentile.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Basic PIScreen tile //! \~english Basic PIScreen tile
* \~russian Базовый тайл для PIScreen //! \~russian Базовый тайл для PIScreen
*/ //! \details
//! \~english Base class for all screen tiles providing layout and event handling.
//! \~russian Базовый класс для всех экранных тайлов, обеспечивающий компоновку и обработку событий.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile
@@ -32,27 +34,92 @@
class PIScreenDrawer; class PIScreenDrawer;
//! \brief
//! \~english Base tile class for console screen
//! \~russian Базовый класс тайла для консольного экрана
//! \brief
//! \~english Base tile class for console screen
//! \~russian Базовый класс тайла для консольного экрана
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject { class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
friend class PIScreen; friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject); PIOBJECT_SUBCLASS(PIScreenTile, PIObject);
public: public:
//! \brief
//! \~english Constructs PIScreenTile
//! \~russian Создает PIScreenTile
//! \param n Tile name / Имя тайла
//! \param d Layout direction / Направление компоновки
//! \param p Size policy / Политика размера
PIScreenTile(const PIString & n = PIString(), PIScreenTile(const PIString & n = PIString(),
PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::Direction d = PIScreenTypes::Vertical,
PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred); PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIScreenTile(); virtual ~PIScreenTile();
//! \brief
//! \~english Adds child tile
//! \~russian Добавляет дочерний тайл
void addTile(PIScreenTile * t); void addTile(PIScreenTile * t);
//! \brief
//! \~english Takes ownership of tile
//! \~russian Забирает владение тайла
void takeTile(PIScreenTile * t); void takeTile(PIScreenTile * t);
//! \brief
//! \~english Removes child tile
//! \~russian Удаляет дочерний тайл
void removeTile(PIScreenTile * t); void removeTile(PIScreenTile * t);
//! \brief
//! \~english Returns parent tile
//! \~russian Возвращает родительский тайл
PIScreenTile * parentTile() const { return parent; } PIScreenTile * parentTile() const { return parent; }
//! \brief
//! \~english Returns child tiles
//! \~russian Возвращает дочерние тайлы
//! \param only_visible Only visible tiles / Только видимые тайлы
PIVector<PIScreenTile *> children(bool only_visible = false); PIVector<PIScreenTile *> children(bool only_visible = false);
//! \brief
//! \~english Returns child under mouse position
//! \~russian Возвращает тайл под мышью
PIScreenTile * childUnderMouse(int x, int y); PIScreenTile * childUnderMouse(int x, int y);
//! \brief
//! \~english Shows tile
//! \~russian Показывает тайл
void show() { visible = true; } void show() { visible = true; }
//! \brief
//! \~english Hides tile
//! \~russian Скрывает тайл
void hide() { visible = false; } void hide() { visible = false; }
//! \brief
//! \~english Sets focus to this tile
//! \~russian Устанавливает фокус на этот тайл
void setFocus(); void setFocus();
//! \brief
//! \~english Checks if tile has focus
//! \~russian Проверяет, имеет ли тайл фокус
bool hasFocus() const { return has_focus; } bool hasFocus() const { return has_focus; }
//! \brief
//! \~english Sets all margins
//! \~russian Устанавливает все отступы
void setMargins(int m) { marginLeft = marginRight = marginTop = marginBottom = m; } void setMargins(int m) { marginLeft = marginRight = marginTop = marginBottom = m; }
//! \brief
//! \~english Sets individual margins
//! \~russian Устанавливает отдельные отступы
void setMargins(int l, int r, int t, int b) { void setMargins(int l, int r, int t, int b) {
marginLeft = l; marginLeft = l;
marginRight = r; marginRight = r;
@@ -60,9 +127,24 @@ public:
marginBottom = b; marginBottom = b;
} }
//! \brief
//! \~english Returns tile X position
//! \~russian Возвращает позицию X тайла
int x() const { return x_; } int x() const { return x_; }
//! \brief
//! \~english Returns tile Y position
//! \~russian Возвращает позицию Y тайла
int y() const { return y_; } int y() const { return y_; }
//! \brief
//! \~english Returns tile width
//! \~russian Возвращает ширину тайла
int width() const { return width_; } int width() const { return width_; }
//! \brief
//! \~english Returns tile height
//! \~russian Возвращает высоту тайла
int height() const { return height_; } int height() const { return height_; }
PIScreenTypes::Direction direction; PIScreenTypes::Direction direction;
@@ -77,29 +159,64 @@ public:
bool visible; bool visible;
protected: protected:
//! Returns desired tile size in "w" and "h" //! \brief
//! \~english Returns desired tile size in "w" and "h"
//! \~russian Возвращает желаемый размер тайла в "w" и "h"
virtual void sizeHint(int & w, int & h) const; virtual void sizeHint(int & w, int & h) const;
//! Tile has been resized to "w"x"h" //! \brief
//! \~english Tile has been resized to "w"x"h"
//! \~russian Тайл был изменен на "w"x"h"
virtual void resizeEvent(int w, int h) {} virtual void resizeEvent(int w, int h) {}
//! Draw tile with drawer "d" in world-space coordinates //! \brief
//! \~english Draw tile with drawer "d" in world-space coordinates
//! \~russian Рисует тайл отрисовщиком "d" в мировых координатах
virtual void drawEvent(PIScreenDrawer * d) {} virtual void drawEvent(PIScreenDrawer * d) {}
//! Return "true" if you process key //! \brief
//! \~english Return "true" if you process key
//! \~russian Возвращает "true" если вы обрабатываете клавишу
virtual bool keyEvent(PIKbdListener::KeyEvent key) { return false; } virtual bool keyEvent(PIKbdListener::KeyEvent key) { return false; }
//! Return "true" if you process event //! \brief
//! \~english Return "true" if you process event
//! \~russian Возвращает "true" если вы обрабатываете событие
virtual bool mouseEvent(PIKbdListener::MouseEvent me) { return false; } virtual bool mouseEvent(PIKbdListener::MouseEvent me) { return false; }
//! Return "true" if you process wheel //! \brief
//! \~english Return "true" if you process wheel
//! \~russian Возвращает "true" если вы обрабатываете колесо
virtual bool wheelEvent(PIKbdListener::WheelEvent we) { return false; } virtual bool wheelEvent(PIKbdListener::WheelEvent we) { return false; }
//! \brief
//! \~english Raises tile event
//! \~russian Вызывает событие тайла
void raiseEvent(PIScreenTypes::TileEvent e); void raiseEvent(PIScreenTypes::TileEvent e);
//! \brief
//! \~english Sets screen reference
//! \~russian Устанавливает ссылку на экран
void setScreen(PIScreenTypes::PIScreenBase * s); void setScreen(PIScreenTypes::PIScreenBase * s);
//! \brief
//! \~english Deletes all children
//! \~russian Удаляет всех потомков
void deleteChildren(); void deleteChildren();
//! \brief
//! \~english Internal draw event
//! \~russian Внутреннее событие отрисовки
void drawEventInternal(PIScreenDrawer * d); void drawEventInternal(PIScreenDrawer * d);
//! \brief
//! \~english Performs layout
//! \~russian Выполняет компоновку
void layout(); void layout();
//! \brief
//! \~english Checks if layout is needed
//! \~russian Проверяет, нужна ли компоновка
bool needLayout() { return size_policy != PIScreenTypes::Ignore; } bool needLayout() { return size_policy != PIScreenTypes::Ignore; }
PIVector<PIScreenTile *> tiles; PIVector<PIScreenTile *> tiles;

View File

@@ -1,9 +1,11 @@
/*! \file piscreentiles.h //! \file piscreentiles.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Various tiles for PIScreen //! \~english Various tiles for PIScreen
* \~russian Различные тайлы для PIScreen //! \~russian Различные тайлы для PIScreen
*/ //! \details
//! \~english Provides ready-to-use tile implementations for common UI elements.
//! \~russian Обеспечивает готовые к использованию реализации тайлов для общих элементов UI.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Various tiles for PIScreen Various tiles for PIScreen
@@ -30,125 +32,326 @@
#include "piscreentile.h" #include "piscreentile.h"
//! \brief
//! \~english Tile for displaying simple text content
//! \~russian Тайл для отображения простого текстового контента
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile { class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile); PIOBJECT_SUBCLASS(TileSimple, PIScreenTile);
public: public:
//! \brief Row type
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
//! \brief
//! \~english Constructs TileSimple
//! \~russian Создает TileSimple
//! \param n Tile name / Имя тайла
TileSimple(const PIString & n = PIString()); TileSimple(const PIString & n = PIString());
//! \brief
//! \~english Constructs TileSimple with row
//! \~russian Создает TileSimple со строкой
//! \param r Row content / Содержимое строки
TileSimple(const Row & r); TileSimple(const Row & r);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileSimple() {} virtual ~TileSimple() {}
//! \brief Tile content rows
PIVector<Row> content; PIVector<Row> content;
//! \brief Text alignment
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
}; };
class TileList; class TileList;
//! \brief
//! \~english Scrollbar for list containers
//! \~russian Полоса прокрутки для списков
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile { class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile); PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile);
friend class TileList; friend class TileList;
public: public:
//! \brief
//! \~english Constructs TileScrollBar
//! \~russian Создает TileScrollBar
//! \param n Tile name / Имя тайла
TileScrollBar(const PIString & n = PIString()); TileScrollBar(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileScrollBar() {} virtual ~TileScrollBar() {}
//! \brief
//! \~english Sets minimum value
//! \~russian Устанавливает минимальное значение
void setMinimum(int v); void setMinimum(int v);
//! \brief
//! \~english Sets maximum value
//! \~russian Устанавливает максимальное значение
void setMaximum(int v); void setMaximum(int v);
//! \brief
//! \~english Sets current value
//! \~russian Устанавливает текущее значение
void setValue(int v); void setValue(int v);
//! \brief
//! \~english Returns minimum value
//! \~russian Возвращает минимальное значение
int minimum() const { return minimum_; } int minimum() const { return minimum_; }
//! \brief
//! \~english Returns maximum value
//! \~russian Возвращает максимальное значение
int maximum() const { return maximum_; } int maximum() const { return maximum_; }
//! \brief
//! \~english Returns current value
//! \~russian Возвращает текущее значение
int value() const { return value_; } int value() const { return value_; }
//! \brief Scrollbar thickness
int thickness; int thickness;
protected: protected:
//! \brief Validates scrollbar state
//! \~english Validates scrollbar state
//! \~russian Проверяет состояние полосы прокрутки
void _check(); void _check();
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
int minimum_, maximum_, value_; int minimum_, maximum_, value_;
PIChar line_char; PIChar line_char;
}; };
//! \brief
//! \~english Scrollable list tile
//! \~russian Прокручиваемый список
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile { class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile); PIOBJECT_SUBCLASS(TileList, PIScreenTile);
public: public:
//! \brief Selection mode
enum SelectionMode { enum SelectionMode {
NoSelection, NoSelection, //!< No selection / Без выделения
SingleSelection, SingleSelection, //!< Single item selection / Выделение одного элемента
MultiSelection MultiSelection //!< Multiple items selection / Выделение нескольких элементов
};
enum EventType {
SelectionChanged,
RowPressed
}; };
//! \brief Event type
enum EventType {
SelectionChanged, //!< Selection changed / Выделение изменено
RowPressed //!< Row pressed / Строка нажата
};
//! \brief
//! \~english Constructs TileList
//! \~russian Создает TileList
//! \param n Tile name / Имя тайла
//! \param sm Selection mode / Режим выделения
TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection); TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileList() {} virtual ~TileList() {}
//! \brief Row type
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
//! \brief List content
PIDeque<Row> content; PIDeque<Row> content;
//! \brief Text alignment
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \brief Selection mode
SelectionMode selection_mode; SelectionMode selection_mode;
//! \brief Selected indices
PISet<int> selected; PISet<int> selected;
//! \brief Line height
int lhei, cur, offset; int lhei, cur, offset;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Called when resized
//! \~russian Вызывается при изменении размера
void resizeEvent(int w, int h) override; void resizeEvent(int w, int h) override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
//! \brief
//! \~english Handles wheel events
//! \~russian Обрабатывает события колеса
bool wheelEvent(PIKbdListener::WheelEvent we) override; bool wheelEvent(PIKbdListener::WheelEvent we) override;
TileScrollBar * scroll; TileScrollBar * scroll;
bool mouse_sel; bool mouse_sel;
}; };
//! \brief
//! \~english Clickable button tile
//! \~russian Кликабельная кнопка
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile { class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile); PIOBJECT_SUBCLASS(TileButton, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileButton
//! \~russian Создает TileButton
//! \param n Tile name / Имя тайла
TileButton(const PIString & n = PIString()); TileButton(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileButton() {} virtual ~TileButton() {}
//! \brief Event type
enum EventType { enum EventType {
ButtonClicked ButtonClicked //!< Button clicked / Кнопка нажата
}; };
//! \brief Button format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Button text
PIString text; PIString text;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
}; };
//! \brief
//! \~english Group of buttons with selection
//! \~russian Группа кнопок с выбором
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile { class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile); PIOBJECT_SUBCLASS(TileButtons, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileButtons
//! \~russian Создает TileButtons
//! \param n Tile name / Имя тайла
TileButtons(const PIString & n = PIString()); TileButtons(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileButtons() {} virtual ~TileButtons() {}
//! \brief Event type
enum EventType { enum EventType {
ButtonSelected ButtonSelected //!< Button selected / Кнопка выбрана
}; };
//! \brief Button type
typedef PIPair<PIString, PIScreenTypes::CellFormat> Button; typedef PIPair<PIString, PIScreenTypes::CellFormat> Button;
//! \brief Button alignment
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \brief Button content
PIVector<Button> content; PIVector<Button> content;
//! \brief Current selection
int cur; int cur;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
//! \brief Button rectangle
struct Rect { struct Rect {
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0), y0(_y0), x1(_x1), y1(_y1) {} Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0), y0(_y0), x1(_x1), y1(_y1) {}
int x0, y0, x1, y1; int x0, y0, x1, y1;
@@ -157,74 +360,198 @@ protected:
}; };
//! \brief
//! \~english Checkbox with toggle state
//! \~russian Флажок с переключаемым состоянием
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile { class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile); PIOBJECT_SUBCLASS(TileCheck, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileCheck
//! \~russian Создает TileCheck
//! \param n Tile name / Имя тайла
TileCheck(const PIString & n = PIString()); TileCheck(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileCheck() {} virtual ~TileCheck() {}
//! \brief Event type
enum EventType { enum EventType {
Toggled Toggled //!< State toggled / Состояние переключено
}; };
//! \brief Checkbox format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Checkbox text
PIString text; PIString text;
//! \brief Checkbox state
bool toggled; bool toggled;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
}; };
//! \brief
//! \~english Progress bar for displaying progress
//! \~russian Индикатор прогресса
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile { class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile); PIOBJECT_SUBCLASS(TileProgress, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileProgress
//! \~russian Создает TileProgress
//! \param n Tile name / Имя тайла
TileProgress(const PIString & n = PIString()); TileProgress(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileProgress() {} virtual ~TileProgress() {}
//! \brief Progress format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Prefix text
PIString prefix; PIString prefix;
//! \brief Suffix text
PIString suffix; PIString suffix;
//! \brief Maximum value
double maximum; double maximum;
//! \brief Current value
double value; double value;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
}; };
//! \brief
//! \~english Tile for displaying console output
//! \~russian Тайл для отображения консольного вывода
//! \brief
//! \~english Tile for displaying console output
//! \~russian Тайл для отображения консольного вывода
class PIP_CONSOLE_EXPORT TilePICout: public TileList { class PIP_CONSOLE_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile); PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TilePICout
//! \~russian Создает TilePICout
//! \param n Tile name / Имя тайла
TilePICout(const PIString & n = PIString()); TilePICout(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TilePICout() {} virtual ~TilePICout() {}
//! \brief Output format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Maximum lines
int max_lines; int max_lines;
protected: protected:
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
}; };
//! \brief
//! \~english Text input tile
//! \~russian Тайл текстового ввода
//! \brief
//! \~english Text input tile
//! \~russian Тайл текстового ввода
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile { class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile); PIOBJECT_SUBCLASS(TileInput, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileInput
//! \~russian Создает TileInput
//! \param n Tile name / Имя тайла
TileInput(const PIString & n = PIString()); TileInput(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileInput() {} virtual ~TileInput() {}
//! \brief Input format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Input text
PIString text; PIString text;
//! \brief Maximum text length
int max_length; int max_length;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Resets cursor position
//! \~russian Сбрасывает позицию курсора
void reserCursor(); void reserCursor();
int cur, offset; int cur, offset;
bool inv; bool inv;

View File

@@ -1,9 +1,11 @@
/*! \file piscreentypes.h //! \file piscreentypes.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Types for PIScreen //! \~english Types for PIScreen
* \~russian Типы для PIScreen //! \~russian Типы для PIScreen
*/ //! \details
//! \~english Provides common types used by screen tiles and drawer.
//! \~russian Обеспечивает общие типы, используемые тайлами и отрисовщиком экрана.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Types for PIScreen Types for PIScreen
@@ -34,7 +36,9 @@ class PIScreenTile;
namespace PIScreenTypes { namespace PIScreenTypes {
//! Color for chars or background //! \brief Color for chars or background
//! \~english Console color values
//! \~russian Значения цветов консоли
enum Color { enum Color {
Default /** Default */, Default /** Default */,
Black /** Black */, Black /** Black */,
@@ -48,7 +52,9 @@ enum Color {
Transparent /** Save previous color */ Transparent /** Save previous color */
}; };
//! Flags for chars //! \brief Flags for chars
//! \~english Character formatting flags
//! \~russian Флаги форматирования символов
enum CharFlag { enum CharFlag {
Bold /** Bold or bright */ = 0x1, Bold /** Bold or bright */ = 0x1,
Blink /** Blink text */ = 0x2, Blink /** Blink text */ = 0x2,
@@ -56,14 +62,18 @@ enum CharFlag {
Inverse = 0x08 Inverse = 0x08
}; };
//! Alignment //! \brief Alignment
//! \~english Text alignment modes
//! \~russian Режимы выравнивания текста
enum Alignment { enum Alignment {
Left /** Left */, Left /** Left */,
Center /** Center */, Center /** Center */,
Right /** Right */ Right /** Right */
}; };
//! Size policy //! \brief Size policy
//! \~english Tile sizing policies
//! \~russian Политики размеров тайлов
enum SizePolicy { enum SizePolicy {
Fixed /** Fixed size */, Fixed /** Fixed size */,
Preferred /** Preferred size */, Preferred /** Preferred size */,
@@ -71,13 +81,17 @@ enum SizePolicy {
Ignore /** Ignore layout logic */ Ignore /** Ignore layout logic */
}; };
//! Direction //! \brief Direction
//! \~english Layout directions
//! \~russian Направления компоновки
enum Direction { enum Direction {
Horizontal /** Horizontal */, Horizontal /** Horizontal */,
Vertical /** Vertical */ Vertical /** Vertical */
}; };
//! Focus flags //! \brief Focus flags
//! \~english Tile focus behavior flags
//! \~russian Флаги поведения фокуса тайла
enum FocusFlag { enum FocusFlag {
CanHasFocus /** Tile can has focus */ = 0x1, CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab /** Focus passed to next tile by tab key */ = 0x2, NextByTab /** Focus passed to next tile by tab key */ = 0x2,
@@ -92,8 +106,19 @@ enum FocusFlag {
typedef PIFlags<CharFlag> CharFlags; typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags; typedef PIFlags<FocusFlag> FocusFlags;
//! \brief Cell format union
//! \~english Packed cell formatting data
//! \~russian Упакованные данные форматирования ячейки
union PIP_CONSOLE_EXPORT CellFormat { union PIP_CONSOLE_EXPORT CellFormat {
//! \brief
//! \~english Constructs CellFormat from raw value
//! \~russian Создает CellFormat из сырого значения
CellFormat(ushort f = 0) { raw_format = f; } CellFormat(ushort f = 0) { raw_format = f; }
//! \brief
//! \~english Constructs CellFormat from color and flags
//! \~russian Создает CellFormat из цвета и флагов
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) { CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_char = col_char; color_char = col_char;
color_back = col_back; color_back = col_back;
@@ -105,19 +130,49 @@ union PIP_CONSOLE_EXPORT CellFormat {
ushort color_back: 4; ushort color_back: 4;
ushort flags : 8; ushort flags : 8;
}; };
//! \brief
//! \~english Equality operator
//! \~russian Оператор равенства
bool operator==(const CellFormat & c) const { return raw_format == c.raw_format; } bool operator==(const CellFormat & c) const { return raw_format == c.raw_format; }
//! \brief
//! \~english Inequality operator
//! \~russian Оператор неравенства
bool operator!=(const CellFormat & c) const { return raw_format != c.raw_format; } bool operator!=(const CellFormat & c) const { return raw_format != c.raw_format; }
}; };
//! \brief Screen cell
//! \~english Single character cell with formatting
//! \~russian Одна символьная ячейка с форматированием
struct PIP_CONSOLE_EXPORT Cell { struct PIP_CONSOLE_EXPORT Cell {
//! \brief
//! \~english Constructs Cell
//! \~russian Создает Cell
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) { Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {
symbol = c; symbol = c;
format = f; format = f;
} }
//! \brief Cell format
CellFormat format; CellFormat format;
//! \brief Cell character
PIChar symbol; PIChar symbol;
//! \brief
//! \~english Equality operator
//! \~russian Оператор равенства
bool operator==(const Cell & c) const { return format == c.format && symbol == c.symbol; } bool operator==(const Cell & c) const { return format == c.format && symbol == c.symbol; }
//! \brief
//! \~english Inequality operator
//! \~russian Оператор неравенства
bool operator!=(const Cell & c) const { return format != c.format || symbol != c.symbol; } bool operator!=(const Cell & c) const { return format != c.format || symbol != c.symbol; }
//! \brief
//! \~english Assignment operator
//! \~russian Оператор присваивания
Cell & operator=(const Cell & c) { Cell & operator=(const Cell & c) {
symbol = c.symbol; symbol = c.symbol;
if (c.format.color_back == Transparent) { if (c.format.color_back == Transparent) {
@@ -129,18 +184,52 @@ struct PIP_CONSOLE_EXPORT Cell {
} }
}; };
//! \brief Tile event data
//! \~english Event data passed to tiles
//! \~russian Данные события, передаваемые тайлам
struct PIP_CONSOLE_EXPORT TileEvent { struct PIP_CONSOLE_EXPORT TileEvent {
//! \brief
//! \~english Constructs TileEvent
//! \~russian Создает TileEvent
//! \param t Event type / Тип события
//! \param d Event data / Данные события
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {} TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
//! \brief Event type
int type; int type;
//! \brief Event data
PIVariant data; PIVariant data;
}; };
//! \brief Base screen interface
//! \~english Base interface for screen tiles
//! \~russian Базовый интерфейс для экранных тайлов
class PIP_CONSOLE_EXPORT PIScreenBase { class PIP_CONSOLE_EXPORT PIScreenBase {
public: public:
//! \brief
//! \~english Constructs PIScreenBase
//! \~russian Создает PIScreenBase
PIScreenBase() {} PIScreenBase() {}
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIScreenBase() {} virtual ~PIScreenBase() {}
//! \brief
//! \~english Handles internal tile event
//! \~russian Обрабатывает внутреннее событие тайла
virtual void tileEventInternal(PIScreenTile *, TileEvent) {} virtual void tileEventInternal(PIScreenTile *, TileEvent) {}
//! \brief
//! \~english Handles tile removal
//! \~russian Обрабатывает удаление тайла
virtual void tileRemovedInternal(PIScreenTile *) {} virtual void tileRemovedInternal(PIScreenTile *) {}
//! \brief
//! \~english Handles tile focus change
//! \~russian Обрабатывает изменение фокуса тайла
virtual void tileSetFocusInternal(PIScreenTile *) {} virtual void tileSetFocusInternal(PIScreenTile *) {}
}; };

View File

@@ -1,9 +1,11 @@
/*! \file piterminal.h //! \file piterminal.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Virtual terminal //! \~english Virtual terminal
* \~russian Виртуальный терминал //! \~russian Виртуальный терминал
*/ //! \details
//! \~english Provides terminal emulation for reading console input and output.
//! \~russian Обеспечивает эмуляцию терминала для чтения ввода и вывода консоли.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal
@@ -31,26 +33,73 @@
#include "piscreentypes.h" #include "piscreentypes.h"
//! \brief
//! \~english Virtual terminal
//! \~russian Виртуальный терминал
class PIP_CONSOLE_EXPORT PITerminal: public PIThread { class PIP_CONSOLE_EXPORT PITerminal: public PIThread {
PIOBJECT_SUBCLASS(PITerminal, PIThread); PIOBJECT_SUBCLASS(PITerminal, PIThread);
public: public:
//! Constructs %PITerminal //! \brief
//! \~english Constructs PITerminal
//! \~russian Создает PITerminal
PITerminal(); PITerminal();
//! \brief
//! \~english Destructor
//! \~russian Деструктор
~PITerminal(); ~PITerminal();
//! \brief
//! \~english Returns number of columns
//! \~russian Возвращает количество колонок
int columns() const { return size_x; } int columns() const { return size_x; }
//! \brief
//! \~english Returns number of rows
//! \~russian Возвращает количество строк
int rows() const { return size_y; } int rows() const { return size_y; }
//! \brief
//! \~english Resizes terminal
//! \~russian Изменяет размер терминала
//! \param cols Number of columns / Количество колонок
//! \param rows Number of rows / Количество строк
bool resize(int cols, int rows); bool resize(int cols, int rows);
//! \brief
//! \~english Writes data to terminal
//! \~russian Записывает данные в терминал
void write(const PIByteArray & d); void write(const PIByteArray & d);
//! \brief
//! \~english Writes special key to terminal
//! \~russian Записывает специальную клавишу в терминал
void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m); void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m);
//! \brief
//! \~english Writes key event to terminal
//! \~russian Записывает событие клавиши в терминал
void write(PIKbdListener::KeyEvent ke); void write(PIKbdListener::KeyEvent ke);
//! \brief
//! \~english Returns terminal content
//! \~russian Возвращает содержимое терминала
PIVector<PIVector<PIScreenTypes::Cell>> content(); PIVector<PIVector<PIScreenTypes::Cell>> content();
//! \brief
//! \~english Checks if key is special
//! \~russian Проверяет, является ли клавиша специальной
static bool isSpecialKey(int k); static bool isSpecialKey(int k);
//! \brief
//! \~english Initializes terminal
//! \~russian Инициализирует терминал
bool initialize(); bool initialize();
//! \brief
//! \~english Destroys terminal
//! \~russian Уничтожает терминал
void destroy(); void destroy();
private: private:

View File

@@ -49,14 +49,28 @@
#include <type_traits> #include <type_traits>
//! \~english Reverse wrapper template class for iterating containers in reverse order.
//! \~russian Класс-обертка для обратного обхода контейнера через итераторы.
template<typename C> template<typename C>
class _PIReverseWrapper { class _PIReverseWrapper {
public: public:
//! \~english Constructor from non-const container reference.
//! \~russian Конструктор из неконстантной ссылки на контейнер.
_PIReverseWrapper(C & c): c_(c) {} _PIReverseWrapper(C & c): c_(c) {}
//! \~english Constructor from const container reference.
//! \~russian Конструктор из константной ссылки на контейнер.
_PIReverseWrapper(const C & c): c_(const_cast<C &>(c)) {} _PIReverseWrapper(const C & c): c_(const_cast<C &>(c)) {}
//! \~english Returns reverse iterator to the first element.
//! \~russian Возвращает обратный итератор на первый элемент.
typename C::reverse_iterator begin() { return c_.rbegin(); } typename C::reverse_iterator begin() { return c_.rbegin(); }
//! \~english Returns reverse iterator past the last element.
//! \~russian Возвращает обратный итератор за последний элемент.
typename C::reverse_iterator end() { return c_.rend(); } typename C::reverse_iterator end() { return c_.rend(); }
//! \~english Returns const reverse iterator to the first element.
//! \~russian Возвращает константный обратный итератор на первый элемент.
typename C::const_reverse_iterator begin() const { return c_.rbegin(); } typename C::const_reverse_iterator begin() const { return c_.rbegin(); }
//! \~english Returns const reverse iterator past the last element.
//! \~russian Возвращает константный обратный итератор за последний элемент.
typename C::const_reverse_iterator end() const { return c_.rend(); } typename C::const_reverse_iterator end() const { return c_.rend(); }
private: private:
@@ -64,32 +78,47 @@ private:
}; };
//! \~english Base class for container constants calculation.
//! \~russian Базовый класс для вычисления констант контейнера.
class PIP_EXPORT _PIContainerConstantsBase { class PIP_EXPORT _PIContainerConstantsBase {
public: public:
//! \~english Calculate minimum elements count for power of two growth.
//! \~russian Вычисляет минимальное количество элементов для роста кратного двум.
static size_t calcMinCountPoT(size_t szof); static size_t calcMinCountPoT(size_t szof);
//! \~english Calculate maximum elements count for power of two growth.
//! \~russian Вычисляет максимальное количество элементов для роста кратного двум.
static size_t calcMaxCountForPoT(size_t szof); static size_t calcMaxCountForPoT(size_t szof);
//! \~english Calculate step size after power of two growth.
//! \~russian Вычисляет размер шага после роста кратного двум.
static size_t calcStepAfterPoT(size_t szof); static size_t calcStepAfterPoT(size_t szof);
}; };
//! \~english Template class for container constants based on element type size.
//! \~russian Шаблонный класс для констант контейнера на основе размера типа элемента.
template<typename T> template<typename T>
class _PIContainerConstants { class _PIContainerConstants {
public: public:
// minimum elements for container //! \~english Get minimum elements count for power of two growth.
//! \~russian Возвращает минимальное количество элементов для роста кратного двум.
static size_t minCountPoT() { static size_t minCountPoT() {
static const size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); static const size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T));
return ret; return ret;
} }
// maximum elements for 2^n growth //! \~english Get maximum elements count for power of two growth.
//! \~russian Возвращает максимальное количество элементов для роста кратного двум.
static size_t maxCountForPoT() { static size_t maxCountForPoT() {
static const size_t ret = _PIContainerConstantsBase::calcMaxCountForPoT(sizeof(T)); static const size_t ret = _PIContainerConstantsBase::calcMaxCountForPoT(sizeof(T));
return ret; return ret;
} }
// add elements after 2^n growth //! \~english Get step size after power of two growth.
//! \~russian Возвращает размер шага после роста кратного двум.
static size_t stepAfterPoT() { static size_t stepAfterPoT() {
static const size_t ret = _PIContainerConstantsBase::calcStepAfterPoT(sizeof(T)); static const size_t ret = _PIContainerConstantsBase::calcStepAfterPoT(sizeof(T));
return ret; return ret;
} }
//! \~english Calculate new container size based on old and requested size.
//! \~russian Вычисляет новый размер контейнера на основе старого и запрошенного размера.
static size_t calcNewSize(size_t old_size, size_t new_size) { static size_t calcNewSize(size_t old_size, size_t new_size) {
if (new_size == 0) return 0; if (new_size == 0) return 0;
if (new_size < maxCountForPoT()) { if (new_size < maxCountForPoT()) {

View File

@@ -1,8 +1,17 @@
/*! \file piset.h //! \addtogroup Containers
* \brief Set container //! \{
* //! \file piset.h
* This file declare PISet //! \brief
*/ //! \~english Declares \a PISet
//! \~russian Объявление \a PISet
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Set container Set container
@@ -27,13 +36,33 @@
#include "pimap.h" #include "pimap.h"
/*! \brief Set of any type //! \addtogroup Containers
* \details This class used to store collection of unique elements //! \{
* of any type. You can only add values to set with \a operator<< or //! \class PISet
* with function \a insert(). You can discover if value already in //! \brief
* set with \a operator[] or with function \a find(). These function //! \~english A set is a collection of unique elements.
* has logarithmic complexity. //! \~russian Множество - это коллекция уникальных элементов.
*/ //! \~\}
//! \details
//! \~english
//! This class is used to store a collection of unique elements of any type.
//! You can add values to the set using \a operator<< or the \a insert() function.
//! You can check if a value already exists in the set using \a operator[] or the \a contains() function.
//! These operations have logarithmic complexity.
//! To iterate over all elements, use STL-style iterators \a begin() and \a end().
//!
//! The set is implemented as a wrapper around \a PIMap, where keys are the elements
//! and values are dummy byte values (used only for storage).
//! \~russian
//! Этот класс используется для хранения коллекции уникальных элементов любого типа.
//! Вы можете добавлять значения в множество с помощью \a operator<< или функции \a insert().
//! Вы можете проверить, существует ли значение в множестве, используя \a operator[] или функцию \a contains().
//! Эти операции имеют логарифмическую сложность.
//! Для перебора всех элементов используйте итераторы в стиле STL \a begin() и \a end().
//!
//! Множество реализовано как обёртка над \a PIMap, где ключами являются элементы,
//! а значениями являются фиктивные байтовые значения (используются только для хранения).
//! \~\sa \a PIMap, \a PIVector
template<typename T> template<typename T>
class PISet: public PIMap<T, uchar> { class PISet: public PIMap<T, uchar> {
typedef PIMap<T, uchar> _CSet; typedef PIMap<T, uchar> _CSet;
@@ -43,26 +72,31 @@ class PISet: public PIMap<T, uchar> {
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PISet<T1> & v); friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PISet<T1> & v);
public: public:
//! Contructs an empty set //! \~english Constructs an empty set.
//! \~russian Создает пустое множество.
PISet() {} PISet() {}
//! Contructs set with one element "value" //! \~english Constructs a set with one element `value`.
//! \~russian Создает множество с одним элементом `value`.
explicit PISet(const T & value) { _CSet::insert(value, 0); } explicit PISet(const T & value) { _CSet::insert(value, 0); }
//! Contructs set with elements "v0" and "v1" //! \~english Constructs a set with two elements `v0` and `v1`.
//! \~russian Создает множество с двумя элементами `v0` и `v1`.
PISet(const T & v0, const T & v1) { PISet(const T & v0, const T & v1) {
_CSet::insert(v0, 0); _CSet::insert(v0, 0);
_CSet::insert(v1, 0); _CSet::insert(v1, 0);
} }
//! Contructs set with elements "v0", "v1" and "v2" //! \~english Constructs a set with three elements `v0`, `v1` and `v2`.
//! \~russian Создает множество с тремя элементами `v0`, `v1` и `v2`.
PISet(const T & v0, const T & v1, const T & v2) { PISet(const T & v0, const T & v1, const T & v2) {
_CSet::insert(v0, 0); _CSet::insert(v0, 0);
_CSet::insert(v1, 0); _CSet::insert(v1, 0);
_CSet::insert(v2, 0); _CSet::insert(v2, 0);
} }
//! Contructs set with elements "v0", "v1", "v2" and "v3" //! \~english Constructs a set with four elements `v0`, `v1`, `v2` and `v3`.
//! \~russian Создает множество с четырьмя элементами `v0`, `v1`, `v2` и `v3`.
PISet(const T & v0, const T & v1, const T & v2, const T & v3) { PISet(const T & v0, const T & v1, const T & v2, const T & v3) {
_CSet::insert(v0, 0); _CSet::insert(v0, 0);
_CSet::insert(v1, 0); _CSet::insert(v1, 0);
@@ -154,7 +188,8 @@ public:
inline const_iterator begin() const { return const_iterator(this, 0); } inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator end() const { return const_iterator(this, _CSet::size()); } inline const_iterator end() const { return const_iterator(this, _CSet::size()); }
//! Contructs set from vector of elements //! \~english Constructs a set from a vector of elements.
//! \~russian Создает множество из вектора элементов.
explicit PISet(const PIVector<T> & values) { explicit PISet(const PIVector<T> & values) {
if (values.isEmpty()) return; if (values.isEmpty()) return;
for (int i = 0; i < values.size_s(); ++i) { for (int i = 0; i < values.size_s(); ++i) {
@@ -162,7 +197,8 @@ public:
} }
} }
//! Contructs set from deque of elements //! \~english Constructs a set from a deque of elements.
//! \~russian Создает множество из deque элементов.
explicit PISet(const PIDeque<T> & values) { explicit PISet(const PIDeque<T> & values) {
if (values.isEmpty()) return; if (values.isEmpty()) return;
for (int i = 0; i < values.size_s(); ++i) { for (int i = 0; i < values.size_s(); ++i) {
@@ -172,6 +208,8 @@ public:
typedef T key_type; typedef T key_type;
//! \~english Inserts element `t` into the set.
//! \~russian Вставляет элемент `t` в множество.
PISet<T> & operator<<(const T & t) { PISet<T> & operator<<(const T & t) {
_CSet::insert(t, 0); _CSet::insert(t, 0);
return *this; return *this;
@@ -185,52 +223,62 @@ public:
return *this; return *this;
} }
//! \~english Tests if element `key` exists in the set. //! \~english Tests if element `t` exists in the set.
//! \~russian Проверяет наличие элемента `key` в массиве. //! \~russian Проверяет наличие элемента `t` в множестве.
inline bool contains(const T & t) const { return _CSet::contains(t); } inline bool contains(const T & t) const { return _CSet::contains(t); }
//! Returns if element "t" exists in this set //! \~english Tests if element `t` exists in the set.
//! \~russian Проверяет наличие элемента `t` в множестве.
bool operator[](const T & t) const { return _CSet::contains(t); } bool operator[](const T & t) const { return _CSet::contains(t); }
//! Returns if element "t" exists in this set //! \~english Removes element `t` from the set.
//! \~russian Удаляет элемент `t` из множества.
PISet<T> & remove(const T & t) { PISet<T> & remove(const T & t) {
_CSet::remove(t); _CSet::remove(t);
return *this; return *this;
} }
//! Unite set with "v" //! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet<T> & unite(const PISet<T> & v) { PISet<T> & unite(const PISet<T> & v) {
for (const auto & i: v) for (const auto & i: v)
_CSet::insert(i, 0); _CSet::insert(i, 0);
return *this; return *this;
} }
//! Subtract set with "v" //! \~english Returns the difference of this set and set `v`.
//! \~russian Возвращает разность этого множества и множества `v`.
PISet<T> & subtract(const PISet<T> & v) { PISet<T> & subtract(const PISet<T> & v) {
for (const auto & i: v) for (const auto & i: v)
_CSet::remove(i); _CSet::remove(i);
return *this; return *this;
} }
//! Intersect set with "v" //! \~english Returns the intersection of this set with set `v`.
//! \~russian Возвращает пересечение этого множества с множеством `v`.
PISet<T> & intersect(const PISet<T> & v) { PISet<T> & intersect(const PISet<T> & v) {
_CSet::removeWhere([&v](const T & k, uchar) { return !v.contains(k); }); _CSet::removeWhere([&v](const T & k, uchar) { return !v.contains(k); });
return *this; return *this;
} }
//! Unite set with "v" //! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet<T> & operator+=(const PISet<T> & v) { return unite(v); } PISet<T> & operator+=(const PISet<T> & v) { return unite(v); }
//! Unite set with "v" //! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet<T> & operator|=(const PISet<T> & v) { return unite(v); } PISet<T> & operator|=(const PISet<T> & v) { return unite(v); }
//! Subtract set with "v" //! \~english Returns the difference of this set and set `v`.
//! \~russian Возвращает разность этого множества и множества `v`.
PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); } PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); }
//! Intersect set with "v" //! \~english Returns the intersection of this set with set `v`.
//! \~russian Возвращает пересечение этого множества с множеством `v`.
PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); } PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); }
//! Returns content of set as PIVector //! \~english Converts the set to a vector.
//! \~russian Преобразует множество в вектор.
PIVector<T> toVector() const { PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
for (const auto & i: *this) for (const auto & i: *this)
@@ -238,7 +286,8 @@ public:
return ret; return ret;
} }
//! Returns content of set as PIDeque //! \~english Converts the set to a deque.
//! \~russian Преобразует множество в deque.
PIDeque<T> toDeque() const { PIDeque<T> toDeque() const {
PIDeque<T> ret; PIDeque<T> ret;
for (const auto & i: *this) for (const auto & i: *this)
@@ -248,7 +297,8 @@ public:
}; };
//! \relatesalso PISet \brief Returns unite of two sets //! \~english Returns the union of two sets.
//! \~russian Возвращает объединение двух множеств.
template<typename T> template<typename T>
PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -256,7 +306,8 @@ PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet \brief Returns subtraction of two sets //! \~english Returns the difference of two sets.
//! \~russian Возвращает разность двух множеств.
template<typename T> template<typename T>
PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -264,7 +315,8 @@ PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet \brief Returns unite of two sets //! \~english Returns the union of two sets.
//! \~russian Возвращает объединение двух множеств.
template<typename T> template<typename T>
PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -272,7 +324,8 @@ PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet \brief Returns intersetion of two sets //! \~english Returns the intersection of two sets.
//! \~russian Возвращает пересечение двух множеств.
template<typename T> template<typename T>
PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -281,6 +334,9 @@ PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
} }
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename Type> template<typename Type>
inline PICout operator<<(PICout s, const PISet<Type> & v) { inline PICout operator<<(PICout s, const PISet<Type> & v) {
s.space(); s.space();
@@ -297,4 +353,6 @@ inline PICout operator<<(PICout s, const PISet<Type> & v) {
return s; return s;
} }
//! \}
#endif // PISET_H #endif // PISET_H

View File

@@ -835,8 +835,8 @@ public:
//! piCout << v.contains({1,4}); // true //! piCout << v.contains({1,4}); // true
//! piCout << v.contains({1,5}); // false //! piCout << v.contains({1,5}); // false
//! \endcode //! \endcode
//! \~\sa \a every(), \a any(), \a entries(), \a forEach() //! \~\sa \a every(), \a any(), \a entries(), \a forEach(), \a contains()
inline bool contains(const PIVector<T> & v, ssize_t start = 0) const { inline bool containsAll(const PIVector<T> & v, ssize_t start = 0) const {
if (start < 0) { if (start < 0) {
start = piv_size + start; start = piv_size + start;
if (start < 0) start = 0; if (start < 0) start = 0;
@@ -854,6 +854,24 @@ public:
return true; return true;
} }
//! \~english Tests if any element of `v` exists in the array.
//! \~russian Проверяет наличие хотя бы одного из элементов `v` в массиве.
//! \~\sa \a containsAll(), \a contains()
inline bool containsAny(const PIVector<T> & v, ssize_t start = 0) const {
if (start < 0) {
start = piv_size + start;
if (start < 0) start = 0;
}
for (const T & e: v) {
for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) {
return true;
}
}
}
return false;
}
//! \~english Count elements equal `e` in the array. //! \~english Count elements equal `e` in the array.
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. //! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
//! \~\details //! \~\details
@@ -1303,14 +1321,16 @@ public:
//! piCout << v; // {1, 3, 7, 5} //! piCout << v; // {1, 3, 7, 5}
//! \endcode //! \endcode
//! \~\sa \a append(), \a prepend(), \a remove() //! \~\sa \a append(), \a prepend(), \a remove()
inline PIVector<T> & insert(size_t index, const T & e = T()) { inline PIVector<T> & insert(size_t index, const T & e = T(), size_t count = 1) {
alloc(piv_size + 1); alloc(piv_size + count);
if (index < piv_size - 1) { if (index < piv_size - count) {
const size_t os = piv_size - index - 1; const size_t os = piv_size - index - count;
memmove(reinterpret_cast<void *>(piv_data + index + 1), reinterpret_cast<const void *>(piv_data + index), os * sizeof(T)); memmove(reinterpret_cast<void *>(piv_data + index + count), reinterpret_cast<const void *>(piv_data + index), os * sizeof(T));
}
PIINTROSPECTION_CONTAINER_USED(T, count)
for (size_t i = 0; i < count; ++i) {
elementNew(piv_data + index + i, e);
} }
PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(piv_data + index, e);
return *this; return *this;
} }
@@ -1349,8 +1369,8 @@ public:
alloc(piv_size + v.piv_size); alloc(piv_size + v.piv_size);
if (os > 0) { if (os > 0) {
memmove(reinterpret_cast<void *>(piv_data + index + v.piv_size), memmove(reinterpret_cast<void *>(piv_data + index + v.piv_size),
reinterpret_cast<const void *>(piv_data + index), reinterpret_cast<const void *>(piv_data + index),
os * sizeof(T)); os * sizeof(T));
} }
newT(piv_data + index, v.piv_data, v.piv_size); newT(piv_data + index, v.piv_data, v.piv_size);
return *this; return *this;
@@ -1372,8 +1392,8 @@ public:
alloc(piv_size + init_list.size()); alloc(piv_size + init_list.size());
if (os > 0) { if (os > 0) {
memmove(reinterpret_cast<void *>(piv_data + index + init_list.size()), memmove(reinterpret_cast<void *>(piv_data + index + init_list.size()),
reinterpret_cast<const void *>(piv_data + index), reinterpret_cast<const void *>(piv_data + index),
os * sizeof(T)); os * sizeof(T));
} }
newT(piv_data + index, init_list.begin(), init_list.size()); newT(piv_data + index, init_list.begin(), init_list.size());
return *this; return *this;

View File

@@ -1,8 +1,15 @@
/*! \file pivector2d.h //! \addtogroup Containers
* \brief 2D wrapper around PIVector //! \{
* //! \file pivector2d.h
* This file declares PIVector //! \brief
*/ //! \~english Declares \a PIVector2D
//! \~russian Объявление \a PIVector2D
//! \~\authors
//! \~english
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
2D wrapper around PIVector 2D wrapper around PIVector
@@ -27,29 +34,111 @@
#include "pivector.h" #include "pivector.h"
/*! \brief 2D array, //! \addtogroup Containers
* \details This class used to store 2D array of any type elements as plain vector. //! \{
* You can read/write any element via operators [][], first dimension - row, second - column. //! \class PIVector2D
* The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc. //! \brief
* You can't add values to array, but you can modify any elements or create another PIVector2D. //! \~english 2D array container.
* PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> > //! \~russian Двумерный контейнер-массив.
*/ //! \details
//! \~english
//! This class is used to store a 2D array of elements of any type as a single continuous block of memory (a plain PIVector).
//! Elements can be accessed using the `[][]` operators, where the first index is the row and the second is the column.
//! Rows can be manipulated as \a PIVector objects, allowing modification of individual elements or assignment of entire rows.
//! You cannot directly add or remove elements to change the dimensions of the array after construction
//! (use \a resize(), \a addRow(), \a removeRow(), \a removeColumn() instead), but you can modify the values of existing elements.
//! \~russian
//! Этот класс используется для хранения двумерного массива элементов любого типа в виде единого непрерывного блока памяти (обычного
//! \a PIVector). Доступ к элементам осуществляется с помощью операторов `[][]`, где первый индекс — это строка, а второй — столбец. Со
//! строками можно работать как с объектами \a PIVector, что позволяет изменять отдельные элементы или присваивать целые строки. Нельзя
//! напрямую добавлять или удалять элементы, чтобы изменить размеры массива после создания (используйте \a resize(), \a addRow(), \a
//! removeRow(), \a removeColumn() для этого), но можно изменять значения существующих элементов.
template<typename T> template<typename T>
class PIVector2D { class PIVector2D {
public: public:
//! \brief
//! \~english Index structure for 2D array elements (row, column).
//! \~russian Структура индекса для элементов двумерного массива (строка, столбец).
struct Index {
//! \~english Row index in the 2D array.
//! \~russian Индекс строки в двумерном массиве.
ssize_t row = -1;
//! \~english Column index in the 2D array.
//! \~russian Индекс столбца в двумерном массиве.
ssize_t col = -1;
//! \~english Default constructor. Initializes row and col to -1 (invalid index).
//! \~russian Конструктор по умолчанию. Инициализирует row и col значениями -1 (некорректный индекс).
inline Index() = default;
//! \~english Constructs an Index with the given row and column values.
//! \~russian Создаёт Index с заданными значениями строки и столбца.
inline Index(ssize_t r, ssize_t c): row(r), col(c) {}
//! \~english Checks if the index is valid (both row and column are non-negative).
//! \~russian Проверяет, является ли индекс корректным (строка и столбец неотрицательны).
//! \~\sa isNotValid()
inline bool isValid() const { return row >= 0 && col >= 0; }
//! \~english Checks if the index is invalid (either row or column is negative).
//! \~russian Проверяет, является ли индекс некорректным (строка или столбец отрицательны).
//! \~\sa isValid()
inline bool isNotValid() const { return !isValid(); }
};
//! \~english Constructs an empty 2D array. No memory is allocated.
//! \~russian Создаёт пустой двумерный массив. Память не выделяется.
//! \details
//! \~english After this constructor, \a rows() and \a cols() return 0, and \a isEmpty() returns true.
//! \~russian После этого конструктора \a rows() и \a cols() возвращают 0, а \a isEmpty() возвращает true.
//! \~\sa PIVector::PIVector()
inline PIVector2D() { rows_ = cols_ = 0; } inline PIVector2D() { rows_ = cols_ = 0; }
//! \~english Constructs a 2D array with the given dimensions, filled with copies of `f`.
//! \~russian Создаёт двумерный массив заданного размера, заполненный копиями `f`.
//! \details
//! \~english The underlying storage is a single contiguous block of memory of size `rows * cols`.
//! All elements are initialized with the value `f`.
//! \~russian Внутреннее хранилище представляет собой единый непрерывный блок памяти размером `rows * cols`.
//! Все элементы инициализируются значением `f`.
//! \~\sa PIVector::PIVector(size_t, const T&)
inline PIVector2D(size_t rows, size_t cols, const T & f = T()) { inline PIVector2D(size_t rows, size_t cols, const T & f = T()) {
rows_ = rows; rows_ = rows;
cols_ = cols; cols_ = cols;
mat.resize(rows * cols, f); mat.resize(rows * cols, f);
} }
//! \~english Constructs a 2D array from an existing 1D vector, reshaping it.
//! \~russian Создаёт двумерный массив из существующего одномерного вектора, изменяя его форму.
//! \details
//! \~english The constructor copies the data from `v` into the internal flat vector.
//! If `v` is larger than `rows * cols`, the excess elements are ignored (the vector is truncated).
//! If `v` is smaller, other values filled whith default cunstructor T()
//! \~russian Конструктор копирует данные из `v` во внутренний плоский вектор.
//! Если `v` больше, чем `rows * cols`, лишние элементы игнорируются (вектор обрезается).
//! Если `v` меньше, остальные значения будут заполнены из конструктора по умолчанию T()
//! \~\sa PIVector::PIVector(const PIVector&), reshape()
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v): rows_(rows), cols_(cols), mat(v) { mat.resize(rows * cols); } inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v): rows_(rows), cols_(cols), mat(v) { mat.resize(rows * cols); }
//! \~english Move constructs a 2D array from an existing 1D vector, reshaping it.
//! \~russian Конструктор перемещения из существующего одномерного вектора, изменяя его форму.
//! \details
//! \~english The data is moved from `v` into the internal flat vector, avoiding a copy.
//! After construction, `v` is left in a valid but unspecified state.
//! \~russian Данные перемещаются из `v` во внутренний плоский вектор, что позволяет избежать копирования.
//! После завершения конструктора `v` остаётся в корректном, но неопределённом состоянии.
//! \~\sa PIVector::PIVector(PIVector&&)
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v): rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows * cols); } inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v): rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows * cols); }
//! \~english Constructs a 2D array from a vector of vectors (jagged array). Assumes all inner vectors have the same size.
//! \~russian Создаёт двумерный массив из вектора векторов (рваного массива). Предполагается, что все внутренние векторы имеют
//! одинаковый размер.
//! \details
//! \~english If the input is empty, the constructed array is also empty. Otherwise, the number of columns is taken from the size of the
//! first inner vector. All inner vectors are concatenated in the internal flat storage.
//! \~russian Если входной массив пуст, создаётся пустой двумерный массив. В противном случае количество столбцов берётся из размера
//! первого внутреннего вектора. Все внутренние векторы конкатенируются во внутреннем плоском хранилище. \sa PIVector::append()
inline PIVector2D(const PIVector<PIVector<T>> & v) { inline PIVector2D(const PIVector<PIVector<T>> & v) {
rows_ = v.size(); rows_ = v.size();
if (rows_) { if (rows_) {
@@ -63,219 +152,858 @@ public:
if (mat.isEmpty()) rows_ = cols_ = 0; if (mat.isEmpty()) rows_ = cols_ = 0;
} }
//! \~english Returns the number of rows in the 2D array.
//! \~russian Возвращает количество строк в двумерном массиве.
//! \return Number of rows.
//! \details
//! \~english The result is always non-negative. If the array is empty, returns 0.
//! \~russian Результат всегда неотрицательный. Если массив пуст, возвращает 0.
//! \~\sa cols(), size(), PIVector::size()
inline size_t rows() const { return rows_; } inline size_t rows() const { return rows_; }
//! \~english Returns the number of columns in the 2D array.
//! \~russian Возвращает количество столбцов в двумерном массиве.
//! \return Number of columns.
//! \details
//! \~english The result is always non-negative. If the array is empty, returns 0.
//! \~russian Результат всегда неотрицательный. Если массив пуст, возвращает 0.
//! \~\sa rows(), size(), PIVector::size()
inline size_t cols() const { return cols_; } inline size_t cols() const { return cols_; }
//! \~english Returns the total number of elements (`rows * cols`).
//! \~russian Возвращает общее количество элементов (`строки * столбцы`).
//! \return Total number of elements.
//! \details
//! \~english This is equivalent to the size of the underlying flat vector.
//! \~russian Это эквивалентно размеру внутреннего плоского вектора.
//! \~\sa rows(), cols(), PIVector::size()
inline size_t size() const { return mat.size(); } inline size_t size() const { return mat.size(); }
//! \~english Returns the total number of elements as a signed value.
//! \~russian Возвращает общее количество элементов в виде знакового числа.
//! \return Signed size.
//! \~\sa size(), PIVector::size_s()
inline ssize_t size_s() const { return mat.size_s(); } inline ssize_t size_s() const { return mat.size_s(); }
//! \~english Returns the total number of elements (same as \a size()).
//! \~russian Возвращает общее количество элементов (то же, что и \a size()).
//! \return Total number of elements.
//! \~\sa size(), PIVector::length()
inline size_t length() const { return mat.length(); } inline size_t length() const { return mat.length(); }
//! \~english Returns the number of elements that the underlying container has currently allocated space for.
//! \~russian Возвращает количество элементов, для которого сейчас выделена память во внутреннем контейнере.
//! \return Capacity of the flat vector.
//! \details
//! \~english This value may be larger than \a size(). It indicates how many elements can be added before a reallocation is needed.
//! \~russian Это значение может быть больше, чем \a size(). Оно показывает, сколько элементов можно добавить до того, как потребуется
//! перераспределение памяти. \sa reserve(), PIVector::capacity()
inline size_t capacity() const { return mat.capacity(); } inline size_t capacity() const { return mat.capacity(); }
//! \~english Checks if the array has no elements.
//! \~russian Проверяет, пуст ли массив.
//! \return \c true if the array is empty, \c false otherwise.
//! \details
//! \~english An empty array has both rows and columns equal to 0.
//! \~russian Пустой массив имеет и строки, и столбцы равные 0.
//! \~\sa isNotEmpty(), PIVector::isEmpty()
inline bool isEmpty() const { return mat.isEmpty(); } inline bool isEmpty() const { return mat.isEmpty(); }
//! \~english Checks if the array has at least one element.
//! \~russian Проверяет, не пуст ли массив.
//! \return \c true if the array is not empty, \c false otherwise.
//! \~\sa isEmpty(), PIVector::isNotEmpty()
inline bool isNotEmpty() const { return mat.isNotEmpty(); } inline bool isNotEmpty() const { return mat.isNotEmpty(); }
class Row { class RowConst;
friend class PIVector2D<T>; class ColConst;
class Row;
class Col;
private:
inline Row(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
st_ = p->cols_ * row;
sz_ = p->cols_;
}
PIVector<T> * p_;
size_t st_, sz_;
public:
inline size_t size() const { return sz_; }
inline T & operator[](size_t index) { return (*p_)[st_ + index]; }
inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; }
inline T * data(size_t index = 0) { return p_->data(st_ + index); }
inline const T * data(size_t index = 0) const { return p_->data(st_ + index); }
inline Row & operator=(const Row & other) {
if (p_ == other.p_ && st_ == other.st_) return *this;
const size_t sz = piMin<size_t>(sz_, other.sz_);
p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this;
}
inline Row & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(sz_, other.size());
p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this;
}
inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); }
};
class Col {
friend class PIVector2D<T>;
private:
inline Col(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
step_ = p->cols_;
row_ = row;
sz_ = p->rows_;
}
PIVector<T> * p_;
size_t step_, row_, sz_;
public:
inline size_t size() const { return sz_; }
inline T & operator[](size_t index) { return (*p_)[index * step_ + row_]; }
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; }
inline T * data(size_t index = 0) { return p_->data(index * step_ + row_); }
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); }
inline Col & operator=(const Col & other) {
if (p_ == other.p_ && row_ == other.row_) return *this;
const size_t sz = piMin<size_t>(sz_, other.sz_);
for (int i = 0; i < sz; ++i)
(*p_)[i * step_ + row_] = other[i];
return *this;
}
inline Row & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(sz_, other.size());
for (int i = 0; i < sz; ++i)
(*p_)[i * step_ + row_] = other[i];
return *this;
}
inline PIVector<T> toVector() const {
PIVector<T> ret;
ret.reserve(sz_);
for (size_t i = 0; i < sz_; i++)
ret << (*p_)[i * step_ + row_];
return ret;
}
};
//! \class RowConst
//! \brief
//! \~english Proxy class representing a single read-only row in a \a PIVector2D.
//! \~russian Прокси-класс, представляющий одну строку в \a PIVector2D только для чтения.
//! \details
//! \~english Returned by const \a operator[] or \a row(). Provides const access to row elements.
//! \~russian Возвращается константными версиями \a operator[] или \a row(). Предоставляет константный доступ к элементам строки.
//! \~\sa Row, ColConst
class RowConst { class RowConst {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: protected:
inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) { inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)), st_(p->cols_ * row), sz_(p->cols_) {}
st_ = p->cols_ * row;
sz_ = p->cols_;
}
const PIVector<T> * p_; const PIVector<T> * p_;
size_t st_, sz_; const size_t st_, sz_;
public: public:
//! \~english Copy constructor from modifiable Row to read-only RowConst.
//! \~russian Конструктор копирования из модифицируемого класса Row в константный RowConst.
//! \~\sa Row
inline RowConst(const PIVector2D<T>::Row & r): p_(r.p_), st_(r.st_), sz_(r.sz_) {}
//! \~english Size of the row (number of columns).
//! \~russian Размер строки (количество столбцов).
inline size_t size() const { return sz_; } inline size_t size() const { return sz_; }
//! \~english Const access to the element at the given column index within the row.
//! \~russian Константный доступ к элементу по заданному индексу столбца в строке.
inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; } inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; }
//! \~english Returns a const pointer to the row data starting at an optional offset.
//! \~russian Возвращает константный указатель на данные строки, начиная с опционального смещения.
inline const T * data(size_t index = 0) const { return p_->data(st_ + index); } inline const T * data(size_t index = 0) const { return p_->data(st_ + index); }
//! \~english Converts the row to a \a PIVector.
//! \~russian Преобразует строку в \a PIVector.
inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); } inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); }
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \details
//! \~english See \a PIVector::indexOf() for details on negative start handling.
//! \~russian Подробнее об обработке отрицательного `start` см. \a PIVector::indexOf().
//! \~\sa PIVector::indexOf()
inline ssize_t indexOf(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[st_ + i] == e) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \return Index if found, -1 otherwise.
//! \~\sa PIVector::lastIndexOf()
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if ((*p_)[st_ + i] == e) return i;
}
return -1;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \~\sa PIVector::indexWhere()
inline ssize_t indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[st_ + i])) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \~\sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if (test((*p_)[st_ + i])) return i;
}
return -1;
}
//! \~english Applies a function to each element of the row (read-only).
//! \~russian Применяет функцию к каждому элементу строки (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \~\sa forEach (modifiable)
inline void forEach(std::function<void(const T &)> func) const {
for (size_t i = 0; i < sz_; ++i) {
func((*p_)[st_ + i]);
}
}
//! \~english Checks if the row contains the element `e`.
//! \~russian Проверяет, содержит ли строка элемент `e`.
//! \~\sa PIVector::contains()
inline bool contains(const T & e, ssize_t start = 0) const { return indexOf(e, start) != -1; }
//! \~english Counts occurrences of `e` in the row.
//! \~russian Подсчитывает количество вхождений `e` в строке.
//! \~\sa PIVector::entries()
inline int entries(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[st_ + i] == e) ++count;
}
return count;
}
//! \~english Counts elements in the row that pass the `test`.
//! \~russian Подсчитывает элементы в строке, проходящие `test`.
//! \~\sa PIVector::entries(std::function)
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[st_ + i])) ++count;
}
return count;
}
//! \~english Tests if any element in the row passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в строке `test`.
//! \~\sa PIVector::any()
inline bool any(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (test((*p_)[st_ + i])) return true;
}
return false;
}
//! \~english Tests if all elements in the row pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в строке `test`.
//! \~\sa PIVector::every()
inline bool every(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (!test((*p_)[st_ + i])) return false;
}
return true;
}
}; };
//! \class ColConst
//! \brief
//! \~english Proxy class representing a single read-only column in a \a PIVector2D.
//! \~russian Прокси-класс, представляющий один столбец в \a PIVector2D только для чтения.
//! \details
//! \~english Returned by const \a col(). Provides const access to column elements.
//! \~russian Возвращается константной версией \a col(). Предоставляет константный доступ к элементам столбца.
//! \~\sa Col, RowConst
class ColConst { class ColConst {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: protected:
inline ColConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) { inline ColConst(const PIVector2D<T> * p, size_t col): p_(&(p->mat)), step_(p->cols_), col_(col), sz_(p->rows_) {}
step_ = p->cols_;
row_ = row;
sz_ = p->rows_;
}
const PIVector<T> * p_; const PIVector<T> * p_;
size_t step_, row_, sz_; const size_t step_, col_, sz_;
public: public:
inline size_t size() const { return p_->rows_; } //! \~english Copy constructor from modifiable Col to read-only ColConst.
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; } //! \~russian Конструктор копирования из модифицируемого класса Col в константный ColConst.
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); } //! \~\sa Col
inline ColConst(const PIVector2D<T>::Col & c): p_(c.p_), step_(c.step_), col_(c.col_), sz_(c.sz_) {}
//! \~english Size of the column (number of rows).
//! \~russian Размер столбца (количество строк).
inline size_t size() const { return sz_; }
//! \~english Const access to the element at the given row index within the column.
//! \~russian Константный доступ к элементу по заданному индексу строки в столбце.
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + col_]; }
//! \~english Returns a const pointer to the column data starting at an optional row offset.
//! \~russian Возвращает константный указатель на данные столбца, начиная с опционального смещения по строкам.
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + col_); }
//! \~english Converts the column to a \a PIVector.
//! \~russian Преобразует столбец в \a PIVector.
inline PIVector<T> toVector() const { inline PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
ret.reserve(sz_); ret.reserve(sz_);
for (int i = 0; i < size(); i++) for (size_t i = 0; i < size(); i++)
ret << (*p_)[i * step_ + row_]; ret << (*p_)[i * step_ + col_];
return ret; return ret;
} }
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \details
//! \~english See \a PIVector::indexOf() for details on negative start handling.
//! \~russian Подробнее об обработке отрицательного `start` см. \a PIVector::indexOf().
//! \~\sa PIVector::indexOf()
inline ssize_t indexOf(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[i * step_ + col_] == e) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \~\sa PIVector::lastIndexOf()
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if ((*p_)[i * step_ + col_] == e) return i;
}
return -1;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \~\sa PIVector::indexWhere()
inline ssize_t indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[i * step_ + col_])) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \~\sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if (test((*p_)[i * step_ + col_])) return i;
}
return -1;
}
//! \~english Applies a function to each element of the column (read-only).
//! \~russian Применяет функцию к каждому элементу столбца (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \~\sa forEach (modifiable)
inline void forEach(std::function<void(const T &)> func) const {
for (size_t i = 0; i < sz_; ++i) {
func((*p_)[i * step_ + col_]);
}
}
//! \~english Checks if the column contains the element `e`.
//! \~russian Проверяет, содержит ли столбец элемент `e`.
//! \~\sa PIVector::contains()
inline bool contains(const T & e, ssize_t start = 0) const { return indexOf(e, start) != -1; }
//! \~english Counts occurrences of `e` in the column.
//! \~russian Подсчитывает количество вхождений `e` в столбце.
//! \~\sa PIVector::entries()
inline int entries(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[i * step_ + col_] == e) ++count;
}
return count;
}
//! \~english Counts elements in the column that pass the `test`.
//! \~russian Подсчитывает элементы в столбце, проходящие `test`.
//! \~\sa PIVector::entries(std::function)
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[i * step_ + col_])) ++count;
}
return count;
}
//! \~english Tests if any element in the column passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в столбце `test`.
//! \~\sa PIVector::any()
inline bool any(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (test((*p_)[i * step_ + col_])) return true;
}
return false;
}
//! \~english Tests if all elements in the column pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в столбце `test`.
//! \~\sa PIVector::every()
inline bool every(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (!test((*p_)[i * step_ + col_])) return false;
}
return true;
}
}; };
//! \class Row
//! \brief
//! \~english Proxy class representing a single row in a \a PIVector2D for modification.
//! \~russian Прокси-класс, представляющий одну строку в \a PIVector2D для модификации.
//! \details
//! \~english Objects of this class are returned by non-const \a operator[] or \a row().
//! They provide array-like access to the elements of a specific row and allow operations such as assignment from another row or a \a
//! PIVector, searching, filling, and iteration.
//! \~russian Объекты этого класса возвращаются неконстантными операторами \a operator[] или методом \a row().
//! Они предоставляют доступ к элементам конкретной строки, подобный массиву, и позволяют выполнять такие операции, как присваивание из
//! другой строки или \a PIVector, поиск, заполнение и итерацию. \sa Col, RowConst
class Row: public RowConst {
friend class PIVector2D<T>;
private:
inline Row(PIVector2D<T> * p, size_t row): RowConst(p, row), p_(&(p->mat)) {}
PIVector<T> * p_;
public:
using RowConst::operator[];
using RowConst::data;
using RowConst::size;
//! \~english Accesses the element at the given column index within the row.
//! \~russian Доступ к элементу по заданному индексу столбца в строке.
//! \details
//! \~english No bounds checking is performed; use with caution.
//! \~russian Проверка границ не выполняется; используйте с осторожностью.
//! \~\sa PIVector::operator[]
inline T & operator[](size_t index) { return (*p_)[this->st_ + index]; }
//! \~english Returns a pointer to the row data starting at an optional offset.
//! \~russian Возвращает указатель на данные строки, начиная с опционального смещения.
//! \details
//! \~english The pointer can be used for direct memory operations. It remains valid as long as the underlying 2D array is not
//! reallocated.
//! \~russian Указатель можно использовать для прямых операций с памятью. Он остаётся действительным, пока не произойдёт
//! перераспределение памяти внутреннего двумерного массива. \sa PIVector::data()
inline T * data(size_t index = 0) { return p_->data(this->st_ + index); }
//! \~english Assigns the contents of another Row to this row.
//! \~russian Присваивает этой строке содержимое другой строки.
//! \details
//! \~english Only the minimum of the two row sizes is copied; if this row is shorter, excess elements in `other` are ignored.
//! \~russian Копируется только минимум из размеров двух строк; если эта строка короче, лишние элементы из `other` игнорируются.
//! \~\sa PIVector::operator=
inline Row & operator=(const Row & other) {
if (p_ == other.p_ && this->st_ == other.st_) return *this;
const size_t sz = piMin<size_t>(this->sz_, other.sz_);
p_->_copyRaw(p_->data(this->st_), other.data(), sz);
return *this;
}
//! \~english Assigns the contents of a \a PIVector to this row.
//! \~russian Присваивает этой строке содержимое \a PIVector.
//! \details
//! \~english Only the minimum of the row size and vector size is copied.
//! \~russian Копируется только минимум из размера строки и размера вектора.
//! \~\sa PIVector::operator=
inline Row & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(this->sz_, other.size());
p_->_copyRaw(p_->data(this->st_), other.data(), sz);
return *this;
}
//! \~english Applies a function to each element of the row (modifiable).
//! \~russian Применяет функцию к каждому элементу строки (с возможностью изменения).
//! \param func Function that takes a reference to T.
//! \details
//! \~english The function can modify the elements.
//! \~russian Функция может изменять элементы.
//! \~\sa PIVector::forEach()
inline void forEach(std::function<void(T &)> func) {
for (size_t i = 0; i < this->sz_; ++i) {
func((*p_)[this->st_ + i]);
}
}
//! \~english Fills the row with copies of `value`.
//! \~russian Заполняет строку копиями `value`.
//! \~\sa PIVector::fill()
inline void fill(const T & value) {
for (size_t i = 0; i < this->sz_; ++i) {
(*p_)[this->st_ + i] = value;
}
}
};
//! \class Col
//! \brief
//! \~english Proxy class representing a single column in a \a PIVector2D for modification.
//! \~russian Прокси-класс, представляющий один столбец в \a PIVector2D для модификации.
//! \details
//! \~english Objects of this class are returned by non-const \a col(). They provide column-wise access and operations similar to \a
//! Row.
//! \~russian Объекты этого класса возвращаются неконстантным методом \a col(). Они предоставляют доступ к столбцам и операции,
//! аналогичные \a Row. \sa Row, ColConst
class Col: public ColConst {
friend class PIVector2D<T>;
private:
inline Col(PIVector2D<T> * p, size_t col): ColConst(p, col), p_(&(p->mat)) {}
PIVector<T> * p_;
public:
using ColConst::operator[];
using ColConst::data;
using ColConst::size;
//! \~english Accesses the element at the given row index within the column.
//! \~russian Доступ к элементу по заданному индексу строки в столбце.
//! \return Reference to the element.
inline T & operator[](size_t index) { return (*p_)[index * this->step_ + this->col_]; }
//! \~english Returns a pointer to the column data starting at an optional row offset.
//! \~russian Возвращает указатель на данные столбца, начиная с опционального смещения по строкам.
//! \details
//! \~english Note that column elements are not stored contiguously in memory, so this pointer cannot be used to iterate over the
//! whole column.
//! \~russian Обратите внимание, что элементы столбца не хранятся в памяти непрерывно, поэтому этот указатель нельзя использовать
//! для итерации по всему столбцу.
inline T * data(size_t index = 0) { return p_->data(index * this->step_ + this->col_); }
//! \~english Assigns the contents of another Col to this column.
//! \~russian Присваивает этому столбцу содержимое другого столбца.
inline Col & operator=(const Col & other) {
if (p_ == other.p_ && this->col_ == other.col_) return *this;
const size_t sz = piMin<size_t>(this->sz_, other.sz_);
for (size_t i = 0; i < sz; ++i)
(*p_)[i * this->step_ + this->col_] = other[i];
return *this;
}
//! \~english Assigns the contents of a \a PIVector to this column.
//! \~russian Присваивает этому столбцу содержимое \a PIVector.
inline Col & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(this->sz_, other.size());
for (size_t i = 0; i < sz; ++i)
(*p_)[i * this->step_ + this->col_] = other[i];
return *this;
}
//! \~english Applies a function to each element of the column (modifiable).
//! \~russian Применяет функцию к каждому элементу столбца (с возможностью изменения).
//! \details
//! \~english The function can modify the elements.
//! \~russian Функция может изменять элементы.
//! \~\sa PIVector::forEach()
inline void forEach(std::function<void(T &)> func) {
for (size_t i = 0; i < this->sz_; ++i) {
func((*p_)[i * this->step_ + this->col_]);
}
}
//! \~english Fills the column with copies of `value`.
//! \~russian Заполняет столбец копиями `value`.
//! \~\sa PIVector::fill()
inline void fill(const T & value) {
for (size_t i = 0; i < this->sz_; ++i) {
(*p_)[i * this->step_ + this->col_] = value;
}
}
};
//! \~english Returns a reference to the element at the given row and column.
//! \~russian Возвращает ссылку на элемент по заданной строке и столбцу.
//! \details
//! \~english No bounds checking is performed.
//! \~russian Проверка границ не выполняется.
//! \~\sa at() (const version), PIVector::operator[]
inline T & element(size_t row, size_t col) { return mat[row * cols_ + col]; } inline T & element(size_t row, size_t col) { return mat[row * cols_ + col]; }
//! \~english Returns a const reference to the element at the given row and column.
//! \~russian Возвращает константную ссылку на элемент по заданной строке и столбцу.
inline const T & element(size_t row, size_t col) const { return mat[row * cols_ + col]; } inline const T & element(size_t row, size_t col) const { return mat[row * cols_ + col]; }
//! \~english Returns a const reference to the element at the given row and column
//! \~russian Возвращает константную ссылку на элемент по заданной строке и столбцу
//! \details
//! \~english No bounds checking is performed.
//! \~russian Проверка границ не выполняется.
inline const T & at(size_t row, size_t col) const { return mat[row * cols_ + col]; } inline const T & at(size_t row, size_t col) const { return mat[row * cols_ + col]; }
//! \~english Returns a reference to the element at the given Index.
//! \~russian Возвращает ссылку на элемент по заданному Index.
inline T & operator[](const Index & idx) { return element(idx.row, idx.col); }
//! \~english Returns a const reference to the element at the given Index.
//! \~russian Возвращает константную ссылку на элемент по заданному Index.
inline const T & operator[](const Index & idx) const { return element(idx.row, idx.col); }
//! \~english Returns a reference to the element at the given Index.
//! \~russian Возвращает ссылку на элемент по заданному Index.
inline T & element(const Index & idx) { return element(idx.row, idx.col); }
//! \~english Returns a const reference to the element at the given Index.
//! \~russian Возвращает константную ссылку на элемент по заданному Index.
inline const T & element(const Index & idx) const { return element(idx.row, idx.col); }
//! \~english Returns a const reference to the element at the given Index (bounds-checked only in debug).
//! \~russian Возвращает константную ссылку на элемент по заданному Index (проверка границ только в отладочном режиме).
inline const T & at(const Index & idx) const { return at(idx.row, idx.col); }
//! \~english Returns a proxy object for the row at the given index for modification.
//! \~russian Возвращает прокси-объект для строки по заданному индексу для модификации.
//! \~\sa row(), Col
inline Row operator[](size_t index) { return Row(this, index); } inline Row operator[](size_t index) { return Row(this, index); }
//! \~english Returns a proxy object for the row at the given index for read-only access.
//! \~russian Возвращает прокси-объект для строки по заданному индексу только для чтения.
inline RowConst operator[](size_t index) const { return RowConst(this, index); } inline RowConst operator[](size_t index) const { return RowConst(this, index); }
//! \~english Returns a pointer to the underlying flat data starting at an optional offset.
//! \~russian Возвращает указатель на внутренние плоские данные, начиная с опционального смещения.
//! \~\sa PIVector::data()
inline T * data(size_t index = 0) { return mat.data(index); } inline T * data(size_t index = 0) { return mat.data(index); }
//! \~english Returns a const pointer to the underlying flat data starting at an optional offset.
//! \~russian Возвращает константный указатель на внутренние плоские данные, начиная с опционального смещения.
inline const T * data(size_t index = 0) const { return mat.data(index); } inline const T * data(size_t index = 0) const { return mat.data(index); }
//! \~english Returns a proxy object for the row at the given index for modification.
//! \~russian Возвращает прокси-объект для строки по заданному индексу для модификации.
//! \~\sa operator[]
inline Row row(size_t index) { return Row(this, index); } inline Row row(size_t index) { return Row(this, index); }
//! \~english Returns a proxy object for the row at the given index for read-only access.
//! \~russian Возвращает прокси-объект для строки по заданному индексу только для чтения.
inline RowConst row(size_t index) const { return RowConst(this, index); } inline RowConst row(size_t index) const { return RowConst(this, index); }
//! \~english Returns a proxy object for the column at the given index for modification.
//! \~russian Возвращает прокси-объект для столбца по заданному индексу для модификации.
//! \~\sa col() const
inline Col col(size_t index) { return Col(this, index); } inline Col col(size_t index) { return Col(this, index); }
//! \~english Returns a proxy object for the column at the given index for read-only access.
//! \~russian Возвращает прокси-объект для столбца по заданному индексу только для чтения.
inline ColConst col(size_t index) const { return ColConst(this, index); } inline ColConst col(size_t index) const { return ColConst(this, index); }
inline PIVector2D<T> & setRow(size_t row, const Row & other) {
const size_t sz = piMin<size_t>(cols_, other.sz_); //! \~english Replaces a row with the contents of a read-only RowConst object.
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); //! \~russian Заменяет строку содержимым объекта RowConst только для чтения.
return *this;
}
inline PIVector2D<T> & setRow(size_t row, const RowConst & other) { inline PIVector2D<T> & setRow(size_t row, const RowConst & other) {
const size_t sz = piMin<size_t>(cols_, other.sz_); const size_t sz = piMin<size_t>(cols_, other.sz_);
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
return *this; return *this;
} }
//! \~english Replaces a row with the contents of a \a PIVector.
//! \~russian Заменяет строку содержимым \a PIVector.
inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) { inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) {
const size_t sz = piMin<size_t>(cols_, other.size()); const size_t sz = piMin<size_t>(cols_, other.size());
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
return *this; return *this;
} }
inline PIVector2D<T> & addRow(const Row & other) {
if (cols_ == 0) cols_ = other.sz_; //! \~english Appends a new row to the bottom of the array from another Row object.
const size_t sz = piMin<size_t>(cols_, other.sz_); //! \~russian Добавляет новую строку в конец массива из другого объекта Row.
const size_t ps = mat.size(); //! \details
mat.resize(mat.size() + cols_); //! \~english If the array was empty, its column count is set to the size of the source row.
mat._copyRaw(mat.data(ps), other.data(), sz); //! Otherwise, only `min(cols(), other.size())` elements are copied; the rest of the new row is default-initialized.
rows_++; //! \~russian Если массив был пуст, количество столбцов устанавливается равным размеру исходной строки.
return *this; //! В противном случае копируется только `min(cols(), other.size())` элементов; остальные элементы новой строки инициализируются по
} //! умолчанию.
//! \~\sa PIVector::push_back()
inline PIVector2D<T> & addRow(const RowConst & other) { inline PIVector2D<T> & addRow(const RowConst & other) {
if (cols_ == 0) cols_ = other.sz_; if (cols_ == 0) cols_ = other.sz_;
const size_t sz = piMin<size_t>(cols_, other.sz_); mat.append(other.toVector());
const size_t ps = mat.size();
mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz);
rows_++; rows_++;
mat.resize(rows_ * cols_);
return *this; return *this;
} }
//! \~english Appends a new row to the bottom of the array from a \a PIVector.
//! \~russian Добавляет новую строку в конец массива из \a PIVector.
inline PIVector2D<T> & addRow(const PIVector<T> & other) { inline PIVector2D<T> & addRow(const PIVector<T> & other) {
if (cols_ == 0) cols_ = other.size(); if (cols_ == 0) cols_ = other.size();
const size_t sz = piMin<size_t>(cols_, other.size()); mat.append(other);
const size_t ps = mat.size();
mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz);
rows_++; rows_++;
mat.resize(rows_ * cols_);
return *this; return *this;
} }
//! \~english Appends \a count new empty rows to the bottom of the array, filled with value \a f.
//! \~russian Добавляет \a count новых пустых строк в конец массива, заполненных значением \a f.
//! \details
//! \~english If the array was empty (no columns defined), the column count is set to 1.
//! The new rows are filled with the default value \a f.
//! \~russian Если массив был пуст (количество столбцов не определено), количество столбцов устанавливается равным 1.
//! Новые строки заполняются значением по умолчанию \a f.
//! \~\sa addRow(), appendColumns()
inline PIVector2D<T> & appendRows(size_t count, const T & f = T()) {
if (count == 0) return *this;
if (cols_ == 0) ++cols_;
mat.resize(mat.size() + count * cols_, f);
rows_ += count;
return *this;
}
//! \~english Appends \a count new empty columns to the end of each row of the array.
//! \~russian Добавляет \a count новых пустых столбцов в конец каждой строки массива.
//! \details
//! \~english If the array was empty (rows not defined), the array becomes a single row with \a count columns.
//! If the array already has rows, new elements are inserted at the end of each existing row.
//! \~russian Если массив был пуст (строки не определены), массив становится одной строкой с \a count столбцов.
//! Если массив уже содержит строки, новые элементы добавляются в конец каждой существующей строки.
//! \~\sa appendRows(), addColumn()
inline PIVector2D<T> & appendColumns(size_t count, const T & f = T()) {
if (count == 0) return *this;
if (rows_ == 0) {
mat.resize(count, f);
rows_ = 1;
cols_ = count;
return *this;
}
const size_t newCols = cols_ + count;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
mat.insert(r * cols_, f, count);
}
cols_ = newCols;
return *this;
}
//! \~english Deletes `count` rows starting from the specified row index.
//! \~russian Удаляет `count` строк, начиная с указанного индекса строки.
//! \details
//! \~english Removes the specified rows from the array and updates the row count. If all elements are deleted (array becomes empty),
//! both rows and columns are set to 0.
//! \~russian Удаляет указанные строки из массива и обновляет количество строк. Если все элементы удалены (массив становится пустым),
//! количество строк и столбцов устанавливается в 0.
//! \~\sa deleteColumns()
inline PIVector2D<T> & deleteRows(size_t row_start, size_t count) {
if (row_start >= rows_ || count == 0) return *this;
mat.remove(row_start * cols_, cols_ * count);
if (isEmpty()) {
cols_ = 0;
rows_ = 0;
} else {
rows_ -= count;
}
return *this;
}
//! \~english Removes the specified columns from the array and updates the column count.
//! \~russian Удаляет указанные столбцы из массива и обновляет количество столбцов.
//! \details
//! \~english Removes \a count columns starting from \a col_start. If \a col_start is out of range or \a count is 0,
//! the function does nothing. If \a count extends beyond the last column, only available columns are deleted.
//! \~russian Удаляет \a count столбцов начиная с \a col_start. Если \a col_start выходит за границы или \a count равен 0,
//! функция ничего не делает. Если \a count выходит за последний столбец, удаляются только доступные столбцы.
//! \~\sa removeColumn(), deleteRows()
inline PIVector2D<T> & deleteColumns(size_t col_start, size_t count) {
if (col_start >= cols_ || rows_ == 0) return *this;
count = piMin(count, cols_ - col_start);
if (count == 0) return *this;
for (size_t r = 0; r < rows_; ++r) {
mat.remove(r * (cols_ - count) + col_start, count);
}
cols_ -= count;
mat.resize(rows_ * cols_);
return *this;
}
//! \~english Appends a new column to the right of the array from a \a ColConst.
//! \~russian Добавляет новую строку в конец массива из \a ColConst.
inline PIVector2D<T> & addColumn(const ColConst & other) {
if (other.size() == 0) return *this;
if (isEmpty()) {
mat.reserve(other.size());
for (size_t r = 0; r < other.size(); ++r) {
mat.append(other[r]);
}
rows_ = mat.size();
cols_ = 1;
return *this;
}
const size_t newCols = cols_ + 1;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
if (r - 1 < other.size()) {
mat.insert(r * cols_, other[r - 1]);
} else {
mat.insert(r * cols_);
}
}
cols_ = newCols;
return *this;
}
//! \~english Appends a new column to the right of the array from a \a PIVector.
//! \~russian Добавляет новую строку в конец массива из \a PIVector.
inline PIVector2D<T> & addColumn(const PIVector<T> & other) {
if (other.size() == 0) return *this;
if (isEmpty()) {
mat.append(other);
rows_ = mat.size();
cols_ = 1;
return *this;
}
const size_t newCols = cols_ + 1;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
if (r - 1 < other.size()) {
mat.insert(r * cols_, other[r - 1]);
} else {
mat.insert(r * cols_);
}
}
cols_ = newCols;
return *this;
}
//! \~english Resizes the 2D array to new dimensions.
//! \~russian Изменяет размер двумерного массива.
//! \details
//! \~english If the new dimensions are larger, new elements are appended and filled with copies of `f`.
//! If they are smaller, the array is truncated (excess elements are destroyed). The underlying memory may be reallocated.
//! \~russian Если новые размеры больше текущих, новые элементы добавляются в конец и заполняются копиями `f`.
//! Если новые размеры меньше, массив усекается (лишние элементы уничтожаются). Внутренняя память может быть перераспределена.
//! \code
//! PIVector2D<int> mat(2, 3, 0); // 2x3 matrix filled with 0
//! mat.resize(3, 4, 1); // becomes 3x4, new elements filled with 1
//! \endcode
//! \~\sa PIVector::resize()
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) { inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) {
mat.resize(rows * cols_, f); if (rows == rows_ && cols == cols_) return *this;
rows_ = rows; if (rows_ == 0 || cols_ == 0) {
const int cs = (cols - cols_); mat.resize(rows * cols, f);
if (cs < 0) { rows_ = rows;
for (size_t r = 0; r < rows; ++r) { cols_ = cols;
mat.remove(r * cols + cols, -cs); return *this;
}
} }
mat.resize(rows * cols, f); if (rows != rows_ && cols == cols_) {
if (!mat.isEmpty()) { mat.resize(rows * cols_, f);
if (cs > 0) { rows_ = rows;
for (size_t r = 0; r < rows_; ++r) { return *this;
for (int i = 0; i < cs; ++i) }
mat.insert(r * cols + cols_, mat.take_back()); if (cols > cols_) {
} appendColumns(cols - cols_, f);
} }
if (rows > rows_) {
appendRows(rows - rows_, f);
}
if (cols < cols_) {
deleteColumns(cols, cols_ - cols);
}
if (rows < rows_) {
deleteRows(rows, rows_ - rows);
} }
cols_ = cols;
return *this; return *this;
} }
//! \~english Equality operator.
//! \~russian Оператор равенства.
//! \~\sa PIVector::operator==
inline bool operator==(const PIVector2D<T> & t) const { inline bool operator==(const PIVector2D<T> & t) const {
if (cols_ != t.cols_ || rows_ != t.rows_) return false; if (cols_ != t.cols_ || rows_ != t.rows_) return false;
return mat == t.mat; return mat == t.mat;
} }
//! \~english Inequality operator.
//! \~russian Оператор неравенства.
inline bool operator!=(const PIVector2D<T> & t) const { return !(*this == t); } inline bool operator!=(const PIVector2D<T> & t) const { return !(*this == t); }
//! \~english Converts the 2D array to a vector of vectors (PIVector<PIVector<T>>).
//! \~russian Преобразует двумерный массив в вектор векторов (PIVector<PIVector<T>>).
//! \details
//! \~english Each row vector is a copy of the corresponding row.
//! \~russian Каждый вектор-строка является копией соответствующей строки.
//! \~\sa fromVectors(), PIVector::PIVector(const T*, size_t)
inline PIVector<PIVector<T>> toVectors() const { inline PIVector<PIVector<T>> toVectors() const {
PIVector<PIVector<T>> ret; PIVector<PIVector<T>> ret;
ret.reserve(rows_); ret.reserve(rows_);
@@ -284,18 +1012,31 @@ public:
return ret; return ret;
} }
//! \~english Returns a const reference to the underlying flat \a PIVector.
//! \~russian Возвращает константную ссылку на внутренний плоский \a PIVector.
inline const PIVector<T> & asPlainVector() const { return mat; }
//! \~english Returns a reference to the underlying flat \a PIVector.
//! \~russian Возвращает ссылку на внутренний плоский \a PIVector.
inline PIVector<T> & asPlainVector() { return mat; }
//! \~english Returns a copy of the underlying flat \a PIVector.
//! \~russian Возвращает копию внутреннего плоского \a PIVector.
inline PIVector<T> toPlainVector() const { return mat; } inline PIVector<T> toPlainVector() const { return mat; }
inline PIVector<T> & plainVector() { return mat; } //! \~english Swaps this 2D array with another.
//! \~russian Меняет местами этот двумерный массив с другим.
inline const PIVector<T> & plainVector() const { return mat; } //! \details
//! \~english Swaps the flat vectors and the dimension members. Very fast, no memory allocation.
//! \~russian Обменивает внутренние плоские векторы и члены, хранящие размеры. Очень быстро, без выделения памяти.
//! \~\sa PIVector::swap()
inline void swap(PIVector2D<T> & other) { inline void swap(PIVector2D<T> & other) {
mat.swap(other.mat); mat.swap(other.mat);
piSwap<size_t>(rows_, other.rows_); piSwap<size_t>(rows_, other.rows_);
piSwap<size_t>(cols_, other.cols_); piSwap<size_t>(cols_, other.cols_);
} }
//! \internal
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0> template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) { inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
rows_ = r; rows_ = r;
@@ -304,29 +1045,348 @@ public:
return *this; return *this;
} }
//! \~english Clears the array, removing all elements and setting dimensions to 0.
//! \~russian Очищает массив, удаляя все элементы и устанавливая размеры в 0.
//! \details
//! \~english The capacity of the underlying flat vector may remain unchanged.
//! \~russian Ёмкость внутреннего плоского вектора может остаться неизменной.
//! \~\sa PIVector::clear()
inline void clear() { inline void clear() {
rows_ = cols_ = 0; rows_ = cols_ = 0;
mat.clear(); mat.clear();
} }
template<typename ST>
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const { //! \~english Checks if the underlying flat vector contains the element `e`.
return PIVector2D<ST>(rows_, cols_, mat.map(f)); //! \~russian Проверяет, содержит ли внутренний плоский вектор элемент `e`.
//! \~\sa PIVector::contains()
inline bool contains(const T & e) const { return mat.contains(e); }
//! \~english Counts occurrences of `e` in the underlying flat vector.
//! \~russian Подсчитывает количество вхождений `e` во внутреннем плоском векторе.
//! \~\sa PIVector::entries()
inline int entries(const T & e) const { return mat.entries(e); }
//! \~english Counts elements in the flat vector that pass the `test`.
//! \~russian Подсчитывает элементы в плоском векторе, проходящие `test`.
//! \~\sa PIVector::entries(std::function)
inline int entries(std::function<bool(const T & e)> test) const { return mat.entries(test); }
//! \~english Returns the first index (row, col) of `e` in the 2D array.
//! \~russian Возвращает первый индекс (строка, столбец) элемента `e` в двумерном массиве.
//! \~\sa PIVector::indexOf()
inline Index indexOf(const T & e) const {
ssize_t flat = mat.indexOf(e);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
} }
inline void forEach(std::function<void(const T &)> f) const { mat.forEach(f); } //! \~english Returns the first index (row, col) in the 2D array that passes the `test`.
//! \~russian Возвращает первый индекс (строка, столбец) в двумерном массиве, проходящий `test`.
//! \~\sa PIVector::indexWhere()
inline Index indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
ssize_t flat = mat.indexWhere(test, start);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
}
inline PIVector2D<T> & forEach(std::function<void(T &)> f) { //! \~english Returns the last index (row, col) of `e` in the 2D array.
mat.forEach(f); //! \~russian Возвращает последний индекс (строка, столбец) элемента `e` в двумерном массиве.
//! \~\sa PIVector::lastIndexOf()
inline Index lastIndexOf(const T & e, ssize_t start = -1) const {
ssize_t flat = mat.lastIndexOf(e, start);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
}
//! \~english Returns the last index (row, col) in the 2D array that passes the `test`.
//! \~russian Возвращает последний индекс (строка, столбец) в двумерном массиве, проходящий `test`.
//! \~\sa PIVector::lastIndexWhere()
inline Index lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
ssize_t flat = mat.lastIndexWhere(test, start);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
}
//! \~english Tests if any element in the flat vector passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в плоском векторе `test`.
//! \~\sa PIVector::any()
inline bool any(std::function<bool(const T & e)> test) const { return mat.any(test); }
//! \~english Tests if all elements in the flat vector pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в плоском векторе `test`.
//! \~\sa PIVector::every()
inline bool every(std::function<bool(const T & e)> test) const { return mat.every(test); }
//! \~english Fills the entire 2D array with copies of `e`.
//! \~russian Заполняет весь двумерный массив копиями `e`.
//! \~\sa PIVector::fill()
inline PIVector2D<T> & fill(const T & e = T()) {
mat.fill(e);
return *this; return *this;
} }
//! \~english Fills the entire 2D array using a generator function `f` based on flat index.
//! \~russian Заполняет весь двумерный массив, используя функцию-генератор `f` на основе плоского индекса.
//! \~\sa PIVector::fill(std::function)
inline PIVector2D<T> & fill(std::function<T(size_t i)> f) {
mat.fill(f);
return *this;
}
//! \~english Same as \a fill().
//! \~russian То же, что и \a fill().
inline PIVector2D<T> & assign(const T & e = T()) { return fill(e); }
//! \~english Assigns new size and fills with value.
//! \~russian Задаёт новый размер и заполняет значением.
//! \~\sa PIVector::assign(size_t, const T&)
inline PIVector2D<T> & assign(size_t rows, size_t cols, const T & f = T()) {
mat.assign(rows * cols, f);
rows_ = rows;
cols_ = cols;
return *this;
}
//! \~english Returns a transposed 2D array (rows become columns and vice versa).
//! \~russian Возвращает транспонированный двумерный массив (строки становятся столбцами и наоборот).
//! \details
//! \~english The element at (r, c) in the original becomes at (c, r) in the result.
//! \~russian Элемент (r, c) исходного массива становится элементом (c, r) в результате.
//! \code
//! PIVector2D<int> mat(2, 3, ...);
//! auto t = mat.transposed(); // now 3x2
//! \endcode
inline PIVector2D<T> transposed() const {
if (isEmpty()) return PIVector2D<T>();
PIVector2D<T> result(cols_, rows_);
for (size_t r = 0; r < rows_; ++r) {
for (size_t c = 0; c < cols_; ++c) {
result.element(c, r) = element(r, c);
}
}
return result;
}
//! \~english Reverses the order of rows in place.
//! \~russian Изменяет порядок строк на обратный на месте.
//! \~\sa reverseColumns(), PIVector::reverse()
inline PIVector2D<T> & reverseRows() {
const size_t half = rows_ / 2;
for (size_t i = 0; i < half; ++i) {
T * row1 = data(i * cols_);
T * row2 = data((rows_ - 1 - i) * cols_);
for (size_t j = 0; j < cols_; ++j) {
piSwap(row1[j], row2[j]);
}
}
return *this;
}
//! \~english Reverses the order of columns in each row in place.
//! \~russian Изменяет порядок столбцов в каждой строке на обратный на месте.
//! \~\sa reverseRows(), PIVector::reverse()
inline PIVector2D<T> & reverseColumns() {
for (size_t r = 0; r < rows_; ++r) {
Row currentRow = row(r);
const size_t half = cols_ / 2;
for (size_t c = 0; c < half; ++c) {
piSwap<T>(currentRow[c], currentRow[cols_ - 1 - c]);
}
}
return *this;
}
//! \~english Returns a sub-2D array (a range of rows and columns).
//! \~russian Возвращает подмассив (диапазон строк и столбцов).
//! \details
//! \~english If the range exceeds the array boundaries, it is clipped. If rowCount or colCount is 0, an empty array is returned.
//! \~russian Если диапазон выходит за границы массива, он обрезается. Если rowCount или colCount равны 0, возвращается пустой массив.
//! \~\sa PIVector::getRange()
inline PIVector2D<T> getRange(size_t rowStart, size_t rowCount, size_t colStart, size_t colCount) const {
if (rowStart >= rows_ || colStart >= cols_ || rowCount == 0 || colCount == 0) return PIVector2D<T>();
const size_t actualRowCount = piMin<size_t>(rowCount, rows_ - rowStart);
const size_t actualColCount = piMin<size_t>(colCount, cols_ - colStart);
PIVector2D<T> result(actualRowCount, actualColCount);
for (size_t r = 0; r < actualRowCount; ++r) {
for (size_t c = 0; c < actualColCount; ++c) {
result.element(r, c) = element(rowStart + r, colStart + c);
}
}
return result;
}
//! \~english Applies a function to each element and returns a new 2D array of a different type.
//! \~russian Применяет функцию к каждому элементу и возвращает новый двумерный массив другого типа.
//! \details
//! \~english The original array is not modified.
//! \~russian Исходный массив не изменяется.
//! \~\sa PIVector::map()
template<typename ST>
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const {
return PIVector2D<ST>(rows_, cols_, mat.template map<ST>(f));
}
//! \~english Applies a function (with row and col indices) to each element and returns a new 2D array.
//! \~russian Применяет функцию (с индексами строки и столбца) к каждому элементу и возвращает новый двумерный массив.
//! \~\sa PIVector::mapIndexed()
template<typename ST>
inline PIVector2D<ST> mapIndexed(std::function<ST(size_t row, size_t col, const T & e)> f) const {
PIVector<ST> mappedMat;
mappedMat.reserve(size());
for (size_t r = 0; r < rows_; ++r) {
for (size_t c = 0; c < cols_; ++c) {
mappedMat << f(r, c, element(r, c));
}
}
return PIVector2D<ST>(rows_, cols_, std::move(mappedMat));
}
//! \~english Applies a function to each row (modifiable).
//! \~russian Применяет функцию к каждой строке (с возможностью изменения).
//! \~\sa forEachRow() const, PIVector::forEach()
inline PIVector2D<T> & forEachRow(std::function<void(Row)> f) {
for (size_t r = 0; r < rows_; ++r)
f(row(r));
return *this;
}
//! \~english Applies a function to each row (read-only).
//! \~russian Применяет функцию к каждой строке (только чтение).
inline void forEachRow(std::function<void(RowConst)> f) const {
for (size_t r = 0; r < rows_; ++r)
f(row(r));
}
//! \~english Applies a function to each column (modifiable).
//! \~russian Применяет функцию к каждому столбцу (с возможностью изменения).
inline PIVector2D<T> & forEachColumn(std::function<void(Col)> f) {
for (size_t c = 0; c < cols_; ++c)
f(col(c));
return *this;
}
//! \~english Applies a function to each column (read-only).
//! \~russian Применяет функцию к каждому столбцу (только чтение).
//! \param f Function taking a \a ColConst.
inline void forEachColumn(std::function<void(ColConst)> f) const {
for (size_t c = 0; c < cols_; ++c)
f(col(c));
}
//! \~english Accumulates a value across all elements.
//! \~russian Аккумулирует значение по всем элементам.
//! \~\sa PIVector::reduce()
template<typename ST>
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
return mat.template reduce<ST>(f, initial);
}
//! \~english Accumulates a value across all elements with indices.
//! \~russian Аккумулирует значение по всем элементам с индексами.
//! \~\sa PIVector::reduceIndexed()
template<typename ST>
inline ST reduceIndexed(std::function<ST(size_t row, size_t col, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t r = 0; r < rows_; ++r) {
for (size_t c = 0; c < cols_; ++c) {
ret = f(r, c, element(r, c), ret);
}
}
return ret;
}
//! \~english Removes a row from the 2D array.
//! \~russian Удаляет строку из двумерного массива.
//! \details
//! \~english If the last row is removed and the array becomes empty, \a cols() is set to 0.
//! \~russian Если удаляется последняя строка и массив становится пустым, \a cols() устанавливается в 0.
//! \~\sa removeColumn(), PIVector::remove()
inline PIVector2D<T> & removeRow(size_t row) { return deleteRows(row, 1); }
//! \~english Removes a column from the 2D array.
//! \~russian Удаляет столбец из двумерного массива.
//! \details
//! \~english This operation is more expensive than removing a row because elements must be moved.
//! \~russian Эта операция дороже, чем удаление строки, поскольку требуется перемещение элементов.
//! \~\sa removeRow(), PIVector::remove()
inline PIVector2D<T> & removeColumn(size_t col) { return deleteColumns(col, 1); }
//! \~english Removes all rows that satisfy a condition.
//! \~russian Удаляет все строки, удовлетворяющие условию.
//! \details
//! \~english Rows are removed from the bottom to avoid index shifting issues.
//! \~russian Строки удаляются снизу вверх, чтобы избежать проблем со смещением индексов.
//! \~\sa removeColumnsWhere(), PIVector::removeWhere()
inline PIVector2D<T> & removeRowsWhere(std::function<bool(const RowConst &)> test) {
ssize_t r = rows_;
while (--r >= 0) {
if (test(RowConst(this, r))) {
removeRow(r);
}
}
return *this;
}
//! \~english Removes all columns that satisfy a condition.
//! \~russian Удаляет все столбцы, удовлетворяющие условию.
//! \~\sa removeRowsWhere()
inline PIVector2D<T> & removeColumnsWhere(std::function<bool(const ColConst &)> test) {
ssize_t c = cols_;
while (--c >= 0) {
if (test(ColConst(this, c))) {
removeColumn(c);
}
}
return *this;
}
//! \~english Returns a new 2D array containing only the rows that pass the test.
//! \~russian Возвращает новый двумерный массив, содержащий только строки, прошедшие проверку.
//! \~\sa filterColumns(), PIVector::filter()
inline PIVector2D<T> filterRows(std::function<bool(const RowConst &)> test) const {
PIVector2D<T> result;
for (size_t r = 0; r < rows_; ++r) {
RowConst currentRow = row(r);
if (test(currentRow)) {
result.addRow(currentRow);
}
}
return result;
}
//! \~english Returns a new 2D array containing only the columns that pass the test.
//! \~russian Возвращает новый двумерный массив, содержащий только столбцы, прошедшие проверку.
//! \~\sa filterRows()
inline PIVector2D<T> filterColumns(std::function<bool(const ColConst &)> test) const {
if (isEmpty()) return PIVector2D<T>();
PIVector<size_t> goodCols;
for (size_t c = 0; c < cols_; ++c) {
if (test(col(c))) {
goodCols << c;
}
}
PIVector2D<T> result;
for (size_t gc = 0; gc < goodCols.size(); ++gc) {
result.addColumn(col(goodCols[gc]));
}
return result;
}
protected: protected:
size_t rows_, cols_; size_t rows_, cols_;
PIVector<T> mat; PIVector<T> mat;
}; };
//! \relatesalso PICout
//! \~english Output operator for \a PIVector2D to \a PICout.
//! \~russian Оператор вывода \a PIVector2D в \a PICout.
template<typename T> template<typename T>
inline PICout operator<<(PICout s, const PIVector2D<T> & v) { inline PICout operator<<(PICout s, const PIVector2D<T> & v) {
s.saveAndSetControls(0); s.saveAndSetControls(0);
@@ -346,5 +1406,6 @@ inline PICout operator<<(PICout s, const PIVector2D<T> & v) {
return s; return s;
} }
//! \}
#endif // PIVECTOR2D_H #endif // PIVECTOR2D_H

View File

@@ -245,6 +245,9 @@ inline constexpr T piAbs(const T & v) {
} }
//! \~\brief
//! \~english Templated function return minimum of two values
//! \~russian Шаблонный метод, возвращающий минимум из двух значений
template<typename T> template<typename T>
constexpr T piMin(const T & f, const T & s) { constexpr T piMin(const T & f, const T & s) {
return ((f > s) ? s : f); return ((f > s) ? s : f);
@@ -282,6 +285,9 @@ constexpr T piMin(const T & f, const T & s, const Args &... args) {
} }
//! \~\brief
//! \~english Templated function return maximum of two values
//! \~russian Шаблонный метод, возвращающий максимум из двух значений
template<typename T> template<typename T>
constexpr T piMax(const T & f, const T & s) { constexpr T piMax(const T & f, const T & s) {
return ((f < s) ? s : f); return ((f < s) ? s : f);

View File

@@ -87,27 +87,27 @@
#else #else
# define ADD_TO_COLLECTION(group, object) \ # define ADD_TO_COLLECTION(group, object) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, "", false); static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, "", false);
# define ADD_TO_COLLECTION_WITH_NAME(group, object, name) \ # define ADD_TO_COLLECTION_WITH_NAME(group, object, name) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, #name, false); static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, #name, false);
# define ADD_NEW_TO_COLLECTION(group, class) \ # define ADD_NEW_TO_COLLECTION(group, class) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), "", true); static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), "", true);
# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) \ # define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) \
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), #name, true); static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), #name, true);
#endif #endif
//! \ingroup Core /// \~english Helper to collect and retrieve classes to groups.
//! \~\brief /// \~russian Помощник для создания и получения классов в группы.
//! \~english Helper to collect and retrieve classes to groups.
//! \~russian Помощник для создания и получения классов в группы.
class PIP_EXPORT PICollection { class PIP_EXPORT PICollection {
friend class __PICollectionInitializer; friend class __PICollectionInitializer;
public: public:
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
PICollection() { ; } PICollection() { ; }
//! \~english Returns all existing groups by their names //! \~english Returns all existing groups by their names
@@ -118,10 +118,14 @@ public:
//! \~russian Возвращает все элементы группы "group" //! \~russian Возвращает все элементы группы "group"
static PIVector<const PIObject *> groupElements(const PIString & group); static PIVector<const PIObject *> groupElements(const PIString & group);
//! \~english Add element "element" to group "group"
//! \~russian Добавляет элемент "element" в группу "group"
static bool addToGroup(const PIString & group, const PIObject * element); static bool addToGroup(const PIString & group, const PIObject * element);
class PIP_EXPORT CollectionAdder { class PIP_EXPORT CollectionAdder {
public: public:
//! \~english Constructor that adds element to group
//! \~russian Конструктор, который добавляет элемент в группу
CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false); CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false);
}; };

View File

@@ -64,7 +64,16 @@ PIP_EXPORT PIString errorString();
//! \~russian Сброс последней ошибки //! \~russian Сброс последней ошибки
PIP_EXPORT void errorClear(); PIP_EXPORT void errorClear();
//! \ingroup Core
//! \brief
//! \~english Initialize random number generator
//! \~russian Инициализация генератора случайных чисел
PIP_EXPORT void randomize(); PIP_EXPORT void randomize();
//! \ingroup Core
//! \brief
//! \~english Returns random integer value
//! \~russian Возвращает случайное целое число
PIP_EXPORT int randomi(); PIP_EXPORT int randomi();
//! \ingroup Core //! \ingroup Core

View File

@@ -1,10 +1,13 @@
/*! \file piinit.h //! \addtogroup Core
* \ingroup Core //! \{
* \~\brief //! \file piinit.h
* \~english Library initialization //! \brief
* \~russian Инициализация библиотеки //! \~english Library initialization
*/ //! \~russian Инициализация библиотеки
/* //! \details
//! \~english This file provides initialization and build information for the PIP library.
//! \~russian Этот файл предоставляет инициализацию и информацию о сборке для библиотеки PIP.
/*!
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Initialization Initialization
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -37,6 +40,8 @@ class PIFile;
class PIStringList; class PIStringList;
//! \~english Internal initializer class for automatic library initialization
//! \~russian Внутренний класс инициализации для автоматической инициализации библиотеки
class PIP_EXPORT __PIInit_Initializer__ { class PIP_EXPORT __PIInit_Initializer__ {
public: public:
__PIInit_Initializer__(); __PIInit_Initializer__();
@@ -48,6 +53,8 @@ public:
static __PIInit_Initializer__ __piinit_initializer__; static __PIInit_Initializer__ __piinit_initializer__;
//! \~english Provides library initialization and build information
//! \~russian Предоставляет инициализацию библиотеки и информацию о сборке
class PIP_EXPORT PIInit { class PIP_EXPORT PIInit {
friend class __PIInit_Initializer__; friend class __PIInit_Initializer__;
friend class PIFile; friend class PIFile;
@@ -69,6 +76,8 @@ public:
boCloud /*! \~english PICloud transport support \~russian Поддержка облачного транспорта PICloud */ = 0x200, boCloud /*! \~english PICloud transport support \~russian Поддержка облачного транспорта PICloud */ = 0x200,
boConsole /*! \~english Console graphics support \~russian Поддержка графики в консоли */ = 0x400, boConsole /*! \~english Console graphics support \~russian Поддержка графики в консоли */ = 0x400,
}; };
//! \~english Returns singleton instance of PIInit
//! \~russian Возвращает синглтон экземпляр PIInit
static PIInit * instance() { return __PIInit_Initializer__::__instance__; } static PIInit * instance() { return __PIInit_Initializer__::__instance__; }
//! \ingroup Core //! \ingroup Core
@@ -89,4 +98,5 @@ private:
#endif // MICRO_PIP #endif // MICRO_PIP
//! \}
#endif // PIINIT_H #endif // PIINIT_H

View File

@@ -45,11 +45,15 @@ public:
s = size_; s = size_;
} }
//! \~english Copy constructor
//! \~russian Конструктор копирования
PIMemoryBlock(const PIMemoryBlock & o) { PIMemoryBlock(const PIMemoryBlock & o) {
d = o.d; d = o.d;
s = o.s; s = o.s;
} }
//! \~english Assignment operator
//! \~russian Оператор присваивания
PIMemoryBlock & operator=(const PIMemoryBlock & o) { PIMemoryBlock & operator=(const PIMemoryBlock & o) {
d = o.d; d = o.d;
s = o.s; s = o.s;

View File

@@ -1,9 +1,15 @@
/*! \file piobject.h //! \addtogroup Core
* \ingroup Core //! \{
* \~\brief //! \file piobject.h
* \~english Base object //! \brief
* \~russian Базовый класс //! \~english Base object class providing event -> handler mechanism
*/ //! \~russian Базовый класс объектов, обеспечивающий механизм событий -> обработчиков
//! \details
//! \~english PIObject is the base class for all PIP classes that need event-driven communication.
//! It provides signal-slot mechanism, property system, and object lifetime management.
//! \~russian PIObject является базовым классом для всех классов PIP, которым необходима событийная коммуникация.
//! Он обеспечивает механизм сигналов-слотов, систему свойств и управление жизненным циклом объектов.
//! \~
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
@@ -34,10 +40,8 @@
#include "pivariant.h" #include "pivariant.h"
#include "pivariantsimple.h" #include "pivariantsimple.h"
//! \ingroup Core //! \~english Base class for classes using event -> handler mechanism
//! \~\brief //! \~russian Базовый класс для классов, использующих механизм событий -> обработчиков
//! \~english This is base class for any classes which use events -> handlers mechanism.
//! \~russian Этот класс является базовым для использования механизма события -> обработчики.
class PIP_EXPORT PIObject { class PIP_EXPORT PIObject {
#ifndef MICRO_PIP #ifndef MICRO_PIP
friend class PIObjectManager; friend class PIObjectManager;
@@ -50,7 +54,7 @@ class PIP_EXPORT PIObject {
public: public:
NO_COPY_CLASS(PIObject); NO_COPY_CLASS(PIObject);
//! \~english Contructs %PIObject with name "name" //! \~english Constructs %PIObject with name "name"
//! \~russian Создает %PIObject с именем "name" //! \~russian Создает %PIObject с именем "name"
explicit PIObject(const PIString & name = PIString()); explicit PIObject(const PIString & name = PIString());
@@ -93,7 +97,7 @@ public:
int args_count; int args_count;
public: public:
//! \~english Contructs invalid %Connection //! \~english Constructs invalid %Connection
//! \~russian Создает недействительный %Connection //! \~russian Создает недействительный %Connection
Connection(); Connection();
@@ -175,17 +179,31 @@ public:
bool isPropertyExists(const char * name) const { return properties_.contains(piHashData((const uchar *)name, strlen(name))); } bool isPropertyExists(const char * name) const { return properties_.contains(piHashData((const uchar *)name, strlen(name))); }
void setThreadSafe(bool yes) { thread_safe_ = yes; } void setThreadSafe(bool yes) { thread_safe_ = yes; }
//! \~english Returns if object is thread safe
//! \~russian Возвращает является ли объект потокобезопасным
bool isThreadSafe() const { return thread_safe_; } bool isThreadSafe() const { return thread_safe_; }
//! \~english Executes method with specified arguments
//! \~russian Выполняет метод с указанными аргументами
bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl); bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl);
//! \~english Executes method without arguments
//! \~russian Выполняет метод без аргументов
bool execute(const PIString & method) { return execute(method, PIVector<PIVariantSimple>()); } bool execute(const PIString & method) { return execute(method, PIVector<PIVariantSimple>()); }
//! \~english Executes method with one argument
//! \~russian Выполняет метод с одним аргументом
bool execute(const PIString & method, const PIVariantSimple & v0) { return execute(method, PIVector<PIVariantSimple>() << v0); } bool execute(const PIString & method, const PIVariantSimple & v0) { return execute(method, PIVector<PIVariantSimple>() << v0); }
//! \~english Executes method with two arguments
//! \~russian Выполняет метод с двумя аргументами
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return execute(method, PIVector<PIVariantSimple>() << v0 << v1); return execute(method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method with three arguments
//! \~russian Выполняет метод с тремя аргументами
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {
return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method with four arguments
//! \~russian Выполняет метод с четырьмя аргументами
bool execute(const PIString & method, bool execute(const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
const PIVariantSimple & v1, const PIVariantSimple & v1,
@@ -194,16 +212,26 @@ public:
return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Executes method queued with performer
//! \~russian Выполняет метод в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl); bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl);
//! \~english Executes method without arguments queued with performer
//! \~russian Выполняет метод без аргументов в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method) { bool executeQueued(PIObject * performer, const PIString & method) {
return executeQueued(performer, method, PIVector<PIVariantSimple>()); return executeQueued(performer, method, PIVector<PIVariantSimple>());
} }
//! \~english Executes method with one argument queued with performer
//! \~russian Выполняет метод с одним аргументом в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) { bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0);
} }
//! \~english Executes method with two arguments queued with performer
//! \~russian Выполняет метод с двумя аргументами в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method with three arguments queued with performer
//! \~russian Выполняет метод с тремя аргументами в очереди с исполнителем
bool executeQueued(PIObject * performer, bool executeQueued(PIObject * performer,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -211,6 +239,8 @@ public:
const PIVariantSimple & v2) { const PIVariantSimple & v2) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method with four arguments queued with performer
//! \~russian Выполняет метод с четырьмя аргументами в очереди с исполнителем
bool executeQueued(PIObject * performer, bool executeQueued(PIObject * performer,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -220,18 +250,30 @@ public:
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Executes method on object with specified arguments
//! \~russian Выполняет метод на объекте с указанными аргументами
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariantSimple> & vl) { return o->execute(method, vl); } static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariantSimple> & vl) { return o->execute(method, vl); }
//! \~english Executes method on object without arguments
//! \~russian Выполняет метод на объекте без аргументов
static bool execute(PIObject * o, const PIString & method) { return execute(o, method, PIVector<PIVariantSimple>()); } static bool execute(PIObject * o, const PIString & method) { return execute(o, method, PIVector<PIVariantSimple>()); }
//! \~english Executes method on object with one argument
//! \~russian Выполняет метод на объекте с одним аргументом
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) { static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) {
return execute(o, method, PIVector<PIVariantSimple>() << v0); return execute(o, method, PIVector<PIVariantSimple>() << v0);
} }
//! \~english Executes method on object with two arguments
//! \~russian Выполняет метод на объекте с двумя аргументами
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1); return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method on object with three arguments
//! \~russian Выполняет метод на объекте с тремя аргументами
static bool static bool
execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method on object with four arguments
//! \~russian Выполняет метод на объекте с четырьмя аргументами
static bool execute(PIObject * o, static bool execute(PIObject * o,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -241,19 +283,29 @@ public:
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Executes method on object queued with performer
//! \~russian Выполняет метод на объекте в очереди с исполнителем
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) { static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) {
return o->executeQueued(performer, method, vl); return o->executeQueued(performer, method, vl);
} }
//! \~english Executes method on object without arguments queued with performer
//! \~russian Выполняет метод на объекте без аргументов в очереди с исполнителем
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) { static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>()); return executeQueued(o, performer, method, PIVector<PIVariantSimple>());
} }
//! \~english Executes method on object with one argument queued with performer
//! \~russian Выполняет метод на объекте с одним аргументом в очереди с исполнителем
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) { static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0);
} }
//! \~english Executes method on object with two arguments queued with performer
//! \~russian Выполняет метод на объекте с двумя аргументами в очереди с исполнителем
static bool static bool
executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method on object with three arguments queued with performer
//! \~russian Выполняет метод на объекте с тремя аргументами в очереди с исполнителем
static bool executeQueued(PIObject * o, static bool executeQueued(PIObject * o,
PIObject * performer, PIObject * performer,
const PIString & method, const PIString & method,
@@ -262,6 +314,8 @@ public:
const PIVariantSimple & v2) { const PIVariantSimple & v2) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method on object with four arguments queued with performer
//! \~russian Выполняет метод на объекте с четырьмя аргументами в очереди с исполнителем
static bool executeQueued(PIObject * o, static bool executeQueued(PIObject * o,
PIObject * performer, PIObject * performer,
const PIString & method, const PIString & method,
@@ -272,6 +326,8 @@ public:
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Dumps object information
//! \~russian Выводит информацию об объекте
void dump(const PIString & line_prefix = PIString()) const; void dump(const PIString & line_prefix = PIString()) const;
@@ -279,10 +335,20 @@ public:
//! \~russian Возвращает цепочку наследования объекта (вместе с классом самого объекта) //! \~russian Возвращает цепочку наследования объекта (вместе с классом самого объекта)
PIStringList scopeList() const; PIStringList scopeList() const;
//! \~english Returns list of all event-handler methods
//! \~russian Возвращает список всех методов-обработчиков событий
PIStringList methodsEH() const; PIStringList methodsEH() const;
//! \~english Returns if method "name" is event-handler
//! \~russian Возвращает является ли метод "name" обработчиком событий
bool isMethodEHContains(const PIString & name) const; bool isMethodEHContains(const PIString & name) const;
//! \~english Returns arguments of event-handler method "name"
//! \~russian Возвращает аргументы метода-обработчика событий "name"
PIString methodEHArguments(const PIString & name) const; PIString methodEHArguments(const PIString & name) const;
//! \~english Returns full format of event-handler method "name"
//! \~russian Возвращает полный формат метода-обработчика событий "name"
PIString methodEHFullFormat(const PIString & name) const; PIString methodEHFullFormat(const PIString & name) const;
//! \~english Returns event-handler method name from address "addr"
//! \~russian Возвращает имя метода-обработчика событий по адресу "addr"
PIString methodEHFromAddr(const void * addr) const; PIString methodEHFromAddr(const void * addr) const;
// / Direct connect // / Direct connect
@@ -542,6 +608,8 @@ public:
//! \~english Returns if "o" is valid %PIObject (check signature) //! \~english Returns if "o" is valid %PIObject (check signature)
//! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись) //! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись)
static bool isPIObject(const PIObject * o); static bool isPIObject(const PIObject * o);
//! \~english Returns if "o" is valid %PIObject (check signature)
//! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись)
static bool isPIObject(const void * o) { return isPIObject((PIObject *)o); } static bool isPIObject(const void * o) { return isPIObject((PIObject *)o); }
//! \~english Returns if "o" is valid %PIObject subclass "T" (check signature and classname) //! \~english Returns if "o" is valid %PIObject subclass "T" (check signature and classname)
@@ -554,6 +622,8 @@ public:
static bool isTypeOf(const void * o) { static bool isTypeOf(const void * o) {
return isTypeOf<T>((PIObject *)o); return isTypeOf<T>((PIObject *)o);
} }
//! \~english Simplifies type name "a" to readable format
//! \~russian Упрощает имя типа "a" в читаемый формат
static PIString simplifyType(const char * a, bool readable = true); static PIString simplifyType(const char * a, bool readable = true);
struct PIP_EXPORT __MetaFunc { struct PIP_EXPORT __MetaFunc {

View File

@@ -1,8 +1,12 @@
/*! \file piauth.h /*! \file piauth.h
* \ingroup Crypt * \addtogroup Crypt
* \~\brief * \{
* \~english Authentication API * \brief Authentication API
* \~russian API аутентификации * \~english Authentication API for client-server key exchange and authentication
* \~russian API аутентификации для обмена ключами и аутентификации клиент-сервер
* \details
* \~english Provides classes for secure client-server authentication with digital signatures, password verification, and key exchange
* \~russian Предоставляет классы для безопасной клиент-серверной аутентификации с цифровыми подписями, проверкой пароля и обменом ключами
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -31,70 +35,106 @@
#include "pip_crypt_export.h" #include "pip_crypt_export.h"
//! \~english Authentication and key exchange class
//! \~russian Класс аутентификации и обмена ключами
class PIP_CRYPT_EXPORT PIAuth: public PIObject { class PIP_CRYPT_EXPORT PIAuth: public PIObject {
PIOBJECT(PIAuth) PIOBJECT(PIAuth)
public: public:
//! \~english Authentication state
//! \~russian Состояние аутентификации
enum State { enum State {
NotConnected, NotConnected, //!< \~english Not connected \~russian Не подключен
AuthProbe, AuthProbe, //!< \~english Authentication probe \~russian Зондирование аутентификации
PassRequest, PassRequest, //!< \~english Password request \~russian Запрос пароля
AuthReply, AuthReply, //!< \~english Authentication reply \~russian Ответ аутентификации
KeyExchange, KeyExchange, //!< \~english Key exchange \~russian Обмен ключами
Connected Connected //!< \~english Connected, authenticated \~russian Подключено, аутентифицировано
}; };
//! Create PIAuth with your digital sign //! \~english Create PIAuth with your digital sign
//! \~russian Создать PIAuth с вашей цифровой подписью
//! \param sign \~english Digital sign private key \~russian Приватный ключ цифровой подписи
PIAuth(const PIByteArray & sign); PIAuth(const PIByteArray & sign);
//! Set server info data for client authorize event //! \~english Set server info data for client authorize event
//! \~russian Установить информационные данные сервера для события авторизации клиента
//! \param info \~english Info data \~russian Информационные данные
void setInfoData(const PIByteArray & info) { custom_info = info; } void setInfoData(const PIByteArray & info) { custom_info = info; }
//! Set server password for check //! \~english Set server password for check
//! \~russian Установить пароль сервера для проверки
//! \param ps \~english Server password \~russian Пароль сервера
void setServerPassword(const PIString & ps); void setServerPassword(const PIString & ps);
//! Set list of trusted clients/servers public digital sign keys //! \~english Set list of trusted clients/servers public digital sign keys
//! \~russian Установить список доверенных публичных ключей цифровой подписи клиентов/серверов
//! \param pkeys \~english List of public keys \~russian Список публичных ключей
void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) { auth_pkeys = pkeys; } void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) { auth_pkeys = pkeys; }
//! Get list of trusted clients/servers public digital sign keys //! \~english Get list of trusted clients/servers public digital sign keys
//! \~russian Получить список доверенных публичных ключей цифровой подписи клиентов/серверов
//! \return \~english List of public keys \~russian Список публичных ключей
PIVector<PIByteArray> getAuthorizedPublicKeys() { return auth_pkeys; } PIVector<PIByteArray> getAuthorizedPublicKeys() { return auth_pkeys; }
//! Get your digital sign public key //! \~english Get your digital sign public key
//! \~russian Получить ваш публичный ключ цифровой подписи
//! \return Public sign key \~english Публичный ключ подписи
PIByteArray getSignPublicKey() { return sign_pk; } PIByteArray getSignPublicKey() { return sign_pk; }
//! Stop authorization //! \~english Stop authorization
//! \~russian Остановить авторизацию
void stop(); void stop();
//! Start authorization as client //! \~english Start authorization as client
//! \~russian Начать авторизацию как клиент
void startClient(); void startClient();
//! Start authorization as server, return first server message for client //! \~english Start authorization as server, return first server message for client
//! \~russian Начать авторизацию как сервер, вернуть первое сообщение сервера для клиента
//! \return \~english First server message \~russian Первое сообщение сервера
PIByteArray startServer(); PIByteArray startServer();
//! Process reseived message both for client and server, return current state and new message writed in "ba" //! \~english Process received message both for client and server, return current state and new message written in "ba"
//! \~russian Обработать полученное сообщение как для клиента, так и для сервера, вернуть текущее состояние и новое сообщение в "ba"
//! \param ba \~english Message to process, output message \~russian Сообщение для обработки, выходное сообщение
//! \return \~english Current authentication state \~russian Текущее состояние аутентификации
State receive(PIByteArray & ba); State receive(PIByteArray & ba);
//! Get session secret key, return key only when Connected state //! \~english Get session secret key, return key only when Connected state
//! \~russian Получить секретный ключ сессии, вернуть ключ только в состоянии Connected
//! \return \~english Session secret key \~russian Секретный ключ сессии
//! \note
//! \~english Returns empty array if not connected
//! \~russian Возвращает пустой массив если не подключен
PIByteArray getSecretKey(); PIByteArray getSecretKey();
//! Generate digital sign from seed //! \~english Generate digital sign from seed
//! \~russian Сгенерировать цифровую подпись из зерна
//! \param seed \~english Seed for key generation \~russian Зерно для генерации ключа
//! \return \~english Generated digital sign key \~russian Сгенерированный ключ цифровой подписи
static PIByteArray generateSign(const PIByteArray & seed); static PIByteArray generateSign(const PIByteArray & seed);
//! Disconneted event //! \~english Disconnected event
//! \~russian Событие отключения
EVENT1(disconnected, PIString, reason); EVENT1(disconnected, PIString, reason);
//! Conneted event //! \~english Connected event
//! \~russian Событие подключения
EVENT1(connected, PIString, info); EVENT1(connected, PIString, info);
//! Client event for authorize new server //! \~english Client event for authorize new server
//! \~russian Событие клиента для авторизации нового сервера
EVENT2(authorize, PIByteArray, info, bool *, ok); EVENT2(authorize, PIByteArray, info, bool *, ok);
//! Client event for input server password //! \~english Client event for input server password
//! \~russian Событие клиента для ввода пароля сервера
EVENT1(passwordRequest, PIString *, pass); EVENT1(passwordRequest, PIString *, pass);
//! Server event on check client password //! \~english Server event on check client password
//! \~russian Событие сервера при проверке пароля клиента
EVENT1(passwordCheck, bool, result); EVENT1(passwordCheck, bool, result);
private: private:

View File

@@ -40,6 +40,9 @@ public:
//! \~russian Конструктор, генерирующий случайный ключ //! \~russian Конструктор, генерирующий случайный ключ
PICrypt(); PICrypt();
//! \~\brief
//! \~english Destructor
//! \~russian Деструктор
~PICrypt(); ~PICrypt();
//! \~\brief //! \~\brief

View File

@@ -1,32 +1,33 @@
/*! \file pidigest.h //! \addtogroup Core
* \ingroup Core //! \{
* \~\brief //! \file pidigest.h
* \~english Digest algorithms //! \brief
* \~russian Алгоритмы хэш-сумм //! \~english Digest algorithms
* //! \~russian Алгоритмы хэш-сумм
* \~\details //!
* \~english //! \details
* This file implements several common-usage hash algorithms //! \~english
* \~russian //! This file implements several common-usage hash algorithms
* Этот файл реализует несколько распространенных алгоритмов хэширования //! \~russian
*/ //! Этот файл реализует несколько распространенных алгоритмов хэширования
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Digest algorithms Digest algorithms
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef pidigest_h #ifndef pidigest_h
@@ -37,6 +38,15 @@
class PIP_EXPORT PIDigest { class PIP_EXPORT PIDigest {
public: public:
//! \~english Hash algorithm type
//! \~russian Тип алгоритма хэширования
//! \details
//! \~english
//! Supported algorithms: SHA1, SHA2 family (224, 256, 384, 512, 512_224, 512_256),
//! MD2, MD4, MD5, BLAKE2s, BLAKE2b, SipHash
//! \~russian
//! Поддерживаемые алгоритмы: SHA1, семейство SHA2 (224, 256, 384, 512, 512_224, 512_256),
//! MD2, MD4, MD5, BLAKE2s, BLAKE2b, SipHash
enum class Type { enum class Type {
SHA1, SHA1,
@@ -70,13 +80,45 @@ public:
Count, Count,
}; };
//! \~english Get hash output length in bytes
//! \~russian Получить длину хэша в байтах
static int hashLength(Type type); static int hashLength(Type type);
//! \~english Get hash block length in bytes
//! \~russian Получить длину блока хэширования в байтах
static int blockLength(Type type); static int blockLength(Type type);
//! \~english Get algorithm name as string
//! \~russian Получить название алгоритма в виде строки
//! \return Algorithm name
//! \sa Type
static PIConstChars typeName(Type type); static PIConstChars typeName(Type type);
//! \~english Calculate hash of message
//! \~russian Вычислить хэш сообщения
//! \param msg Input message
//! \param type Hash algorithm type
//! \return Hash bytes
//! \sa calculateWithKey, HMAC
static PIByteArray calculate(const PIByteArray & msg, Type type); static PIByteArray calculate(const PIByteArray & msg, Type type);
//! \~english Calculate keyed hash of message
//! \~russian Вычислить ключевой хэш сообщения
//! \param msg Input message
//! \param key Secret key
//! \param type Hash algorithm type (SipHash or BLAKE2)
//! \return Hash bytes
//! \note Only SipHash and BLAKE2 algorithms support keyed hashing
//! \sa calculate, HMAC
static PIByteArray calculateWithKey(const PIByteArray & msg, const PIByteArray & key, Type type); static PIByteArray calculateWithKey(const PIByteArray & msg, const PIByteArray & key, Type type);
//! \~english Calculate HMAC (Keyed-Hash Message Authentication Code)
//! \~russian Вычислить HMAC (код аутентификации сообщений на основе ключа)
//! \param msg Input message
//! \param key Secret key
//! \param type Hash algorithm type
//! \return HMAC bytes
//! \note Supports SHA1, SHA2 and MD5 algorithms
//! \sa calculate, calculateWithKey
static PIByteArray HMAC(const PIByteArray & msg, const PIByteArray & key, PIDigest::Type type); static PIByteArray HMAC(const PIByteArray & msg, const PIByteArray & key, PIDigest::Type type);
}; };
//! \}
#endif #endif

View File

@@ -29,21 +29,53 @@
#include "pimathbase.h" #include "pimathbase.h"
//! \~english Geographical ellipsoid Earth model
//! \~russian Географическая эллипсоидная модель Земли
class PIP_EXPORT PIEllipsoidModel { class PIP_EXPORT PIEllipsoidModel {
public: public:
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
PIEllipsoidModel(); PIEllipsoidModel();
double eccSquared() const { return eccentricity * eccentricity; } // eccentricity squared
//! \~english Get eccentricity squared
//! \~russian Получить квадрат эксцентриситета
double eccSquared() const { return eccentricity * eccentricity; }
//! \~english Get semi-minor axis (b)
//! \~russian Получить малую полуось (b)
double b() const { return a * sqrt(1 - eccSquared()); } double b() const { return a * sqrt(1 - eccSquared()); }
//! \~english WGS84 ellipsoid model
//! \~russian Эллипсоид WGS84
static PIEllipsoidModel WGS84Ellipsoid(); static PIEllipsoidModel WGS84Ellipsoid();
//! \~english PZ90 ellipsoid model
//! \~russian Эллипсоид ПЗ-90
static PIEllipsoidModel PZ90Ellipsoid(); static PIEllipsoidModel PZ90Ellipsoid();
//! \~english GPS ellipsoid (same as WGS84)
//! \~russian Эллипсоид GPS (то же что WGS84)
static PIEllipsoidModel GPSEllipsoid(); static PIEllipsoidModel GPSEllipsoid();
//! \~english Krasovskiy ellipsoid model
//! \~russian Эллипсоид Красовского
static PIEllipsoidModel KrasovskiyEllipsoid(); static PIEllipsoidModel KrasovskiyEllipsoid();
double a; /// Major axis of Earth in meters //! \~english Major semi-axis (meters)
double flattening; /// Flattening (ellipsoid parameter) //! \~russian Большая полуось (метры)
double eccentricity; /// Eccentricity (ellipsoid parameter) double a;
double angVelocity; /// Angular velocity of Earth in radians/sec
//! \~english Flattening (f = (a-b)/a)
//! \~russian Сплюснутость (f = (a-b)/a)
double flattening;
//! \~english First eccentricity
//! \~russian Первый эксцентриситет
double eccentricity;
//! \~english Angular velocity (rad/sec)
//! \~russian Угловая скорость (рад/сек)
double angVelocity;
}; };

View File

@@ -29,147 +29,338 @@
#include "piellipsoidmodel.h" #include "piellipsoidmodel.h"
#include "pimathvector.h" #include "pimathvector.h"
//! \~english Geographical position class
//! \~russian Класс географической позиции
class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d { class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d {
public: public:
//! \~english Coordinate system types
//! \~russian Типы систем координат
enum CoordinateSystem { enum CoordinateSystem {
Unknown = 0, /// Unknown coordinate system Unknown = 0, //!< Unknown coordinate system
Geodetic, /// Geodetic latitude, longitude, and height above ellipsoid Geodetic, //!< Geodetic latitude, longitude, and height above ellipsoid
Geocentric, /// Geocentric (regular spherical coordinates) Geocentric, //!< Geocentric (regular spherical coordinates)
Cartesian, /// Cartesian (Earth-centered, Earth-fixed) Cartesian, //!< Cartesian (Earth-centered, Earth-fixed)
Spherical /// Spherical coordinates (theta,phi,radius) Spherical //!< Spherical coordinates (theta,phi,radius)
}; };
static const double one_cm_tolerance; /// One centimeter tolerance. //! \~english One centimeter tolerance
static const double one_mm_tolerance; /// One millimeter tolerance. //! \~russian Допуск один сантиметр
static const double one_um_tolerance; /// One micron tolerance. static const double one_cm_tolerance;
static double position_tolerance; /// Default tolerance (default 1mm)
//! \~english One millimeter tolerance
//! \~russian Допуск один миллиметр
static const double one_mm_tolerance;
//! \~english One micron tolerance
//! \~russian Допуск один микрон
static const double one_um_tolerance;
//! \~english Default position tolerance (default 1mm)
//! \~russian Допуск позиции по умолчанию (по умолчанию 1мм)
static double position_tolerance;
//! \~english Set position tolerance
//! \~russian Установить допуск позиции
//! \param tol New tolerance value
//! \return Previous tolerance value
static double setPositionTolerance(const double tol) { static double setPositionTolerance(const double tol) {
position_tolerance = tol; position_tolerance = tol;
return position_tolerance; return position_tolerance;
} }
//! \~english Get position tolerance
//! \~russian Получить допуск позиции
static double getPositionTolerance() { return position_tolerance; } static double getPositionTolerance() { return position_tolerance; }
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
PIGeoPosition(); PIGeoPosition();
//! \~english Constructor with coordinates
//! \~russian Конструктор с координатами
//! \param a First coordinate
//! \param b Second coordinate
//! \param c Third coordinate
//! \param s Coordinate system
//! \param ell Ellipsoid model
PIGeoPosition(double a, double b, double c, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition(double a, double b, double c, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Constructor from vector
//! \~russian Конструктор из вектора
//! \param v Vector with coordinates
//! \param s Coordinate system
//! \param ell Ellipsoid model
PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Transform to specified coordinate system
//! \~russian Преобразовать в указанную систему координат
//! \param sys Target coordinate system
//! \return Reference to this position
PIGeoPosition & transformTo(CoordinateSystem sys); PIGeoPosition & transformTo(CoordinateSystem sys);
//! \~english Convert to geodetic coordinates
//! \~russian Преобразовать в геодезические координаты
PIGeoPosition & asGeodetic() { PIGeoPosition & asGeodetic() {
transformTo(Geodetic); transformTo(Geodetic);
return *this; return *this;
} /// Convert to geodetic coordinate }
//! \~english Convert to geodetic coordinates using specified ellipsoid
//! \~russian Преобразовать в геодезические координаты с указанным эллипсоидом
//! \param ell Ellipsoid model to use
//! \return Reference to this position
PIGeoPosition & asGeodetic(const PIEllipsoidModel & ell) { PIGeoPosition & asGeodetic(const PIEllipsoidModel & ell) {
setEllipsoidModel(ell); setEllipsoidModel(ell);
transformTo(Geodetic); transformTo(Geodetic);
return *this; return *this;
} /// Convert to another ell, then to geodetic coordinates }
//! \~english Convert to ECEF (cartesian) coordinates
//! \~russian Преобразовать в координаты ECEF (декартовы)
PIGeoPosition & asECEF() { PIGeoPosition & asECEF() {
transformTo(Cartesian); transformTo(Cartesian);
return *this; return *this;
} /// Convert to cartesian coordinates }
//! \~english Get X coordinate (or first coordinate in Cartesian)
//! \~russian Получить координату X (или первую координату в Декартовой)
double x() const; double x() const;
//! \~english Get Y coordinate (or second coordinate in Cartesian)
//! \~russian Получить координату Y (или вторую координату в Декартовой)
double y() const; double y() const;
//! \~english Get Z coordinate (or third coordinate in Cartesian)
//! \~russian Получить координату Z (или третью координату в Декартовой)
double z() const; double z() const;
//! \~english Get geodetic latitude in degrees
//! \~russian Получить геодезическую широту в градусах
double latitudeGeodetic() const; double latitudeGeodetic() const;
//! \~english Get geocentric latitude in degrees
//! \~russian Получить геоцентрическую широту в градусах
double latitudeGeocentric() const; double latitudeGeocentric() const;
//! \~english Get longitude in degrees
//! \~russian Получить долготу в градусах
double longitude() const; double longitude() const;
//! \~english Get theta (angle from Z axis) in degrees
//! \~russian Получить тета (угол от оси Z) в градусах
double theta() const; double theta() const;
//! \~english Get phi (angle in XY plane from X axis) in degrees
//! \~russian Получить фи (угол в плоскости XY от оси X) в градусах
double phi() const; double phi() const;
//! \~english Get radius (distance from Earth center)
//! \~russian Получить радиус (расстояние от центра Земли)
double radius() const; double radius() const;
//! \~english Get height above ellipsoid
//! \~russian Получить высоту над эллипсоидом
double height() const; double height() const;
/// Set the ellipsoid values for this PIGeoPosition given a ellipsoid. //! \~english Set ellipsoid model for this position
//! \~russian Установить модель эллипсоида для этой позиции
//! \param ell Ellipsoid model
void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; } void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; }
/// Set the \a PIGeoPosition given geodetic coordinates in degrees. \a CoordinateSystem is set to \a Geodetic. //! \~english Set position from geodetic coordinates
//! \~russian Установить позицию из геодезических координат
//! \param lat Latitude in degrees
//! \param lon Longitude in degrees
//! \param ht Height above ellipsoid
//! \param ell Ellipsoid model (default WGS84)
//! \return Reference to this position
PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Set the \a PIGeoPosition given geocentric coordinates in degrees. \a CoordinateSystem is set to \a Geocentric //! \~english Set position from geocentric coordinates
//! \~russian Установить позицию из геоцентрических координат
//! \param lat Latitude in degrees
//! \param lon Longitude in degrees
//! \param rad Radius
//! \return Reference to this position
PIGeoPosition & setGeocentric(double lat, double lon, double rad); PIGeoPosition & setGeocentric(double lat, double lon, double rad);
/// Set the \a PIGeoPosition given spherical coordinates in degrees. \a CoordinateSystem is set to \a Spherical //! \~english Set position from spherical coordinates
//! \~russian Установить позицию из сферических координат
//! \param theta Angle from Z axis in degrees
//! \param phi Angle in XY plane from X axis in degrees
//! \param rad Radius
//! \return Reference to this position
PIGeoPosition & setSpherical(double theta, double phi, double rad); PIGeoPosition & setSpherical(double theta, double phi, double rad);
/// Set the \a PIGeoPosition given ECEF coordinates in meeters. \a CoordinateSystem is set to \a Cartesian. //! \~english Set position from ECEF coordinates
//! \~russian Установить позицию из координат ECEF
//! \param x X coordinate in meters
//! \param y Y coordinate in meters
//! \param z Z coordinate in meters
//! \return Reference to this position
PIGeoPosition & setECEF(double x, double y, double z); PIGeoPosition & setECEF(double x, double y, double z);
/// Fundamental conversion from spherical to cartesian coordinates. //! \~english Convert spherical to Cartesian coordinates
//! \~russian Преобразовать сферические в декартовы координаты
//! \param tpr Input spherical (theta, phi, radius)
//! \param xyz Output Cartesian (x, y, z)
static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz); static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz);
/// Fundamental routine to convert cartesian to spherical coordinates. //! \~english Convert Cartesian to spherical coordinates
//! \~russian Преобразовать декартовы в сферические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param tpr Output spherical (theta, phi, radius)
static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr); static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr);
/// Fundamental routine to convert ECEF (cartesian) to geodetic coordinates, //! \~english Convert Cartesian (ECEF) to geodetic coordinates
//! \~russian Преобразовать декартовы (ECEF) в геодезические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param llh Output geodetic (latitude, longitude, height)
//! \param ell Ellipsoid model (default WGS84)
static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz, static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz,
PIMathVectorT3d & llh, PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert geodetic to ECEF (cartesian) coordinates, //! \~english Convert geodetic to Cartesian (ECEF) coordinates
//! \~russian Преобразовать геодезические в декартовы (ECEF) координаты
//! \param llh Input geodetic (latitude, longitude, height)
//! \param xyz Output Cartesian (x, y, z)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeodeticToCartesian(const PIMathVectorT3d & llh, static void convertGeodeticToCartesian(const PIMathVectorT3d & llh,
PIMathVectorT3d & xyz, PIMathVectorT3d & xyz,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert cartesian (ECEF) to geocentric //! \~english Convert Cartesian (ECEF) to geocentric coordinates
//! \~russian Преобразовать декартовы (ECEF) в геоцентрические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param llr Output geocentric (latitude, longitude, radius)
static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr); static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr);
/// Fundamental routine to convert geocentric to cartesian (ECEF) //! \~english Convert geocentric to Cartesian (ECEF)
//! \~russian Преобразовать геоцентрические в декартовы (ECEF)
//! \param llr Input geocentric (latitude, longitude, radius)
//! \param xyz Output Cartesian (x, y, z)
static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz); static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz);
/// Fundamental routine to convert geocentric to geodetic //! \~english Convert geocentric to geodetic
//! \~russian Преобразовать геоцентрические в геодезические
//! \param llr Input geocentric (latitude, longitude, radius)
//! \param llh Output geodetic (latitude, longitude, height)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr, static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr,
PIMathVectorT3d & llh, PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert geodetic to geocentric //! \~english Convert geodetic to geocentric
//! \~russian Преобразовать геодезические в геоцентрические
//! \param llh Input geodetic (latitude, longitude, height)
//! \param llr Output geocentric (latitude, longitude, radius)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh, static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh,
PIMathVectorT3d & llr, PIMathVectorT3d & llr,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Compute the radius of the ellipsoidal Earth, given the geodetic latitude. //! \~english Compute radius of ellipsoid at given latitude
//! \~russian Вычислить радиус эллипсоида на заданной широте
//! \param geolat Geodetic latitude in degrees
//! \param ell Ellipsoid model (default WGS84)
//! \return Radius in meters
static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Compute radius of ellipsoid at current position
//! \~russian Вычислить радиус эллипсоида в текущей позиции
double radiusEarth() const { double radiusEarth() const {
PIGeoPosition p(*this); PIGeoPosition p(*this);
p.transformTo(PIGeoPosition::Geodetic); p.transformTo(PIGeoPosition::Geodetic);
return PIGeoPosition::radiusEarth((*this)[0], p.el); return PIGeoPosition::radiusEarth((*this)[0], p.el);
} }
/// Compute the range in meters between two PIGeoPositions. //! \~english Compute range between two positions
//! \~russian Вычислить расстояние между двумя позициями
//! \param a First position
//! \param b Second position
//! \return Range in meters
static double range(const PIGeoPosition & a, const PIGeoPosition & b); static double range(const PIGeoPosition & a, const PIGeoPosition & b);
//! \~english Compute range from this position to another
//! \~russian Вычислить расстояние от этой позиции до другой
//! \param p Target position
//! \return Range in meters
double range(const PIGeoPosition & p) const { return range((*this), p); } double range(const PIGeoPosition & p) const { return range((*this), p); }
/// Computes the elevation of the input (p) position as seen from this PIGeoPosition. //! \~english Compute elevation angle to target position
//! \~russian Вычислить угол возвышения до целевой позиции
//! \param p Target position
//! \return Elevation angle in degrees
double elevation(const PIGeoPosition & p) const; double elevation(const PIGeoPosition & p) const;
/// Computes the elevation of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system. //! \~english Compute geodetic elevation angle to target position
//! \~russian Вычислить геодезический угол возвышения до целевой позиции
//! \param p Target position
//! \return Elevation angle in degrees
double elevationGeodetic(const PIGeoPosition & p) const; double elevationGeodetic(const PIGeoPosition & p) const;
/// Computes the azimuth of the input (p) position as seen from this PIGeoPosition. //! \~english Compute azimuth angle to target position
//! \~russian Вычислить азимут до целевой позиции
//! \param p Target position
//! \return Azimuth angle in degrees
double azimuth(const PIGeoPosition & p) const; double azimuth(const PIGeoPosition & p) const;
/// Computes the azimuth of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system. //! \~english Compute geodetic azimuth angle to target position
//! \~russian Вычислить геодезический азимут до целевой позиции
//! \param p Target position
//! \return Azimuth angle in degrees
double azimuthGeodetic(const PIGeoPosition & p) const; double azimuthGeodetic(const PIGeoPosition & p) const;
/// Computes the radius of curvature of the meridian (Rm) corresponding to this PIGeoPosition. //! \~english Get radius of curvature of the meridian
//! \~russian Получить радиус кривизны меридиана
//! \return Radius in meters
double getCurvMeridian() const; double getCurvMeridian() const;
/// Computes the radius of curvature in the prime vertical (Rn) corresponding to this PIGeoPosition. //! \~english Get radius of curvature in the prime vertical
//! \~russian Получить радиус кривизны в вертикале
//! \return Radius in meters
double getCurvPrimeVertical() const; double getCurvPrimeVertical() const;
/// Returns as PIMathVectorT3d //! \~english Get as PIMathVectorT3d
//! \~russian Получить как PIMathVectorT3d
//! \return Reference to underlying vector
const PIMathVectorT3d & vector() const { return *this; } const PIMathVectorT3d & vector() const { return *this; }
//! \~english Assignment from vector
//! \~russian Присваивание из вектора
PIGeoPosition & operator=(const PIMathVectorT3d & v); PIGeoPosition & operator=(const PIMathVectorT3d & v);
//! \~english Subtraction
//! \~russian Вычитание
PIGeoPosition & operator-=(const PIGeoPosition & right); PIGeoPosition & operator-=(const PIGeoPosition & right);
//! \~english Addition
//! \~russian Сложение
PIGeoPosition & operator+=(const PIGeoPosition & right); PIGeoPosition & operator+=(const PIGeoPosition & right);
//! \~english Subtraction
//! \~russian Вычитание
friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right); friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Addition
//! \~russian Сложение
friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right); friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Scalar multiplication
//! \~russian Умножение на скаляр
friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right); friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale); friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale);
friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right); friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale); friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale);
//! \~english Equality comparison
//! \~russian Сравнение на равенство
bool operator==(const PIGeoPosition & right) const; bool operator==(const PIGeoPosition & right) const;
//! \~english Inequality comparison
//! \~russian Сравнение на неравенство
bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); } bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); }
@@ -181,6 +372,8 @@ private:
}; };
//! \~english Subtraction
//! \~russian Вычитание
inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right) { inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right); PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian); l.transformTo(PIGeoPosition::Cartesian);
@@ -188,6 +381,8 @@ inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition &
l -= r; l -= r;
return l; return l;
} }
//! \~english Addition
//! \~russian Сложение
inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right) { inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right); PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian); l.transformTo(PIGeoPosition::Cartesian);
@@ -195,17 +390,25 @@ inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition &
l += r; l += r;
return l; return l;
} }
//! \~english Scalar multiplication (double)
//! \~russian Умножение на скаляр (double)
inline PIGeoPosition operator*(const double & scale, const PIGeoPosition & right) { inline PIGeoPosition operator*(const double & scale, const PIGeoPosition & right) {
PIMathVectorT3d tmp(right); PIMathVectorT3d tmp(right);
tmp *= scale; tmp *= scale;
return PIGeoPosition(tmp); return PIGeoPosition(tmp);
} }
//! \~english Scalar multiplication (double)
//! \~russian Умножение на скаляр (double)
inline PIGeoPosition operator*(const PIGeoPosition & left, const double & scale) { inline PIGeoPosition operator*(const PIGeoPosition & left, const double & scale) {
return operator*(scale, left); return operator*(scale, left);
} }
//! \~english Scalar multiplication (int)
//! \~russian Умножение на скаляр (int)
inline PIGeoPosition operator*(const int & scale, const PIGeoPosition & right) { inline PIGeoPosition operator*(const int & scale, const PIGeoPosition & right) {
return operator*(double(scale), right); return operator*(double(scale), right);
} }
//! \~english Scalar multiplication (int)
//! \~russian Умножение на скаляр (int)
inline PIGeoPosition operator*(const PIGeoPosition & left, const int & scale) { inline PIGeoPosition operator*(const PIGeoPosition & left, const int & scale) {
return operator*(double(scale), left); return operator*(double(scale), left);
} }

View File

@@ -1,3 +1,14 @@
//! \addtogroup HTTP
//! \{
//! \file pihttpclient.h
//! \brief HTTP client implementation
//! \~english HTTP client for performing asynchronous HTTP requests with callbacks
//! \~russian HTTP клиент для выполнения асинхронных HTTP запросов с колбэками
//! \details
//! \~english Provides async HTTP client functionality using libcurl
//! \~russian Обеспечивает функциональность асинхронного HTTP клиента с использованием libcurl
//! \}
#ifndef pihttpclient_h #ifndef pihttpclient_h
#define pihttpclient_h #define pihttpclient_h
@@ -6,6 +17,8 @@
#include "pistringlist.h" #include "pistringlist.h"
//! \~english Base class for HTTP client internal functionality
//! \~russian Базовый класс для внутренней функциональности HTTP клиента
class PIHTTPClientBase { class PIHTTPClientBase {
public: public:
int __infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow); int __infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow);

View File

@@ -1,9 +1,23 @@
//! \addtogroup HTTP
//! \{
//! \file pihttpconstants.h
//! \brief HTTP constants and enumerations
//! \~english Definitions for HTTP methods, status codes and header names
//! \~russian Определения HTTP методов, кодов состояния и имен заголовков
//! \details
//! \~english Provides enum classes for HTTP methods and status codes, and a namespace with HTTP header name constants
//! \~russian Предоставляет классы перечислений для HTTP методов и кодов состояния, а также пространство имён с константами имён HTTP
//! заголовков
//! \}
#ifndef pihttpconstants_h #ifndef pihttpconstants_h
#define pihttpconstants_h #define pihttpconstants_h
namespace PIHTTP { namespace PIHTTP {
//! \~english HTTP request methods
//! \~russian HTTP методы запросов
enum class Method { enum class Method {
Unknown, Unknown,
Get, Get,
@@ -17,6 +31,8 @@ enum class Method {
Patch Patch
}; };
//! \~english HTTP response status codes
//! \~russian Коды состояния HTTP ответа
enum class Code { enum class Code {
Unknown = -1, Unknown = -1,
Continue = 100, Continue = 100,
@@ -90,6 +106,8 @@ enum class Code {
NetworkAuthenticationRequired = 511, NetworkAuthenticationRequired = 511,
}; };
//! \~english HTTP header field names
//! \~russian Имена полей заголовков HTTP
namespace Header { namespace Header {
constexpr static char Accept[] = "Accept"; constexpr static char Accept[] = "Accept";
constexpr static char AcceptCharset[] = "Accept-Charset"; constexpr static char AcceptCharset[] = "Accept-Charset";

View File

@@ -1,3 +1,14 @@
//! \addtogroup HTTP
//! \{
//! \file pihttptypes.h
//! \brief HTTP types and message classes
//! \~english HTTP message types and containers for requests and responses
//! \~russian Типы HTTP и классы сообщений для запросов и ответов
//! \details
//! \~english Provides MessageConst and MessageMutable classes for HTTP communication
//! \~russian Предоставляет классы MessageConst и MessageMutable для HTTP коммуникации
//! \}
#ifndef pihttptypes_h #ifndef pihttptypes_h
#define pihttptypes_h #define pihttptypes_h

View File

@@ -1,3 +1,14 @@
//! \addtogroup HTTP
//! \{
//! \file microhttpd_server.h
//! \brief Base HTTP server class
//! \~english Base HTTP server class using libmicrohttpd
//! \~russian Базовый класс HTTP сервера с использованием libmicrohttpd
//! \details
//! \~english Provides core HTTP server functionality with connection handling
//! \~russian Обеспечивает базовую функциональность HTTP сервера с обработкой соединений
//! \}
#ifndef MICROHTTPD_SERVER_P_H #ifndef MICROHTTPD_SERVER_P_H
#define MICROHTTPD_SERVER_P_H #define MICROHTTPD_SERVER_P_H
@@ -14,24 +25,28 @@ class PIP_HTTP_SERVER_EXPORT MicrohttpdServer: public PIObject {
friend struct MicrohttpdServerConnection; friend struct MicrohttpdServerConnection;
public: public:
//! \~english Constructs a new MicroHTTP server
//! \~russian Создает новый MicroHTTP сервер
MicrohttpdServer(); MicrohttpdServer();
//! \~english Destroys the MicroHTTP server
//! \~russian Уничтожает MicroHTTP сервер
virtual ~MicrohttpdServer(); virtual ~MicrohttpdServer();
//! \~english Server configuration options //! \~english Server configuration options
//! \~russian Опции конфигурации сервера //! \~russian Опции конфигурации сервера
enum class Option { enum class Option {
ConnectionLimit, //!< \~english Maximum concurrent connections ConnectionLimit, //!< \~english Maximum concurrent connections
//!< \~russian Максимальное количество соединений //!< \~russian Максимальное количество соединений
ConnectionTimeout, //!< \~english Connection timeout in seconds ConnectionTimeout, //!< \~english Connection timeout in seconds
//!< \~russian Таймаут соединения в секундах //!< \~russian Таймаут соединения в секундах
HTTPSEnabled, //!< \~english Enable HTTPS support HTTPSEnabled, //!< \~english Enable HTTPS support
//!< \~russian Включить поддержку HTTPS //!< \~russian Включить поддержку HTTPS
HTTPSMemKey, //!< \~english SSL key in memory (PIByteArray) HTTPSMemKey, //!< \~english SSL key in memory (PIByteArray)
//!< \~russian SSL ключ в памяти (PIByteArray) //!< \~russian SSL ключ в памяти (PIByteArray)
HTTPSMemCert, //!< \~english SSL certificate in memory (PIByteArray) HTTPSMemCert, //!< \~english SSL certificate in memory (PIByteArray)
//!< \~russian SSL сертификат в памяти (PIByteArray) //!< \~russian SSL сертификат в памяти (PIByteArray)
HTTPSKeyPassword //!< \~english SSL key password (PIByteArray) HTTPSKeyPassword //!< \~english SSL key password (PIByteArray)
//!< \~russian Пароль SSL ключа (PIByteArray) //!< \~russian Пароль SSL ключа (PIByteArray)
}; };
//! \~english Sets server option //! \~english Sets server option

View File

@@ -1,3 +1,14 @@
//! \addtogroup HTTP
//! \{
//! \file pihttpserver.h
//! \brief High-level HTTP server implementation
//! \~english High-level HTTP server with path-based routing and handler registration
//! \~russian Высокоуровневый HTTP сервер с маршрутизацией по путям и регистрацией обработчиков
//! \details
//! \~english Provides path-based request routing and handler management
//! \~russian Обеспечивает маршрутизацию запросов по путям и управление обработчиками
//! \}
#ifndef PIHTTPSERVER_H #ifndef PIHTTPSERVER_H
#define PIHTTPSERVER_H #define PIHTTPSERVER_H
@@ -9,7 +20,11 @@ class PIP_HTTP_SERVER_EXPORT PIHTTPServer: public MicrohttpdServer {
PIOBJECT_SUBCLASS(PIHTTPServer, MicrohttpdServer) PIOBJECT_SUBCLASS(PIHTTPServer, MicrohttpdServer)
public: public:
//! \~english Constructs a new HTTP server
//! \~russian Создает новый HTTP сервер
PIHTTPServer(); PIHTTPServer();
//! \~english Destroys the HTTP server
//! \~russian Уничтожает HTTP сервер
virtual ~PIHTTPServer(); virtual ~PIHTTPServer();
using RequestFunction = std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)>; using RequestFunction = std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)>;

View File

@@ -61,12 +61,17 @@ class PIIntrospection;
class PIIntrospectionServer; class PIIntrospectionServer;
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
//! \~english Declare singleton interface for introspection module T
//! \~russian Объявить интерфейс-синглтон для интроспекции модуля T
# define __PIINTROSPECTION_SINGLETON_H__(T) static PIIntrospection##T##Interface * instance(); # define __PIINTROSPECTION_SINGLETON_H__(T) static PIIntrospection##T##Interface * instance();
# define __PIINTROSPECTION_SINGLETON_CPP__(T) \ //! \~english Implement singleton interface for introspection module T
PIIntrospection##T##Interface * PIIntrospection##T##Interface::instance() { \ //! \~russian Реализовать интерфейс-синглтон для интроспекции модуля T
static PIIntrospection##T##Interface ret; \ # define __PIINTROSPECTION_SINGLETON_CPP__(T) \
return &ret; \ PIIntrospection##T##Interface * PIIntrospection##T##Interface::instance() { \
} static PIIntrospection##T##Interface ret; \
return &ret; \
}
#endif // PIP_INTROSPECTION #endif // PIP_INTROSPECTION
#endif // PIINTROSPECTION_BASE_H #endif // PIINTROSPECTION_BASE_H

View File

@@ -3,44 +3,67 @@
Introspection module - interface for containers Introspection module - interface for containers
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify 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 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 the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details. GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//! \addtogroup Introspection
//! \{
//! \file piintrospection_containers.h
//! \brief Container introspection
//! \~english Interface for container introspection and memory tracking
//! \~russian Интерфейс для интроспекции контейнеров и отслеживания памяти
//! \details
//! \~english Provides interface for tracking container memory allocations and usage
//! \~russian Предоставляет интерфейс для отслеживания выделения и использования памяти контейнерами
#ifndef PIINTROSPECTION_CONTAINERS_H #ifndef PIINTROSPECTION_CONTAINERS_H
#define PIINTROSPECTION_CONTAINERS_H # define PIINTROSPECTION_CONTAINERS_H
#include "pibase.h" # include "pibase.h"
//! \~english Container type information structure
//! \~russian Структура информации о типе контейнера
struct PIP_EXPORT PIIntrospectionContainersType { struct PIP_EXPORT PIIntrospectionContainersType {
~PIIntrospectionContainersType(); ~PIIntrospectionContainersType();
void finish(); void finish();
//! \~english Type identifier
//! \~russian Идентификатор типа
uint id = 0; uint id = 0;
//! \~english Type name
//! \~russian Имя типа
const char * name = nullptr; const char * name = nullptr;
//! \~english Demangled type name
//! \~russian Демангл-имя типа
const char * demangled = "?"; const char * demangled = "?";
//! \~english Initialization flag
//! \~russian Флаг инициализации
bool inited = false; bool inited = false;
//! \~english Has demangled name flag
//! \~russian Флаг наличия demangled имени
bool has_demangled = false; bool has_demangled = false;
}; };
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) # if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
# include "piintrospection_base.h" # include "piintrospection_base.h"
class PIIntrospectionContainers;
//! \~english Container type information template
//! \~russian Шаблон информации о типе контейнера
template<typename T> template<typename T>
class PIIntrospectionContainersTypeInfo { class PIIntrospectionContainersTypeInfo {
public: public:
//! \~english Get container type information
//! \~russian Получить информацию о типе контейнера
static const PIIntrospectionContainersType & get() { static const PIIntrospectionContainersType & get() {
static PIIntrospectionContainersType ret = create(); static PIIntrospectionContainersType ret = create();
return ret; return ret;
@@ -55,7 +78,7 @@ private:
} }
}; };
# define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance()) # define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())
// clang-format off // clang-format off
# define PIINTROSPECTION_CONTAINER_NEW(t, isz) PIINTROSPECTION_CONTAINERS->containerNew (PIIntrospectionContainersTypeInfo<t>::get(), isz); # define PIINTROSPECTION_CONTAINER_NEW(t, isz) PIINTROSPECTION_CONTAINERS->containerNew (PIIntrospectionContainersTypeInfo<t>::get(), isz);
@@ -67,6 +90,8 @@ private:
// clang-format on // clang-format on
//! \~english Container introspection interface
//! \~russian Интерфейс интроспекции контейнеров
class PIP_EXPORT PIIntrospectionContainersInterface { class PIP_EXPORT PIIntrospectionContainersInterface {
friend class PIIntrospection; friend class PIIntrospection;
friend class PIIntrospectionServer; friend class PIIntrospectionServer;
@@ -75,11 +100,23 @@ public:
__PIINTROSPECTION_SINGLETON_H__(Containers) __PIINTROSPECTION_SINGLETON_H__(Containers)
// clang-format off // clang-format off
//! \~english Notify about new container allocation
//! \~russian Уведомить о новом выделении контейнера
void containerNew (const PIIntrospectionContainersType & ti, uint isz); void containerNew (const PIIntrospectionContainersType & ti, uint isz);
//! \~english Notify about container deletion
//! \~russian Уведомить об удалении контейнера
void containerDelete(const PIIntrospectionContainersType & ti); void containerDelete(const PIIntrospectionContainersType & ti);
//! \~english Notify about container memory allocation
//! \~russian Уведомить о выделении памяти контейнером
void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt); void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Notify about container memory freeing
//! \~russian Уведомить об освобождении памяти контейнером
void containerFree (const PIIntrospectionContainersType & ti, ullong cnt); void containerFree (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Notify about container memory usage
//! \~russian Уведомить об использовании памяти контейнером
void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt); void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Notify about container unused memory
//! \~russian Уведомить о неиспользуемой памяти контейнера
void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt); void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt);
// clang-format on // clang-format on
@@ -91,14 +128,15 @@ private:
}; };
#else # else
# define PIINTROSPECTION_CONTAINER_NEW(t, isz) # define PIINTROSPECTION_CONTAINER_NEW(t, isz)
# define PIINTROSPECTION_CONTAINER_DELETE(t) # define PIINTROSPECTION_CONTAINER_DELETE(t)
# define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt) # define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt)
# define PIINTROSPECTION_CONTAINER_FREE(t, cnt) # define PIINTROSPECTION_CONTAINER_FREE(t, cnt)
# define PIINTROSPECTION_CONTAINER_USED(t, cnt) # define PIINTROSPECTION_CONTAINER_USED(t, cnt)
# define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) # define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt)
#endif # endif // defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#endif // PIINTROSPECTION_CONTAINERS_H #endif // PIINTROSPECTION_CONTAINERS_H
//! \}

View File

@@ -51,13 +51,23 @@ class PISystemMonitor;
# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name); # define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
# define PIINTROSPECTION_STOP PIINTROSPECTION_SERVER->stop(); # define PIINTROSPECTION_STOP PIINTROSPECTION_SERVER->stop();
//! \~english Introspection server class for collecting and broadcasting PIP internal statistics
//! \~russian Класс сервера интроспекции для сбора и распространения внутренних статистик PIP
class PIP_EXPORT PIIntrospectionServer: public PIPeer { class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer); PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer);
public: public:
//! \~english Get singleton instance of introspection server
//! \~russian Получить синглтон-экземпляр сервера интроспекции
static PIIntrospectionServer * instance(); static PIIntrospectionServer * instance();
//! \~english Start introspection server with specified name
//! \~russian Запустить сервер интроспекции с указанным именем
//! \param server_name \~english Name of the server to start \~russian Имя сервера для запуска
void start(const PIString & server_name); void start(const PIString & server_name);
//! \~english Stop introspection server
//! \~russian Остановить сервер интроспекции
void stop(); void stop();
private: private:

View File

@@ -17,25 +17,39 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//! \addtogroup Introspection
//! \{
//! \file piintrospection_threads.h
//! \brief Thread introspection interface
//! \~english Interface for thread introspection and monitoring
//! \~russian Интерфейс для интроспекции и мониторинга потоков
//! \details
//! \~english Provides callbacks for thread lifecycle events such as creation, deletion, start, run, wait, stop and completion
//! \~russian Предоставляет обратные вызовы для событий жизненного цикла потоков: создание, удаление, запуск, выполнение, ожидание,
//! остановка и завершение
//! \}
#ifndef PIINTROSPECTION_THREADS_H #ifndef PIINTROSPECTION_THREADS_H
#define PIINTROSPECTION_THREADS_H # define PIINTROSPECTION_THREADS_H
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) # if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
# include "piintrospection_base.h" # include "piintrospection_base.h"
class PIIntrospectionThreads; class PIIntrospectionThreads;
# define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance()) # define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance())
# define PIINTROSPECTION_THREAD_NEW(t) PIINTROSPECTION_THREADS->threadNew(t); # define PIINTROSPECTION_THREAD_NEW(t) PIINTROSPECTION_THREADS->threadNew(t);
# define PIINTROSPECTION_THREAD_DELETE(t) PIINTROSPECTION_THREADS->threadDelete(t); # define PIINTROSPECTION_THREAD_DELETE(t) PIINTROSPECTION_THREADS->threadDelete(t);
# define PIINTROSPECTION_THREAD_START(t) PIINTROSPECTION_THREADS->threadStart(t); # define PIINTROSPECTION_THREAD_START(t) PIINTROSPECTION_THREADS->threadStart(t);
# define PIINTROSPECTION_THREAD_RUN(t) PIINTROSPECTION_THREADS->threadRun(t); # define PIINTROSPECTION_THREAD_RUN(t) PIINTROSPECTION_THREADS->threadRun(t);
# define PIINTROSPECTION_THREAD_WAIT(t) PIINTROSPECTION_THREADS->threadWait(t); # define PIINTROSPECTION_THREAD_WAIT(t) PIINTROSPECTION_THREADS->threadWait(t);
# define PIINTROSPECTION_THREAD_STOP(t) PIINTROSPECTION_THREADS->threadStop(t); # define PIINTROSPECTION_THREAD_STOP(t) PIINTROSPECTION_THREADS->threadStop(t);
# define PIINTROSPECTION_THREAD_RUN_DONE(t, us) PIINTROSPECTION_THREADS->threadRunDone(t, us); # define PIINTROSPECTION_THREAD_RUN_DONE(t, us) PIINTROSPECTION_THREADS->threadRunDone(t, us);
//! \~english Thread introspection interface class
//! \~russian Класс интерфейса интроспекции потоков
class PIP_EXPORT PIIntrospectionThreadsInterface { class PIP_EXPORT PIIntrospectionThreadsInterface {
friend class PIIntrospection; friend class PIIntrospection;
@@ -43,12 +57,26 @@ public:
__PIINTROSPECTION_SINGLETON_H__(Threads) __PIINTROSPECTION_SINGLETON_H__(Threads)
// clang-format off // clang-format off
//! \~english Called when new thread is created
//! \~russian Вызывается при создании нового потока
void threadNew (PIThread * t); void threadNew (PIThread * t);
//! \~english Called when thread is deleted
//! \~russian Вызывается при удалении потока
void threadDelete (PIThread * t); void threadDelete (PIThread * t);
//! \~english Called when thread is starting
//! \~russian Вызывается при запуске потока
void threadStart (PIThread * t); void threadStart (PIThread * t);
//! \~english Called when thread starts execution
//! \~russian Вызывается при начале выполнения потока
void threadRun (PIThread * t); void threadRun (PIThread * t);
//! \~english Called when thread is waiting
//! \~russian Вызывается при ожидании потока
void threadWait (PIThread * t); void threadWait (PIThread * t);
//! \~english Called when thread is stopped
//! \~russian Вызывается при остановке потока
void threadStop (PIThread * t); void threadStop (PIThread * t);
//! \~english Called when thread execution is done
//! \~russian Вызывается при завершении выполнения потока
void threadRunDone(PIThread * t, ullong us); void threadRunDone(PIThread * t, ullong us);
// clang-format on // clang-format on
@@ -59,14 +87,15 @@ private:
PIIntrospectionThreads * p; PIIntrospectionThreads * p;
}; };
#else # else
# define PIINTROSPECTION_THREAD_NEW(t) # define PIINTROSPECTION_THREAD_NEW(t)
# define PIINTROSPECTION_THREAD_DELETE(t) # define PIINTROSPECTION_THREAD_DELETE(t)
# define PIINTROSPECTION_THREAD_START(t) # define PIINTROSPECTION_THREAD_START(t)
# define PIINTROSPECTION_THREAD_RUN(t) # define PIINTROSPECTION_THREAD_RUN(t)
# define PIINTROSPECTION_THREAD_WAIT(t) # define PIINTROSPECTION_THREAD_WAIT(t)
# define PIINTROSPECTION_THREAD_STOP(t) # define PIINTROSPECTION_THREAD_STOP(t)
# define PIINTROSPECTION_THREAD_RUN_DONE(t, us) # define PIINTROSPECTION_THREAD_RUN_DONE(t, us)
#endif # endif
#endif // PIINTROSPECTION_THREADS_H #endif // PIINTROSPECTION_THREADS_H
//! \}

View File

@@ -1,9 +1,13 @@
/*! \file pibinarylog.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file pibinarylog.h
* \~english Binary log //! \brief
* \~russian Бинарный лог //! \~english Binary log
*/ //! \~russian Бинарный лог
//! \details
//! \~english Class for writing and reading binary data to/from log files, with support for playback in different modes
//! \~russian Класс для записи и чтения бинарных данных в/из файлов логов с поддержкой воспроизведения в различных режимах
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for write binary data to logfile, and read or playback this data Class for write binary data to logfile, and read or playback this data
@@ -29,10 +33,8 @@
#include "pichunkstream.h" #include "pichunkstream.h"
#include "pifile.h" #include "pifile.h"
//! \ingroup IO //! \~english Class for writing and reading binary data to/from log files, with support for playback in different modes
//! \~\brief //! \~russian Класс для записи и чтения бинарных данных в/из файлов логов с поддержкой воспроизведения в различных режимах
//! \~english Binary log
//! \~russian Бинарный лог
class PIP_EXPORT PIBinaryLog: public PIIODevice { class PIP_EXPORT PIBinaryLog: public PIIODevice {
PIIODEVICE(PIBinaryLog, "binlog"); PIIODEVICE(PIBinaryLog, "binlog");
@@ -40,94 +42,147 @@ public:
explicit PIBinaryLog(); explicit PIBinaryLog();
virtual ~PIBinaryLog(); virtual ~PIBinaryLog();
//! \brief Play modes for \a PIBinaryLog //! \~english Play modes for \a PIBinaryLog
enum PlayMode { //! \~russian Режимы воспроизведения для \a PIBinaryLog
PlayRealTime /*! Play in system realtime, default mode */, enum PlayMode {
PlayVariableSpeed /*! Play in software realtime with speed, set by \a setSpeed */, PlayRealTime /*! \~english Play in system realtime, default mode \~russian В системном реальном времени, режим по умолчанию */,
PlayStaticDelay /*! Play with custom static delay, ignoring timestamp */ PlayVariableSpeed /*! \~english Play in software realtime with speed, set by \a setSpeed \~russian В программном реальном времени со скоростью, задаваемой через \a setSpeed */,
}; PlayStaticDelay /*! \~english Play with custom static delay, ignoring timestamp \~russian С пользовательской статической задержкой, игнорируя метку времени */
};
//! \brief Different split modes for writing \a PIBinaryLog, which can separate files by size, by time or by records count //! \~english Different split modes for writing \a PIBinaryLog, which can separate files by size, by time or by records count
enum SplitMode { //! \~russian Различные режимы разделения для записи \a PIBinaryLog, позволяющие разделять файлы по размеру, времени или количеству записей
SplitNone /*! Without separate, default mode */, enum SplitMode {
SplitTime /*! Separate files by record time */, SplitNone /*! \~english Without separate, default mode \~russian Без разделения, режим по умолчанию */,
SplitSize /*! Separate files by size */, SplitTime /*! \~english Separate files by record time \~russian Разделение файлов по времени записи */,
SplitCount /*! Separate files by records count */ SplitSize /*! \~english Separate files by size \~russian Разделение файлов по размеру */,
}; SplitCount /*! \~english Separate files by records count \~russian Разделение файлов по количеству записей */
};
#pragma pack(push, 8) #pragma pack(push, 8)
//! \brief Struct contains information about all records with same ID //! \~english Struct contains information about all records with same ID
struct PIP_EXPORT BinLogRecordInfo { //! \~russian Структура содержит информацию обо всех записях с одинаковым ID
BinLogRecordInfo() { struct PIP_EXPORT BinLogRecordInfo {
id = count = 0; //! \~english Constructor, initializes all fields to zero
minimum_size = maximum_size = 0; //! \~russian Конструктор, инициализирует все поля нулями
} BinLogRecordInfo() {
int id; id = count = 0;
int count; minimum_size = maximum_size = 0;
int minimum_size; }
int maximum_size; //! \~english Record ID
PISystemTime start_time; //! \~russian ID записи
PISystemTime end_time; int id;
}; //! \~english Records count
//! \~russian Количество записей
int count;
//! \~english Minimum record size
//! \~russian Минимальный размер записи
int minimum_size;
//! \~english Maximum record size
//! \~russian Максимальный размер записи
int maximum_size;
//! \~english Start time of records
//! \~russian Время начала записей
PISystemTime start_time;
//! \~english End time of records
//! \~russian Время окончания записей
PISystemTime end_time;
};
//! \brief Struct contains position, ID and timestamp of record in file //! \~english Struct contains position, ID and timestamp of record in file
struct PIP_EXPORT BinLogIndex { //! \~russian Структура содержит позицию, ID и метку времени записи в файле
int id; struct PIP_EXPORT BinLogIndex {
int data_size; //! \~english Record ID
llong pos; //! \~russian ID записи
PISystemTime timestamp; int id;
}; //! \~english Data size
//! \~russian Размер данных
int data_size;
//! \~english Position in file
//! \~russian Позиция в файле
llong pos;
//! \~english Timestamp
//! \~russian Метка времени
PISystemTime timestamp;
};
#pragma pack(pop) #pragma pack(pop)
//! \brief Struct contains full information about Binary Log file and about all Records using map of \a BinLogRecordInfo //! \~english Struct contains full information about Binary Log file and about all Records using map of \a BinLogRecordInfo
struct PIP_EXPORT BinLogInfo { //! \~russian Структура содержит полную информацию о файле бинарного лога и обо всех записях с использованием карты \a BinLogRecordInfo
PIString path; struct PIP_EXPORT BinLogInfo {
int records_count = 0; //! \~english Path to the log file
llong log_size = 0L; //! \~russian Путь к файлу лога
PISystemTime start_time; PIString path;
PISystemTime end_time; //! \~english Total records count
PIMap<int, BinLogRecordInfo> records; //! \~russian Общее количество записей
PIByteArray user_header; int records_count = 0;
}; //! \~english Log file size
//! \~russian Размер файла лога
llong log_size = 0L;
//! \~english Start time of logging
//! \~russian Время начала логирования
PISystemTime start_time;
//! \~english End time of logging
//! \~russian Время окончания логирования
PISystemTime end_time;
//! \~english Map of record information by ID
//! \~russian Карта информации о записях по ID
PIMap<int, BinLogRecordInfo> records;
//! \~english User-defined header data
//! \~russian Пользовательские данные заголовка
PIByteArray user_header;
};
//! Current \a PlayMode //! \~english Returns current \a PlayMode
PlayMode playMode() const { return play_mode; } //! \~russian Возвращает текущий \a PlayMode
PlayMode playMode() const { return play_mode; }
//! Current \a SplitMode //! \~english Returns current \a SplitMode
SplitMode splitMode() const { return split_mode; } //! \~russian Возвращает текущий \a SplitMode
SplitMode splitMode() const { return split_mode; }
//! Current directory where billogs wiil be saved //! \~english Returns current directory where binlogs will be saved
PIString logDir() const { return property("logDir").toString(); } //! \~russian Возвращает текущий каталог, куда будут сохраняться бинарные логи
PIString logDir() const { return property("logDir").toString(); }
//! Returns current file prefix //! \~english Returns current file prefix
PIString filePrefix() const { return property("filePrefix").toString(); } //! \~russian Возвращает текущий префикс файла
PIString filePrefix() const { return property("filePrefix").toString(); }
//! Default ID, used in \a write function //! \~english Returns default ID, used in \a write function
int defaultID() const { return default_id; } //! \~russian Возвращает ID по умолчанию, используемый в функции \a write
int defaultID() const { return default_id; }
//! Returns current play speed //! \~english Returns current play speed
double playSpeed() const { return play_speed > 0 ? 1. / play_speed : 0.; } //! \~russian Возвращает текущую скорость воспроизведения
double playSpeed() const { return play_speed > 0 ? 1. / play_speed : 0.; }
//! Returns current play delay //! \~english Returns current play delay
PISystemTime playDelay() const { return play_delay; } //! \~russian Возвращает текущую задержку воспроизведения
PISystemTime playDelay() const { return play_delay; }
//! Returns current binlog file split time //! \~english Returns current binlog file split time
PISystemTime splitTime() const { return split_time; } //! \~russian Возвращает текущее время разделения файла бинарного лога
PISystemTime splitTime() const { return split_time; }
//! Returns current binlog file split size //! \~english Returns current binlog file split size
llong splitFileSize() const { return split_size; } //! \~russian Возвращает текущий размер разделения файла бинарного лога
llong splitFileSize() const { return split_size; }
//! Returns current binlog file split records count //! \~english Returns current binlog file split records count
int splitRecordCount() const { return split_count; } //! \~russian Возвращает текущее количество записей для разделения файла бинарного лога
int splitRecordCount() const { return split_count; }
//! Returns if rapid start enabled //! \~english Returns if rapid start enabled
bool rapidStart() const { return rapid_start; } //! \~russian Возвращает, включено ли быстрое начало
bool rapidStart() const { return rapid_start; }
//! Returns if index creates while writing //! \~english Returns if index creates while writing
bool createIndexOnFly() const { return create_index_on_fly; } //! \~russian Возвращает, создается ли индекс во время записи
bool createIndexOnFly() const { return create_index_on_fly; }
//! Create binlog file with Filename = path //! Create binlog file with Filename = path
void createNewFile(const PIString & path); void createNewFile(const PIString & path);

View File

@@ -29,16 +29,36 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english CAN device.
//! \~russian Устройство CAN.
class PIP_EXPORT PICAN: public PIIODevice { class PIP_EXPORT PICAN: public PIIODevice {
PIIODEVICE(PICAN, "can"); PIIODEVICE(PICAN, "can");
public: public:
//! \~english Constructs %PICAN with empty path and ReadWrite mode
//! \~russian Создаёт %PICAN с пустым путём и режимом ReadWrite
explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PICAN(); virtual ~PICAN();
//! \~english Set CAN ID for filtering received messages
//! \~russian Устанавливает CAN ID для фильтрации принимаемых сообщений
void setCANID(int id); void setCANID(int id);
//! \~english Returns current CAN ID
//! \~russian Возвращает текущий CAN ID
int CANID() const; int CANID() const;
//! \~english Returns CAN ID of last readed message
//! \~russian Возвращает CAN ID последнего прочитанного сообщения
int readedCANID() const; int readedCANID() const;
//! \~english Interrupt blocking operation
//! \~russian Прерывает блокирующую операцию
void interrupt() override; void interrupt() override;
protected: protected:

View File

@@ -1,9 +1,13 @@
/*! \file piconfig.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file piconfig.h
* \~english Configuration files parser and writer //! \brief Configuration files parser and writer
* \~russian Разбор и запись конфигурационных файлов //! \~english Parser and writer for configuration files with tree structure support
*/ //! \~russian Разбор и запись конфигурационных файлов с поддержкой древовидной структуры
//! \details
//! \~english PIConfig provides functionality to read, write and manipulate configuration files in a tree-like structure.
//! \~russian PIConfig предоставляет функциональность для чтения, записи и управления конфигурационными файлами в древовидной структуре.
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Configuration parser and writer Configuration parser and writer
@@ -58,6 +62,8 @@
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);}
// clang-format on // clang-format on
//! \~english Main configuration parser and writer class
//! \~russian Главный класс для разбора и записи конфигурационных файлов
class PIP_EXPORT PIConfig { class PIP_EXPORT PIConfig {
friend class Entry; friend class Entry;
friend class Branch; friend class Branch;
@@ -79,6 +85,8 @@ public:
class Entry; class Entry;
//! \~english Branch class - container for Entry objects
//! \~russian Класс Branch - контейнер для объектов Entry
class PIP_EXPORT Branch: public PIVector<Entry *> { class PIP_EXPORT Branch: public PIVector<Entry *> {
friend class PIConfig; friend class PIConfig;
friend class Entry; friend class Entry;
@@ -90,22 +98,44 @@ public:
public: public:
Branch() { ; } Branch() { ; }
//! \~english Get value from branch by name with default value
//! \~russian Получить значение из ветки по имени со значением по умолчанию
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0);
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const { Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {
return const_cast<Branch *>(this)->getValue(vname, def, exists); return const_cast<Branch *>(this)->getValue(vname, def, exists);
} }
PICONFIG_GET_VALUE PICONFIG_GET_VALUE
//! \~english Get all leaf entries from the entire tree
//! \~russian Получить все листовые записи из всего дерева
Branch allLeaves(); Branch allLeaves();
//! \~english Get all entries with name containing specified substring
//! \~russian Получить все записи с именем, содержащим указанную подстроку
Branch getValues(const PIString & name); Branch getValues(const PIString & name);
//! \~english Get all leaf entries (entries without children)
//! \~russian Получить все листовые записи (записи без детей)
Branch getLeaves(); Branch getLeaves();
//! \~english Get all branch entries (entries with children)
//! \~russian Получить все ветвящиеся записи (записи с детьми)
Branch getBranches(); Branch getBranches();
//! \~english Filter branch by filter string
//! \~russian Фильтровать ветку по строке фильтра
Branch & filter(const PIString & f); Branch & filter(const PIString & f);
//! \~english Check if entry with specified name exists
//! \~russian Проверить, существует ли запись с указанным именем
bool isEntryExists(const PIString & name) const { bool isEntryExists(const PIString & name) const {
for (const auto * i: *this) for (const auto * i: *this)
if (entryExists(i, name)) return true; if (entryExists(i, name)) return true;
return false; return false;
} }
//! \~english Get index of entry in branch
//! \~russian Получить индекс записи в ветке
int indexOf(const Entry * e) { int indexOf(const Entry * e) {
for (int i = 0; i < size_s(); ++i) for (int i = 0; i < size_s(); ++i)
if (at(i) == e) return i; if (at(i) == e) return i;
@@ -138,6 +168,8 @@ public:
}; };
//! \~english Entry class - represents a single configuration entry
//! \~russian Класс Entry - представляет отдельную запись конфигурации
class PIP_EXPORT Entry { class PIP_EXPORT Entry {
friend class PIConfig; friend class PIConfig;
friend class Branch; friend class Branch;
@@ -446,18 +478,24 @@ public:
}; };
//! Read configuration from file at path "path" in mode "mode" //! \~english Open configuration from file at path in specified mode
//! \~russian Открыть конфигурацию из файла по указанному пути в указанном режиме
bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Read configuration from string "string" in mode "mode" //! \~english Open configuration from string in specified mode
//! \~russian Открыть конфигурацию из строки в указанном режиме
bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Read configuration from custom device "device" in mode "mode" //! \~english Open configuration from custom I/O device in specified mode
//! \~russian Открыть конфигурацию из пользовательского устройства ввода-вывода в указанном режиме
bool open(PIIODevice * device, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(PIIODevice * device, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Check if configuration is opened
//! \~russian Проверить, открыта ли конфигурация
bool isOpened() const; bool isOpened() const;
//! Returns top-level entry with name "vname", if doesn`t exists return entry with value "def" and set *exist to false //! \~english Get top-level entry by name with default value
//! \~russian Получить запись верхнего уровня по имени со значением по умолчанию
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0);
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const { Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {
return const_cast<PIConfig *>(this)->getValue(vname, def, exists); return const_cast<PIConfig *>(this)->getValue(vname, def, exists);
@@ -504,13 +542,16 @@ public:
//! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0) //! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0)
//! \brief Returns top-level entry with name "vname" and default value "def" //! \brief Returns top-level entry with name "vname" and default value "def"
//! \~english Get all top-level entries with name containing substring
//! Returns top-level entries with names with substrings "vname" //! \~russian Получить все записи верхнего уровня с именем, содержащим подстроку
Branch getValues(const PIString & vname); Branch getValues(const PIString & vname);
//! Set top-level entry with name "name" value to "value", type to "type" and if "write" immediate write to file. Add new entry if there //! \~english Set value for top-level entry with name
//! is no suitable exists //! \~russian Установить значение для записи верхнего уровня с именем
//! \details
//! \~english Set top-level entry with name "name" value to "value", type to "type" and if "write" immediate write to file.
//! Add new entry if there is no suitable exists
void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true);
//! Set top-level entry with name "name" value to "value", type to "l" and if "write" immediate write to file. Add new entry if there is //! Set top-level entry with name "name" value to "value", type to "l" and if "write" immediate write to file. Add new entry if there is
@@ -561,16 +602,20 @@ public:
//! no suitable exists //! no suitable exists
void setValue(const PIString & name, const double value, bool write = true) { setValue(name, PIString::fromNumber(value), "f", write); } void setValue(const PIString & name, const double value, bool write = true) { setValue(name, PIString::fromNumber(value), "f", write); }
//! Returns root entry //! \~english Get root entry of configuration tree
//! \~russian Получить корневую запись дерева конфигурации
Entry & rootEntry() { return root; } Entry & rootEntry() { return root; }
//! Returns top-level entries count //! \~english Get count of top-level entries
//! \~russian Получить количество записей верхнего уровня
int entriesCount() const { return childCount(&root); } int entriesCount() const { return childCount(&root); }
//! Returns if top-level entry with name "name" exists //! \~english Check if top-level entry with name exists
//! \~russian Проверить, существует ли запись верхнего уровня с указанным именем
bool isEntryExists(const PIString & name) const { return entryExists(&root, name); } bool isEntryExists(const PIString & name) const { return entryExists(&root, name); }
//! Returns all top-level entries //! \~english Get all top-level entries
//! \~russian Получить все записи верхнего уровня
Branch allTree() { Branch allTree() {
Branch b; Branch b;
for (auto * i: root._children) for (auto * i: root._children)
@@ -579,7 +624,8 @@ public:
return b; return b;
} }
//! Returns all entries without children //! \~english Get all entries without children (leaves)
//! \~russian Получить все записи без детей (листья)
Branch allLeaves() { Branch allLeaves() {
Branch b; Branch b;
allLeaves(b, &root); allLeaves(b, &root);
@@ -588,35 +634,71 @@ public:
return b; return b;
} }
//! \~english Get index of entry by name
//! \~russian Получить индекс записи по имени
int entryIndex(const PIString & name); int entryIndex(const PIString & name);
//! \~english Get entry name by index
//! \~russian Получить имя записи по индексу
PIString getName(uint number) { return entryByIndex(number)._name; } PIString getName(uint number) { return entryByIndex(number)._name; }
//! \~english Get entry value by index
//! \~russian Получить значение записи по индексу
PIString getValueByIndex(uint number) { return entryByIndex(number)._value; } PIString getValueByIndex(uint number) { return entryByIndex(number)._value; }
//! \~english Get entry type by index
//! \~russian Получить тип записи по индексу
PIChar getType(uint number) { return entryByIndex(number)._type[0]; } PIChar getType(uint number) { return entryByIndex(number)._type[0]; }
//! \~english Get entry comment by index
//! \~russian Получить комментарий записи по индексу
PIString getComment(uint number) { return entryByIndex(number)._comment; } PIString getComment(uint number) { return entryByIndex(number)._comment; }
//! \~english Add new entry with name, value and type
//! \~russian Добавить новую запись с именем, значением и типом
void addEntry(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); void addEntry(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true);
//! \~english Set name of entry by index
//! \~russian Установить имя записи по индексу
void setName(uint number, const PIString & name, bool write = true); void setName(uint number, const PIString & name, bool write = true);
//! \~english Set value of entry by index
//! \~russian Установить значение записи по индексу
void setValue(uint number, const PIString & value, bool write = true); void setValue(uint number, const PIString & value, bool write = true);
//! \~english Set type of entry by index
//! \~russian Установить тип записи по индексу
void setType(uint number, const PIString & type, bool write = true); void setType(uint number, const PIString & type, bool write = true);
//! \~english Set comment of entry by index
//! \~russian Установить комментарий записи по индексу
void setComment(uint number, const PIString & comment, bool write = true); void setComment(uint number, const PIString & comment, bool write = true);
//! \~english Remove entry by name
//! \~russian Удалить запись по имени
void removeEntry(const PIString & name, bool write = true); void removeEntry(const PIString & name, bool write = true);
//! \~english Remove entry by index
//! \~russian Удалить запись по индексу
void removeEntry(uint number, bool write = true); void removeEntry(uint number, bool write = true);
//! Remove all tree and device content //! Remove all tree and device content
void clear(); void clear();
//! Parse device and build internal tree //! \~english Parse device and build internal tree
//! \~russian Прочитать устройство и построить внутреннее дерево
void readAll(); void readAll();
//! Write all internal tree to device //! \~english Write all internal tree to device
//! \~russian Записать всё внутреннее дерево в устройство
void writeAll(); void writeAll();
//! Returns current tree delimiter, default "." //! \~english Get current tree delimiter
//! \~russian Получить текущий разделитель дерева
const PIString & delimiter() const { return delim; } const PIString & delimiter() const { return delim; }
//! Set current tree delimiter //! \~english Set tree delimiter
//! \~russian Установить разделитель дерева
void setDelimiter(const PIString & d) { void setDelimiter(const PIString & d) {
delim = d; delim = d;
setEntryDelim(&root, d); setEntryDelim(&root, d);
@@ -708,14 +790,18 @@ inline PICout operator<<(PICout s, const PIConfig::Entry & v) {
} }
/** \relatesalso PIConfig \relatesalso PIIODevice //! \~english Service function for reading device settings from configuration
* \brief Service function. useful for configuring devices //! \~russian Сервисная функция для чтения настроек устройства из конфигурации
* \details Function takes entry name "name", default value "def" and two //! \note
* \a PIConfig::Entry sections: "em" and their parent "ep". If there is no //! \~english Useful for implementing PIIODevice::configureDevice()
* parent ep = 0. If "ep" is not null and entry "name" exists in "ep" function //! \~russian Полезно для реализации PIIODevice::configureDevice()
* returns this value. Else returns value of entry "name" in section "em" or //! \~\details Function takes entry name "name", default value "def" and two
* "def" if entry doesn`t exists. \n This function useful to read settings //! \a PIConfig::Entry sections: "em" and their parent "ep". If there is no
* from configuration file in implementation \a PIIODevice::configureDevice() function */ //! parent ep = 0. If "ep" is not null and entry "name" exists in "ep" function
//! returns this value. Else returns value of entry "name" in section "em" or
//! "def" if entry doesn`t exists. \n This function useful to read settings
//! from configuration file in implementation \a PIIODevice::configureDevice() function
//! \relatesalso PIConfig \relatesalso PIIODevice
template<typename T> template<typename T>
T readDeviceSetting(const PIString & name, const T & def, const PIConfig::Entry * em, const PIConfig::Entry * ep) { T readDeviceSetting(const PIString & name, const T & def, const PIConfig::Entry * em, const PIConfig::Entry * ep) {
PIVariant v = PIVariant::fromValue<T>(def); PIVariant v = PIVariant::fromValue<T>(def);

View File

@@ -76,30 +76,40 @@ public:
//! Set read address //! Set read address
//! \~english Set read address
//! \~russian Устанавливает адрес для чтения
void setReadAddress(const PIString & ip, int port) { void setReadAddress(const PIString & ip, int port) {
addr_r.set(ip, port); addr_r.set(ip, port);
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read address in format "i.i.i.i:p" //! Set read address in format "i.i.i.i:p"
//! \~english Set read address in format "i.i.i.i:p"
//! \~russian Устанавливает адрес для чтения в формате "i.i.i.i:p"
void setReadAddress(const PIString & ip_port) { void setReadAddress(const PIString & ip_port) {
addr_r.set(ip_port); addr_r.set(ip_port);
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read address //! Set read address
//! \~english Set read address
//! \~russian Устанавливает адрес для чтения
void setReadAddress(const PINetworkAddress & addr) { void setReadAddress(const PINetworkAddress & addr) {
addr_r = addr; addr_r = addr;
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read IP //! Set read IP
//! \~english Set read IP
//! \~russian Устанавливает IP для чтения
void setReadIP(const PIString & ip) { void setReadIP(const PIString & ip) {
addr_r.setIP(ip); addr_r.setIP(ip);
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read port //! Set read port
//! \~english Set read port
//! \~russian Устанавливает порт для чтения
void setReadPort(int port) { void setReadPort(int port) {
addr_r.setPort(port); addr_r.setPort(port);
setPath(addr_r.toString()); setPath(addr_r.toString());
@@ -153,12 +163,16 @@ public:
//! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them //! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
//! \~english Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
//! \~russian Устанавливает параметры "parameters_". Необходимо переоткрыть %PIEthernet для применения
void setParameters(PIFlags<PIEthernet::Parameters> parameters_) { void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {
params = parameters_; params = parameters_;
applyParameters(); applyParameters();
} }
//! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this //! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this
//! \~english Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this
//! \~russian Устанавливает параметр "parameter" в состояние "on". Необходимо переоткрыть %PIEthernet для применения
void setParameter(PIEthernet::Parameters parameter, bool on = true) { void setParameter(PIEthernet::Parameters parameter, bool on = true) {
params.setFlag(parameter, on); params.setFlag(parameter, on);
applyParameters(); applyParameters();
@@ -222,18 +236,24 @@ public:
bool connect(bool threaded = true); bool connect(bool threaded = true);
//! Connect to TCP server with address "ip":"port". Use only for TCP_Client //! Connect to TCP server with address "ip":"port". Use only for TCP_Client
//! \~english Connect to TCP server with address "ip":"port". Use only for TCP_Client
//! \~russian Подключается к TCP серверу по адресу "ip":"port". Только для TCP_Client
bool connect(const PIString & ip, int port, bool threaded = true) { bool connect(const PIString & ip, int port, bool threaded = true) {
setPath(ip + PIStringAscii(":") + PIString::fromNumber(port)); setPath(ip + PIStringAscii(":") + PIString::fromNumber(port));
return connect(threaded); return connect(threaded);
} }
//! Connect to TCP server with address "ip_port". Use only for TCP_Client //! Connect to TCP server with address "ip_port". Use only for TCP_Client
//! \~english Connect to TCP server with address "ip_port". Use only for TCP_Client
//! \~russian Подключается к TCP серверу по адресу "ip_port". Только для TCP_Client
bool connect(const PIString & ip_port, bool threaded = true) { bool connect(const PIString & ip_port, bool threaded = true) {
setPath(ip_port); setPath(ip_port);
return connect(threaded); return connect(threaded);
} }
//! Connect to TCP server with address "addr". Use only for TCP_Client //! Connect to TCP server with address "addr". Use only for TCP_Client
//! \~english Connect to TCP server with address "addr". Use only for TCP_Client
//! \~russian Подключается к TCP серверу по адресу "addr". Только для TCP_Client
bool connect(const PINetworkAddress & addr, bool threaded = true) { bool connect(const PINetworkAddress & addr, bool threaded = true) {
setPath(addr.toString()); setPath(addr.toString());
return connect(threaded); return connect(threaded);
@@ -269,11 +289,15 @@ public:
bool send(const void * data, int size, bool threaded = false); bool send(const void * data, int size, bool threaded = false);
//! Send data "data" with size "size" to address "ip":"port" //! Send data "data" with size "size" to address "ip":"port"
//! \~english Send data "data" with size "size" to address "ip":"port"
//! \~russian Отправляет данные "data" размером "size" на адрес "ip":"port"
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) { bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {
return send(PINetworkAddress(ip, port), data, size, threaded); return send(PINetworkAddress(ip, port), data, size, threaded);
} }
//! Send data "data" with size "size" to address "ip_port" //! Send data "data" with size "size" to address "ip_port"
//! \~english Send data "data" with size "size" to address "ip_port"
//! \~russian Отправляет данные "data" размером "size" на адрес "ip_port"
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) { bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {
return send(PINetworkAddress(ip_port), data, size, threaded); return send(PINetworkAddress(ip_port), data, size, threaded);
} }
@@ -285,11 +309,15 @@ public:
bool send(const PIByteArray & data, bool threaded = false); bool send(const PIByteArray & data, bool threaded = false);
//! Send data "data" to address "ip":"port" for UDP //! Send data "data" to address "ip":"port" for UDP
//! \~english Send data "data" to address "ip":"port" for UDP
//! \~russian Отправляет данные "data" на адрес "ip":"port" для UDP
bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) { bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {
return send(PINetworkAddress(ip, port), data, threaded); return send(PINetworkAddress(ip, port), data, threaded);
} }
//! Send data "data" to address "ip_port" for UDP //! Send data "data" to address "ip_port" for UDP
//! \~english Send data "data" to address "ip_port" for UDP
//! \~russian Отправляет данные "data" на адрес "ip_port" для UDP
bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) { bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {
return send(PINetworkAddress(ip_port), data, threaded); return send(PINetworkAddress(ip_port), data, threaded);
} }

View File

@@ -56,26 +56,20 @@ typedef std::function<bool(const uchar *, int, void *)> ReadRetFunc;
#else #else
# define REGISTER_DEVICE(name) \ # define REGISTER_DEVICE(name) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIIODevice::registerDevice(name::fullPathPrefixS(), #name, []() -> PIIODevice * { return new name(); }); \ PIIODevice::registerDevice(name::fullPathPrefixS(), #name, []() -> PIIODevice * { return new name(); }); \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
# define PIIODEVICE(name, prefix) \ # define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \ PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const override { \ PIIODevice * copy() const override { return new name(); } \
return new name(); \ \
} \ public: \
\ PIConstChars fullPathPrefix() const override { return prefix; } \
public: \ static PIConstChars fullPathPrefixS() { return prefix; } \
PIConstChars fullPathPrefix() const override { \ \
return prefix; \ private:
} \
static PIConstChars fullPathPrefixS() { \
return prefix; \
} \
\
private:
#endif #endif

View File

@@ -49,11 +49,15 @@ public:
resetReadError(); resetReadError();
} }
//! \~english Append data to stream
//! \~russian Добавляет данные в поток
bool binaryStreamAppendImp(const void * d, size_t s) { bool binaryStreamAppendImp(const void * d, size_t s) {
if (!dev) return false; if (!dev) return false;
return (dev->write(d, s) == (int)s); return (dev->write(d, s) == (int)s);
} }
//! \~english Take data from stream
//! \~russian Извлекает данные из потока
bool binaryStreamTakeImp(void * d, size_t s) { bool binaryStreamTakeImp(void * d, size_t s) {
if (!dev) return false; if (!dev) return false;
return (dev->read(d, s) == (int)s); return (dev->read(d, s) == (int)s);
@@ -90,6 +94,8 @@ public:
if (io_string) delete io_string; if (io_string) delete io_string;
} }
//! \~english Assign "device" device
//! \~russian Назначает устройство "device"
void setDevice(PIIODevice * device) { void setDevice(PIIODevice * device) {
bin_stream = PIIOBinaryStream(device); bin_stream = PIIOBinaryStream(device);
setStream(&bin_stream); setStream(&bin_stream);

View File

@@ -29,6 +29,10 @@
#include "pidiagnostics.h" #include "pidiagnostics.h"
#include "piethernet.h" #include "piethernet.h"
//! \ingroup IO
//! \~\brief
//! \~english Peering net node.
//! \~russian Элемент пиринговой сети.
class PIP_EXPORT PIPeer: public PIIODevice { class PIP_EXPORT PIPeer: public PIIODevice {
PIIODEVICE(PIPeer, "peer"); PIIODEVICE(PIPeer, "peer");
@@ -36,9 +40,16 @@ private:
class PeerData; class PeerData;
public: public:
//! \~english Constructs %PIPeer with name "name"
//! \~russian Создаёт %PIPeer с именем "name"
explicit PIPeer(const PIString & name = PIString()); explicit PIPeer(const PIString & name = PIString());
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIPeer(); virtual ~PIPeer();
//! \~english Peer information structure
//! \~russian Структура информации о пире
class PIP_EXPORT PeerInfo { class PIP_EXPORT PeerInfo {
friend class PIPeer; friend class PIPeer;
BINARY_STREAM_FRIEND(PIPeer::PeerInfo); BINARY_STREAM_FRIEND(PIPeer::PeerInfo);
@@ -87,38 +98,89 @@ public:
BINARY_STREAM_FRIEND(PIPeer::PeerInfo); BINARY_STREAM_FRIEND(PIPeer::PeerInfo);
//! \~english Send data to peer with name "to"
//! \~russian Отправляет данные пиру с именем "to"
bool send(const PIString & to, const PIByteArray & data) { return send(to, data.data(), data.size_s()); } bool send(const PIString & to, const PIByteArray & data) { return send(to, data.data(), data.size_s()); }
//! \~english Send string to peer with name "to"
//! \~russian Отправляет строку пиру с именем "to"
bool send(const PIString & to, const PIString & data) { return send(to, data.data(), data.size_s()); } bool send(const PIString & to, const PIString & data) { return send(to, data.data(), data.size_s()); }
bool send(const PIString & to, const void * data, int size); bool send(const PIString & to, const void * data, int size);
//! \~english Send data to peer "to"
//! \~russian Отправляет данные пиру "to"
bool send(const PeerInfo & to, const PIByteArray & data) { return send(to.name, data.data(), data.size_s()); } bool send(const PeerInfo & to, const PIByteArray & data) { return send(to.name, data.data(), data.size_s()); }
bool send(const PeerInfo & to, const PIString & data) { return send(to.name, data.data(), data.size_s()); } bool send(const PeerInfo & to, const PIString & data) { return send(to.name, data.data(), data.size_s()); }
bool send(const PeerInfo & to, const void * data, int size) { return send(to.name, data, size); } bool send(const PeerInfo & to, const void * data, int size) { return send(to.name, data, size); }
bool send(const PeerInfo * to, const PIByteArray & data); bool send(const PeerInfo * to, const PIByteArray & data);
bool send(const PeerInfo * to, const PIString & data); bool send(const PeerInfo * to, const PIString & data);
bool send(const PeerInfo * to, const void * data, int size); bool send(const PeerInfo * to, const void * data, int size);
//! \~english Send data to all peers
//! \~russian Отправляет данные всем пирам
void sendToAll(const PIByteArray & data); void sendToAll(const PIByteArray & data);
void sendToAll(const PIString & data); void sendToAll(const PIString & data);
void sendToAll(const void * data, int size); void sendToAll(const void * data, int size);
//! \~english Returns if receiving multicast packets is enabled
//! \~russian Возвращает включён ли приём мультикаст пакетов
bool isMulticastReceive() const { return !eths_mcast.isEmpty(); } bool isMulticastReceive() const { return !eths_mcast.isEmpty(); }
//! \~english Returns if receiving broadcast packets is enabled
//! \~russian Возвращает включён ли приём широковещательных пакетов
bool isBroadcastReceive() const { return !eths_bcast.isEmpty(); } bool isBroadcastReceive() const { return !eths_bcast.isEmpty(); }
//! \~english Returns diagnostic service
//! \~russian Возвращает диагностический сервис
PIDiagnostics & diagnosticService() { return diag_s; } PIDiagnostics & diagnosticService() { return diag_s; }
//! \~english Returns diagnostic data
//! \~russian Возвращает диагностические данные
PIDiagnostics & diagnosticData() { return diag_d; } PIDiagnostics & diagnosticData() { return diag_d; }
//! \~english Returns all known peers
//! \~russian Возвращает всех известных пиров
const PIVector<PIPeer::PeerInfo> & allPeers() const { return peers; } const PIVector<PIPeer::PeerInfo> & allPeers() const { return peers; }
//! \~english Returns if peer with name "name" exists
//! \~russian Возвращает существует ли пир с именем "name"
bool isPeerExists(const PIString & name) const { return getPeerByName(name) != 0; } bool isPeerExists(const PIString & name) const { return getPeerByName(name) != 0; }
//! \~english Returns peer info by name, or nullptr if not found
//! \~russian Возвращает информацию о пире по имени, или nullptr если не найден
const PeerInfo * getPeerByName(const PIString & name) const { return peers_map.value(name, 0); } const PeerInfo * getPeerByName(const PIString & name) const { return peers_map.value(name, 0); }
//! \~english Returns self info
//! \~russian Возвращает информацию о себе
const PeerInfo & selfInfo() const { return self_info; } const PeerInfo & selfInfo() const { return self_info; }
const PIMap<PIString, PIVector<PeerInfo *>> & _peerMap() const { return addresses_map; } const PIMap<PIString, PIVector<PeerInfo *>> & _peerMap() const { return addresses_map; }
//! \~english Reinitialize peer network
//! \~russian Переинициализирует пиринговую сеть
void reinit(); void reinit();
//! \~english Lock peers list
//! \~russian Блокирует список пиров
void lock() { peers_mutex.lock(); } void lock() { peers_mutex.lock(); }
//! \~english Unlock peers list
//! \~russian Разблокирует список пиров
void unlock() { peers_mutex.unlock(); } void unlock() { peers_mutex.unlock(); }
//! \~english Change peer name to "new_name"
//! \~russian Изменяет имя пира на "new_name"
void changeName(const PIString & new_name); void changeName(const PIString & new_name);
//! \~english Returns trusted peer name
//! \~russian Возвращает имя доверенного пира
const PIString & trustPeerName() const { return trust_peer; } const PIString & trustPeerName() const { return trust_peer; }
//! \~english Set trusted peer name
//! \~russian Устанавливает имя доверенного пира
void setTrustPeerName(const PIString & peer_name) { trust_peer = peer_name; } void setTrustPeerName(const PIString & peer_name) { trust_peer = peer_name; }
//! \~english Set TCP server IP address
//! \~russian Устанавливает IP адрес TCP сервера
void setTcpServerIP(const PIString & ip); void setTcpServerIP(const PIString & ip);
ssize_t bytesAvailable() const override; ssize_t bytesAvailable() const override;

View File

@@ -216,6 +216,8 @@ public:
//! \~russian Переключает состояние передачи в break //! \~russian Переключает состояние передачи в break
bool setBreak(bool enabled); bool setBreak(bool enabled);
//! \~english Set VTime parameter
//! \~russian Устанавливает параметр VTime
void setVTime(int t) { void setVTime(int t) {
vtime = t; vtime = t;
applySettings(); applySettings();

View File

@@ -29,35 +29,59 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english SPI device.
//! \~russian Устройство SPI.
class PIP_EXPORT PISPI: public PIIODevice { class PIP_EXPORT PISPI: public PIIODevice {
PIIODEVICE(PISPI, "spi"); PIIODEVICE(PISPI, "spi");
public: public:
//! \~english Constructs %PISPI with path "path", speed "speed_hz" and mode "mode"
//! \~russian Создаёт %PISPI с путём "path", скоростью "speed_hz" и режимом "mode"
explicit PISPI(const PIString & path = PIString(), uint speed_hz = 1000000, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PISPI(const PIString & path = PIString(), uint speed_hz = 1000000, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PISPI(); virtual ~PISPI();
//! \brief Parameters of PISPI //! \~english Parameters of PISPI
//! \~russian Параметры PISPI
enum Parameters { enum Parameters {
ClockInverse /*! SPI clk polarity control*/ = 0x1, ClockInverse /*! \~english SPI clk polarity control \~russian Управление полярностью SPI clk */ = 0x1,
ClockPhaseShift /*! SPI clk phase control */ = 0x2, ClockPhaseShift /*! \~english SPI clk phase control \~russian Управление фазой SPI clk */ = 0x2,
}; };
//! \~english Set SPI speed in Hz
//! \~russian Устанавливает скорость SPI в Гц
void setSpeed(uint speed_hz); void setSpeed(uint speed_hz);
//! \~english Returns current SPI speed in Hz
//! \~russian Возвращает текущую скорость SPI в Гц
uint speed() const { return spi_speed; } uint speed() const { return spi_speed; }
//! \~english Set number of bits per word, default is 8
//! \~russian Устанавливает количество бит на слово, по умолчанию 8
void setBits(uchar bits = 8); void setBits(uchar bits = 8);
//! \~english Returns number of bits per word
//! \~russian Возвращает количество бит на слово
uchar bits() const { return spi_bits; } uchar bits() const { return spi_bits; }
//! Set parameters to "parameters_" //! \~english Set parameters to "parameters_"
//! \~russian Устанавливает параметры в "parameters_"
void setParameters(PIFlags<PISPI::Parameters> parameters_) { spi_mode = (int)parameters_; } void setParameters(PIFlags<PISPI::Parameters> parameters_) { spi_mode = (int)parameters_; }
//! Set parameter "parameter" to "on" state //! \~english Set parameter "parameter" to "on" state
//! \~russian Устанавливает параметр "parameter" в состояние "on"
void setParameter(PISPI::Parameters parameter, bool on = true); void setParameter(PISPI::Parameters parameter, bool on = true);
//! Returns if parameter "parameter" is set //! \~english Returns if parameter "parameter" is set
//! \~russian Возвращает установлен ли параметр "parameter"
bool isParameterSet(PISPI::Parameters parameter) const; bool isParameterSet(PISPI::Parameters parameter) const;
//! Returns parameters //! \~english Returns parameters
//! \~russian Возвращает параметры
PIFlags<PISPI::Parameters> parameters() const { return spi_mode; } PIFlags<PISPI::Parameters> parameters() const { return spi_mode; }
ssize_t bytesAvailable() const override; ssize_t bytesAvailable() const override;

View File

@@ -62,13 +62,24 @@
struct usb_dev_handle; struct usb_dev_handle;
//! \ingroup IO
//! \~\brief
//! \~english USB device.
//! \~russian Устройство USB.
class PIP_USB_EXPORT PIUSB: public PIIODevice { class PIP_USB_EXPORT PIUSB: public PIIODevice {
PIIODEVICE(PIUSB, "usb"); PIIODEVICE(PIUSB, "usb");
public: public:
//! \~english Constructs %PIUSB with vendor ID "vid" and product ID "pid"
//! \~russian Создаёт %PIUSB с идентификатором поставщика "vid" и идентификатором продукта "pid"
explicit PIUSB(ushort vid = 0, ushort pid = 0); explicit PIUSB(ushort vid = 0, ushort pid = 0);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIUSB(); virtual ~PIUSB();
//! \~english USB endpoint structure
//! \~russian Структура USB endpoint
struct PIP_USB_EXPORT Endpoint { struct PIP_USB_EXPORT Endpoint {
Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) { Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) {
address = a; address = a;
@@ -111,6 +122,8 @@ public:
UsageType usage_type = DataEndpoint; UsageType usage_type = DataEndpoint;
}; };
//! \~english USB interface structure
//! \~russian Структура USB интерфейса
struct PIP_USB_EXPORT Interface { struct PIP_USB_EXPORT Interface {
uchar index = 0; uchar index = 0;
uchar value_to_select = 0; uchar value_to_select = 0;
@@ -120,6 +133,8 @@ public:
PIVector<PIUSB::Endpoint> endpoints; PIVector<PIUSB::Endpoint> endpoints;
}; };
//! \~english USB configuration structure
//! \~russian Структура USB конфигурации
struct PIP_USB_EXPORT Configuration { struct PIP_USB_EXPORT Configuration {
uchar index = 0; uchar index = 0;
uchar value_to_select = 0; uchar value_to_select = 0;
@@ -130,6 +145,8 @@ public:
PIVector<PIUSB::Interface> interfaces; PIVector<PIUSB::Interface> interfaces;
}; };
//! \~english USB device descriptor structure
//! \~russian Структура дескриптора USB устройства
struct PIP_USB_EXPORT Descriptor { struct PIP_USB_EXPORT Descriptor {
ushort usb_spec_number = 0; ushort usb_spec_number = 0;
uchar device_class = 0; uchar device_class = 0;
@@ -145,36 +162,100 @@ public:
PIVector<PIUSB::Configuration> configurations; PIVector<PIUSB::Configuration> configurations;
}; };
//! \~english Returns current device descriptor
//! \~russian Возвращает текущий дескриптор устройства
const PIUSB::Descriptor & currentDescriptor() const { return desc_; } const PIUSB::Descriptor & currentDescriptor() const { return desc_; }
//! \~english Returns current configuration
//! \~russian Возвращает текущую конфигурацию
const PIUSB::Configuration & currentConfiguration() const { return conf_; } const PIUSB::Configuration & currentConfiguration() const { return conf_; }
//! \~english Returns current interface
//! \~russian Возвращает текущий интерфейс
const PIUSB::Interface & currentInterface() const { return iface_; } const PIUSB::Interface & currentInterface() const { return iface_; }
//! \~english Returns vendor ID
//! \~russian Возвращает ID поставщика
ushort vendorID() const { return vid_; } ushort vendorID() const { return vid_; }
//! \~english Returns product ID
//! \~russian Возвращает ID продукта
ushort productID() const { return pid_; } ushort productID() const { return pid_; }
//! \~english Returns device number
//! \~russian Возвращает номер устройства
int deviceNumber() const { return property("deviceNumber").toInt(); } int deviceNumber() const { return property("deviceNumber").toInt(); }
//! \~english Returns read timeout in milliseconds
//! \~russian Возвращает таймаут чтения в миллисекундах
int timeoutRead() const { return property("timeoutRead").toInt(); } int timeoutRead() const { return property("timeoutRead").toInt(); }
//! \~english Returns write timeout in milliseconds
//! \~russian Возвращает таймаут записи в миллисекундах
int timeoutWrite() const { return property("timeoutWrite").toInt(); } int timeoutWrite() const { return property("timeoutWrite").toInt(); }
//! \~english Returns read endpoint
//! \~russian Возвращает endpoint для чтения
const PIUSB::Endpoint & endpointRead() const { return ep_read; } const PIUSB::Endpoint & endpointRead() const { return ep_read; }
//! \~english Returns write endpoint
//! \~russian Возвращает endpoint для записи
const PIUSB::Endpoint & endpointWrite() const { return ep_write; } const PIUSB::Endpoint & endpointWrite() const { return ep_write; }
//! \~english Returns all endpoints
//! \~russian Возвращает все endpoints
const PIVector<PIUSB::Endpoint> & endpoints() const { return eps; } const PIVector<PIUSB::Endpoint> & endpoints() const { return eps; }
//! \~english Returns read endpoints
//! \~russian Возвращает endpoints для чтения
PIVector<PIUSB::Endpoint> endpointsRead(); PIVector<PIUSB::Endpoint> endpointsRead();
//! \~english Returns write endpoints
//! \~russian Возвращает endpoints для записи
PIVector<PIUSB::Endpoint> endpointsWrite(); PIVector<PIUSB::Endpoint> endpointsWrite();
//! \~english Returns endpoint by address
//! \~russian Возвращает endpoint по адресу
PIUSB::Endpoint getEndpointByAddress(uchar address); PIUSB::Endpoint getEndpointByAddress(uchar address);
//! \~english Set vendor ID to "vid"
//! \~russian Устанавливает ID поставщика в "vid"
void setVendorID(ushort vid); void setVendorID(ushort vid);
//! \~english Set product ID to "pid"
//! \~russian Устанавливает ID продукта в "pid"
void setProductID(ushort pid); void setProductID(ushort pid);
//! \~english Set configuration by value
//! \~russian Устанавливает конфигурацию по значению
bool setConfiguration(uchar value); bool setConfiguration(uchar value);
//! \~english Set interface by value
//! \~russian Устанавливает интерфейс по значению
bool setInterface(uchar value); bool setInterface(uchar value);
//! \~english Set read endpoint
//! \~russian Устанавливает endpoint для чтения
void setEndpointRead(const PIUSB::Endpoint & ep) { ep_read = ep; } void setEndpointRead(const PIUSB::Endpoint & ep) { ep_read = ep; }
//! \~english Set write endpoint
//! \~russian Устанавливает endpoint для записи
void setEndpointWrite(const PIUSB::Endpoint & ep) { ep_write = ep; } void setEndpointWrite(const PIUSB::Endpoint & ep) { ep_write = ep; }
//! \~english Set device number
//! \~russian Устанавливает номер устройства
void setDeviceNumber(int dn) { setProperty("deviceNumber", dn); } void setDeviceNumber(int dn) { setProperty("deviceNumber", dn); }
//! \~english Set read timeout in milliseconds
//! \~russian Устанавливает таймаут чтения в миллисекундах
void setTimeoutRead(int t) { setProperty("timeoutRead", t); } void setTimeoutRead(int t) { setProperty("timeoutRead", t); }
//! \~english Set write timeout in milliseconds
//! \~russian Устанавливает таймаут записи в миллисекундах
void setTimeoutWrite(int t) { setProperty("timeoutWrite", t); } void setTimeoutWrite(int t) { setProperty("timeoutWrite", t); }
//! \~english Control write to device
//! \~russian Управляющая запись в устройство
int controlWrite(const void * data, int max_size); int controlWrite(const void * data, int max_size);
virtual void flush() override; virtual void flush() override;

View File

@@ -29,24 +29,39 @@
#include "picrc.h" #include "picrc.h"
#include "pidiagnostics.h" #include "pidiagnostics.h"
//! \~english Base class for reliable send and receive data in fixed packets with error correction, pause and resume
//! \~russian Базовый класс для надежного обмена данными с помощью фиксированных пакетов с коррекцией ошибок и паузой
class PIP_EXPORT PIBaseTransfer: public PIObject { class PIP_EXPORT PIBaseTransfer: public PIObject {
PIOBJECT_SUBCLASS(PIBaseTransfer, PIObject); PIOBJECT_SUBCLASS(PIBaseTransfer, PIObject);
public: public:
//! \~english Constructs empty transfer
//! \~russian Создает пустой transfer
PIBaseTransfer(); PIBaseTransfer();
//! \~english Destructor
//! \~russian Деструктор
~PIBaseTransfer(); ~PIBaseTransfer();
#pragma pack(push, 1) #pragma pack(push, 1)
//! \~english Packet header structure
//! \~russian Структура заголовка пакета
struct PIP_EXPORT PacketHeader { struct PIP_EXPORT PacketHeader {
uint sig; uint sig;
int type; // PacketType int type; // PacketType
int session_id; int session_id;
uint id; uint id;
uint crc; uint crc;
//! \~english Check if signature is valid
//! \~russian Проверка валидности подписи
bool check_sig() { return (sig == signature); } bool check_sig() { return (sig == signature); }
}; };
//! \~english Part information structure
//! \~russian Структура информации о части
struct PIP_EXPORT Part { struct PIP_EXPORT Part {
//! \~english Constructor
//! \~russian Конструктор
Part(uint id_ = 0, ullong size_ = 0, ullong start_ = 0): id(id_), size(size_), start(start_) {} Part(uint id_ = 0, ullong size_ = 0, ullong start_ = 0): id(id_), size(size_), start(start_) {}
uint id; uint id;
ullong size; ullong size;
@@ -54,29 +69,76 @@ public:
}; };
#pragma pack(pop) #pragma pack(pop)
//! \~english Stop sending data
//! \~russian Остановить отправку данных
void stopSend(); void stopSend();
//! \~english Stop receiving data
//! \~russian Остановить прием данных
void stopReceive(); void stopReceive();
//! \~english Check if currently sending
//! \~russian Проверка, идет ли отправка
bool isSending() const { return is_sending; } bool isSending() const { return is_sending; }
//! \~english Check if currently receiving
//! \~russian Проверка, идет ли прием
bool isReceiving() const { return is_receiving; } bool isReceiving() const { return is_receiving; }
//! \~english Check if paused
//! \~russian Проверка, на паузе ли
bool isPause() const { return is_pause; } bool isPause() const { return is_pause; }
//! \~english Set pause state
//! \~russian Установить состояние паузы
void setPause(bool pause_); void setPause(bool pause_);
//! \~english Set packet size
//! \~russian Установить размер пакета
void setPacketSize(int size) { packet_size = size; } void setPacketSize(int size) { packet_size = size; }
//! \~english Get packet size
//! \~russian Получить размер пакета
int packetSize() const { return packet_size; } int packetSize() const { return packet_size; }
//! \~english Set timeout in seconds
//! \~russian Установить таймаут в секундах
void setTimeout(double sec); void setTimeout(double sec);
//! \~english Get timeout in seconds
//! \~russian Получить таймаут в секундах
double timeout() const { return timeout_; } double timeout() const { return timeout_; }
//! \~english Enable/disable CRC check
//! \~russian Включить/выключить проверку CRC
void setCRCEnabled(bool en = true) { crc_enabled = en; } void setCRCEnabled(bool en = true) { crc_enabled = en; }
//! \~english Check if CRC is enabled
//! \~russian Проверка, включен ли CRC
bool isCRCEnabled() const { return crc_enabled; } bool isCRCEnabled() const { return crc_enabled; }
//! \~english Get state as string
//! \~russian Получить состояние в виде строки
PIString stateString() const { return state_string; } PIString stateString() const { return state_string; }
//! \~english Get packet map as string
//! \~russian Получить карту пакетов в виде строки
PIString packetMap() const { return pm_string; } PIString packetMap() const { return pm_string; }
//! \~english Get total bytes count
//! \~russian Получить общее количество байт
llong bytesAll() const { return bytes_all; } llong bytesAll() const { return bytes_all; }
//! \~english Get current bytes count
//! \~russian Получить текущее количество байт
llong bytesCur() const { return bytes_cur; } llong bytesCur() const { return bytes_cur; }
//! \~english Get diagnostics object
//! \~russian Получить объект диагностики
const PIDiagnostics & diagnostic() { return diag; } const PIDiagnostics & diagnostic() { return diag; }
//! \~english Get packet signature
//! \~russian Получить подпись пакета
static uint packetSignature() { return signature; } static uint packetSignature() { return signature; }
EVENT_HANDLER1(void, received, PIByteArray, data); EVENT_HANDLER1(void, received, PIByteArray, data);

View File

@@ -31,13 +31,16 @@
#include "pip_io_utils_export.h" #include "pip_io_utils_export.h"
//! \~english Broadcast for all interfaces, including loopback
//! \~russian Широкое вещание на все интерфейсы, включая loopback
class PIP_IO_UTILS_EXPORT PIBroadcast class PIP_IO_UTILS_EXPORT PIBroadcast
: public PIThread : public PIThread
, public PIEthUtilBase { , public PIEthUtilBase {
PIOBJECT_SUBCLASS(PIBroadcast, PIThread); PIOBJECT_SUBCLASS(PIBroadcast, PIThread);
public: public:
//! %PIBroadcast channels, can be used independently //! \~english %PIBroadcast channels, can be used independently
//! \~russian Каналы %PIBroadcast, могут использоваться независимо
enum Channel { enum Channel {
Multicast /** Use multicast addresses */ = 0x01, Multicast /** Use multicast addresses */ = 0x01,
Broadcast /** Use broadcast addresses */ = 0x02, Broadcast /** Use broadcast addresses */ = 0x02,
@@ -45,75 +48,97 @@ public:
All /** Use all channels */ = 0xFFFF, All /** Use all channels */ = 0xFFFF,
}; };
//! \~english Channels flags type
//! \~russian Тип флагов каналов
typedef PIFlags<Channel> Channels; typedef PIFlags<Channel> Channels;
/** Contructs %PIBroadcast, if \"send_only\" not set //! \~english Constructs %PIBroadcast. If "send_only" not set, all PIEthernets will be binded to receive data
* all PIEthernets will be binded to receive data //! \~russian Создает %PIBroadcast. Если "send_only" не установлен, все PIEthernets будут привязаны для приема данных
* */
PIBroadcast(bool send_only = false); PIBroadcast(bool send_only = false);
//! \~english Destructor
//! \~russian Деструктор
~PIBroadcast(); ~PIBroadcast();
//! Set channels to \"ch\" and queue to reinit //! \~english Set channels to "ch" and queue to reinit
//! \~russian Установить каналы в "ch" и очередь на реинициализацию
void setChannels(Channels ch); void setChannels(Channels ch);
//! Returns channels //! \~english Returns channels
//! \~russian Возвращает каналы
Channels channels() const { return _channels; } Channels channels() const { return _channels; }
//! Returns if is send_only //! \~english Returns if is send_only
//! \~russian Возвращает, является ли отправка только
bool isSendOnly() const { return _send_only; } bool isSendOnly() const { return _send_only; }
//! Set multicast IP to \"mg\" and queue to reinit //! \~english Set multicast IP to "mg" and queue to reinit
//! \~russian Установить multicast IP в "mg" и очередь на реинициализацию
void setMulticastGroup(const PIString & mg); void setMulticastGroup(const PIString & mg);
//! Returns multicast IP //! \~english Returns multicast IP
//! \~russian Возвращает multicast IP
PIString multicastGroup() const { return mcast_address.ipString(); } PIString multicastGroup() const { return mcast_address.ipString(); }
//! Set multicast port to \"port\" and queue to reinit //! \~english Set multicast port to "port" and queue to reinit
//! \~russian Установить multicast порт в "port" и очередь на реинициализацию
void setMulticastPort(ushort port); void setMulticastPort(ushort port);
//! Returns multicast port //! \~english Returns multicast port
//! \~russian Возвращает multicast порт
ushort multicastPort() const { return mcast_address.port(); } ushort multicastPort() const { return mcast_address.port(); }
//! Set multicast address to \"addr\" and queue to reinit //! \~english Set multicast address to "addr" and queue to reinit
//! \~russian Установить multicast адрес в "addr" и очередь на реинициализацию
void setMulticastAddress(const PINetworkAddress & addr); void setMulticastAddress(const PINetworkAddress & addr);
//! Returns multicast address //! \~english Returns multicast address
//! \~russian Возвращает multicast адрес
PINetworkAddress multicastAddress() const { return mcast_address; } PINetworkAddress multicastAddress() const { return mcast_address; }
//! Set broadcast port to \"port\" and queue to reinit //! \~english Set broadcast port to "port" and queue to reinit
//! \~russian Установить broadcast порт в "port" и очередь на реинициализацию
void setBroadcastPort(ushort port); void setBroadcastPort(ushort port);
//! Returns broadcast port //! \~english Returns broadcast port
//! \~russian Возвращает broadcast порт
ushort broadcastPort() { return bcast_port; } ushort broadcastPort() { return bcast_port; }
//! Set loopback start port to \"port\" and queue to reinit //! \~english Set loopback start port to "port" and queue to reinit
//! \~russian Установить начальный loopback порт в "port" и очередь на реинициализацию
void setLoopbackPort(ushort port); void setLoopbackPort(ushort port);
//! Returns loopback start port //! \~english Returns loopback start port
//! \~russian Возвращает начальный loopback порт
ushort loopbackPort() { return lo_port; } ushort loopbackPort() { return lo_port; }
//! Set loopback ports count to \"count\" and queue to reinit //! \~english Set loopback ports count to "count" and queue to reinit
//! \~russian Установить количество loopback портов в "count" и очередь на реинициализацию
void setLoopbackPortsCount(int count); void setLoopbackPortsCount(int count);
//! Returns loopback ports count //! \~english Returns loopback ports count
//! \~russian Возвращает количество loopback портов
int loopbackPortsCount() const { return lo_pcnt; } int loopbackPortsCount() const { return lo_pcnt; }
//! If not send_only starts all threaded reads //! \~english If not send_only starts all threaded reads
//! \~russian Если не send_only запускает все потоковые чтения
void startRead(); void startRead();
//! Stop all threaded reads //! \~english Stop all threaded reads
//! \~russian Остановить все потоковые чтения
void stopRead(); void stopRead();
//! Reinit all PIEthernets with current \a PIEthernet::allAddresses() //! \~english Reinit all PIEthernets with current \a PIEthernet::allAddresses()
//! \~russian Реинициализировать все PIEthernets с текущими \a PIEthernet::allAddresses()
void reinit(); void reinit();
//! Send packet //! \~english Send packet
//! \~russian Отправить пакет
void send(const PIByteArray & data); void send(const PIByteArray & data);
EVENT1(receiveEvent, PIByteArray, data); EVENT1(receiveEvent, PIByteArray, data);

View File

@@ -1,10 +1,13 @@
/*! \file piconnection.h //! \addtogroup IO-Utils
* \brief //! \{
* \ingroup IO-Utils //! \file piconnection.h
* \~\brief //! \brief
* \~english Complex I/O point //! \~english Complex I/O point
* \~russian Составное устройство ввода/вывода //! \~russian Составное устройство ввода/вывода
*/ //! \details
//! \~english This class provides a complex I/O point that can manage multiple devices, filters, channels, and senders.
//! \~russian Этот класс предоставляет составное устройство ввода/вывода, которое может управлять множеством устройств, фильтров, каналов и отправителей.
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Complex I/O point Complex I/O point
@@ -32,269 +35,373 @@
class PIConfig; class PIConfig;
//! \~english Complex I/O point
//! \~russian Составное устройство ввода/вывода
//! \details This class provides a complex I/O point that can manage multiple devices, filters, channels, and senders.
//! \~russian Этот класс предоставляет составное устройство ввода/вывода, которое может управлять множеством устройств, фильтров, каналов и отправителей.
class PIP_EXPORT PIConnection: public PIObject { class PIP_EXPORT PIConnection: public PIObject {
PIOBJECT_SUBCLASS(PIConnection, PIObject); PIOBJECT_SUBCLASS(PIConnection, PIObject);
public: public:
//! Constructs connection with name "name", or with default name = "connection" //! \~english Constructs connection with name "name", or with default name = "connection"
//! \~russian Создает подключение с именем "name" или с именем по умолчанию "connection"
PIConnection(const PIString & name = PIStringAscii("connection")); PIConnection(const PIString & name = PIStringAscii("connection"));
//! Constructs connection and configure it from config file "config" from section "name" //! \~english Constructs connection and configure it from config file "config" from section "name"
//! \~russian Создает подключение и настраивает его из файла конфигурации "config" из секции "name"
PIConnection(const PIString & config, const PIString & name); PIConnection(const PIString & config, const PIString & name);
//! Constructs connection and configure it from config content "string" from section "name" //! \~english Constructs connection and configure it from config content "string" from section "name"
//! \~russian Создает подключение и настраивает его из содержимого конфигурации "string" из секции "name"
PIConnection(PIString * string, const PIString & name); PIConnection(PIString * string, const PIString & name);
//! \~english Destructor
//! \~russian Деструктор
~PIConnection(); ~PIConnection();
/*! \brief Configure connection from config file "config" from section "name". Returns if configuration was successful //! \~english Configure connection from config file "config" from section "name". Returns if configuration was successful
* \details \b Warning: all devices, filters and channels removed before configure! */ //! \~russian Настраивает подключение из файла конфигурации "config" из секции "name". Возвращает успешность настройки
//! \details \b Warning: all devices, filters and channels removed before configure!
//! \~russian \b Внимание: все устройства, фильтры и каналы удаляются перед настройкой!
bool configureFromConfig(const PIString & config, const PIString & name = PIStringAscii("connection")); bool configureFromConfig(const PIString & config, const PIString & name = PIStringAscii("connection"));
/*! \brief Configure connection from config content "string" from section "name". Returns if configuration was successful //! \~english Configure connection from config content "string" from section "name". Returns if configuration was successful
* \details \b Warning: all devices, filters and channels removed before configure! */ //! \~russian Настраивает подключение из содержимого конфигурации "string" из секции "name". Возвращает успешность настройки
//! \details \b Warning: all devices, filters and channels removed before configure!
//! \~russian \b Внимание: все устройства, фильтры и каналы удаляются перед настройкой!
bool configureFromString(PIString * string, const PIString & name = PIStringAscii("connection")); bool configureFromString(PIString * string, const PIString & name = PIStringAscii("connection"));
//! Returns config file section of current connection configuration //! \~english Returns config file section of current connection configuration
//! \~russian Возвращает секцию файла конфигурации текущей конфигурации подключения
PIString makeConfig() const; PIString makeConfig() const;
/*! \brief Add device with full path "full_path", open mode "mode" to Device pool and connection //! \~english Add device with full path "full_path", open mode "mode" to Device pool and connection
* \details Returns pointer to device or null if device can not be created. If "start" is true, //! \~russian Добавляет устройство с полным путем "full_path", режимом открытия "mode" в пул устройств и подключение
* read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead() //! \details Returns pointer to device or null if device can not be created. If "start" is true,
* or \a startAllThreadedReads(). By default, read thread doesn`t start */ //! \~english read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead()
//! \~russian поток чтения запускается немедленно. В противном случае можно запустить поток чтения с помощью функций \a startThreadedRead()
//! \~english or \a startAllThreadedReads(). By default, read thread doesn`t start
//! \~russian или \a startAllThreadedReads(). По умолчанию поток чтения не запускается
PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false); PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false);
//! \~english Sets the name for device "dev"
//! \~russian Устанавливает имя для устройства "dev"
void setDeviceName(PIIODevice * dev, const PIString & name); void setDeviceName(PIIODevice * dev, const PIString & name);
//! \~english Returns list of device names
//! \~russian Возвращает список имен устройств
PIStringList deviceNames(const PIIODevice * dev) const; PIStringList deviceNames(const PIIODevice * dev) const;
/*! \brief Remove device with full path "full_path" from connection //! \~english Remove device with full path "full_path" from connection
* \details Returns if device was removed. If there is no connection bounded to this device, //! \~russian Удаляет устройство с полным путем "full_path" из подключения
* it will be removed from Device pool */ //! \details Returns if device was removed. If there is no connection bounded to this device,
//! \~english it will be removed from Device pool
//! \~russian оно будет удалено из пула устройств
bool removeDevice(const PIString & full_path); bool removeDevice(const PIString & full_path);
/*! \brief Remove all device from connection //! \~english Remove all device from connection
* \details If there is no connection bounded to there devices, they removed from Device pool */ //! \~russian Удаляет все устройства из подключения
//! \details If there is no connection bounded to there devices, they removed from Device pool
//! \~russian Если к устройствам не привязано подключение, они удаляются из пула устройств
void removeAllDevices(); void removeAllDevices();
//! Returns device with full path "full_path" or null if there is no such device //! \~english Returns device with full path "full_path" or null if there is no such device
//! \~russian Возвращает устройство с полным путем "full_path" или null, если такого устройства нет
PIIODevice * deviceByFullPath(const PIString & full_path) const; PIIODevice * deviceByFullPath(const PIString & full_path) const;
//! Returns device with name "name" or null if there is no such device //! \~english Returns device with name "name" or null if there is no such device
//! \~russian Возвращает устройство с именем "name" или null, если такого устройства нет
PIIODevice * deviceByName(const PIString & name) const; PIIODevice * deviceByName(const PIString & name) const;
//! Returns all devices bounded to this connection //! \~english Returns all devices bounded to this connection
//! \~russian Возвращает все устройства, привязанные к этому подключению
PIVector<PIIODevice *> boundedDevices() const; PIVector<PIIODevice *> boundedDevices() const;
/*! \brief Add filter with name "name" to device with full path "full_path_name" or filter "full_path_name" //! \~english Add filter with name "name" to device with full path "full_path_name" or filter "full_path_name"
* \details If there is no filter with name "name", connection create new with split mode "mode" and bound //! \~russian Добавляет фильтр с именем "name" к устройству с полным путем "full_path_name" или фильтру "full_path_name"
* to it device "full_path_name" or filter "full_path_name". If filter with name "name" already exists, //! \details If there is no filter with name "name", connection create new with split mode "mode" and bound
* device "full_path_name" or filter "full_path_name" add to this filter. //! \~english to it device "full_path_name" or filter "full_path_name". If filter with name "name" already exists,
* This function returns PIPacketExtractor * assosiated with this filter //! \~english device "full_path_name" or filter "full_path_name" add to this filter.
* \n \b Attention! "mode" is altual olny if new filter was created! */ //! \~russian к нему устройство "full_path_name" или фильтр "full_path_name". Если фильтр с именем "name" уже существует,
//! \~english This function returns PIPacketExtractor * assosiated with this filter
//! \~russian устройство "full_path_name" или фильтр "full_path_name" добавляется к этому фильтру.
//! \~english This function returns PIPacketExtractor * assosiated with this filter
//! \~russian Эта функция возвращает PIPacketExtractor *, связанный с этим фильтром
//! \~\sa PIPacketExtractor
//! \details \b Attention! "mode" is altual olny if new filter was created!
//! \~russian \b Внимание! "mode" актуален только если был создан новый фильтр!
PIPacketExtractor * PIPacketExtractor *
addFilter(const PIString & name, const PIString & full_path_name, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None); addFilter(const PIString & name, const PIString & full_path_name, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None);
//! Add filter with name "name" to device "dev" //! \~english Add filter with name "name" to device "dev"
//! \~russian Добавляет фильтр с именем "name" к устройству "dev"
PIPacketExtractor * PIPacketExtractor *
addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None) { addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None) {
return addFilter(name, devFPath(dev), mode); return addFilter(name, devFPath(dev), mode);
} }
//! Add filter with "filter" to device "dev" //! \~english Add filter with "filter" to device "dev"
//! \~russian Добавляет фильтр "filter" к устройству "dev"
PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIString & full_path_name); PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIString & full_path_name);
//! Add filter with "filter" to device "dev" //! \~english Add filter with "filter" to device "dev"
//! \~russian Добавляет фильтр "filter" к устройству "dev"
PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIIODevice * dev) { return addFilter(filter, devFPath(dev)); } PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIIODevice * dev) { return addFilter(filter, devFPath(dev)); }
/*! \brief Remove from filter with name "name" device with full path "full_path_name" or filter "full_path_name" //! \~english Remove from filter with name "name" device with full path "full_path_name" or filter "full_path_name"
* \details If there is no devices bounded to this filter, it will be removed. Returns if device was removed */ //! \~russian Удаляет из фильтра с именем "name" устройство с полным путем "full_path_name" или фильтр "full_path_name"
//! \details If there is no devices bounded to this filter, it will be removed. Returns if device was removed
//! \~russian Если к этому фильтру не привязано устройств, он будет удален. Возвращает успешность удаления устройства
bool removeFilter(const PIString & name, const PIString & full_path_name); bool removeFilter(const PIString & name, const PIString & full_path_name);
//! Remove from filter with name "name" device or filter "dev" //! \~english Remove from filter with name "name" device or filter "dev"
//! \~russian Удаляет из фильтра с именем "name" устройство или фильтр "dev"
bool removeFilter(const PIString & name, const PIIODevice * dev); bool removeFilter(const PIString & name, const PIIODevice * dev);
//! Remove filter with name "name". Returns if filter was removed //! \~english Remove filter with name "name". Returns if filter was removed
//! \~russian Удаляет фильтр с именем "name". Возвращает успешность удаления фильтра
bool removeFilter(const PIString & name); bool removeFilter(const PIString & name);
//! Remove all filters from connection //! \~english Remove all filters from connection
//! \~russian Удаляет все фильтры из подключения
void removeAllFilters(); void removeAllFilters();
//! Returns all filters of connection //! \~english Returns all filters of connection
//! \~russian Возвращает все фильтры подключения
PIVector<PIPacketExtractor *> filters() const; PIVector<PIPacketExtractor *> filters() const;
//! Returns all filter names of connection //! \~english Returns all filter names of connection
//! \~russian Возвращает все имена фильтров подключения
PIStringList filterNames() const; PIStringList filterNames() const;
//! Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter //! \~english Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter
//! \~russian Возвращает PIPacketExtractor *, связанный с фильтром "name" или null, если такого фильтра нет
PIPacketExtractor * filter(const PIString & name) const; PIPacketExtractor * filter(const PIString & name) const;
//! Returns all devices bounded to filter "name" //! \~english Returns all devices bounded to filter "name"
//! \~russian Возвращает все устройства, привязанные к фильтру "name"
PIVector<PIIODevice *> filterBoundedDevices(const PIString & name) const; PIVector<PIIODevice *> filterBoundedDevices(const PIString & name) const;
/*! \brief Add to connection channel from "name_from" to "name_to" //! \~english Add to connection channel from "name_from" to "name_to"
* \details "name_from" and "name_to" can be full pathes of devices or device names or filter names. //! \~russian Добавляет в подключение канал от "name_from" к "name_to"
* Returns \b false if there if no such device or filter, else create channel and returns \b true */ //! \details "name_from" and "name_to" can be full pathes of devices or device names or filter names.
//! \~english Returns \b false if there if no such device or filter, else create channel and returns \b true
//! \~russian Возвращает \b false, если такого устройства или фильтра нет, иначе создает канал и возвращает \b true
bool addChannel(const PIString & name_from, const PIString & name_to); bool addChannel(const PIString & name_from, const PIString & name_to);
//! Add to connection channel from "name_from" to "dev_to" //! \~english Add to connection channel from "name_from" to "dev_to"
//! \~russian Добавляет в подключение канал от "name_from" к "dev_to"
bool addChannel(const PIString & name_from, const PIIODevice * dev_to) { return addChannel(name_from, devFPath(dev_to)); } bool addChannel(const PIString & name_from, const PIIODevice * dev_to) { return addChannel(name_from, devFPath(dev_to)); }
//! Add to connection channel from "dev_from" to "name_to" //! \~english Add to connection channel from "dev_from" to "name_to"
//! \~russian Добавляет в подключение канал от "dev_from" к "name_to"
bool addChannel(const PIIODevice * dev_from, const PIString & name_to) { return addChannel(devFPath(dev_from), name_to); } bool addChannel(const PIIODevice * dev_from, const PIString & name_to) { return addChannel(devFPath(dev_from), name_to); }
//! Add to connection channel from "dev_from" to "dev_to" //! \~english Add to connection channel from "dev_from" to "dev_to"
//! \~russian Добавляет в подключение канал от "dev_from" к "dev_to"
bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) { return addChannel(devFPath(dev_from), devFPath(dev_to)); } bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) { return addChannel(devFPath(dev_from), devFPath(dev_to)); }
/*! \brief Remove from connection channel from "name_from" to "name_to" //! \~english Remove from connection channel from "name_from" to "name_to"
* \details "name_from" and "name_to" can be full pathes of devices or filter names. //! \~russian Удаляет из подключения канал от "name_from" к "name_to"
* Returns \b false if there if no such device or filter, else remove channel and returns \b true */ //! \details "name_from" and "name_to" can be full pathes of devices or filter names.
//! \~english Returns \b false if there if no such device or filter, else remove channel and returns \b true
//! \~russian Возвращает \b false, если такого устройства или фильтра нет, иначе удаляет канал и возвращает \b true
bool removeChannel(const PIString & name_from, const PIString & name_to); bool removeChannel(const PIString & name_from, const PIString & name_to);
//! Remove from connection channel from "name_from" to "dev_to" //! \~english Remove from connection channel from "name_from" to "dev_to"
//! \~russian Удаляет из подключения канал от "name_from" к "dev_to"
bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) { return removeChannel(name_from, devFPath(dev_to)); } bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) { return removeChannel(name_from, devFPath(dev_to)); }
//! Remove from connection channel from "dev_from" to "name_to" //! \~english Remove from connection channel from "dev_from" to "name_to"
//! \~russian Удаляет из подключения канал от "dev_from" к "name_to"
bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) { return removeChannel(devFPath(dev_from), name_to); } bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) { return removeChannel(devFPath(dev_from), name_to); }
//! Remove from connection channel from "dev_from" to "dev_to" //! \~english Remove from connection channel from "dev_from" to "dev_to"
//! \~russian Удаляет из подключения канал от "dev_from" к "dev_to"
bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) { bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {
return removeChannel(devFPath(dev_from), devFPath(dev_to)); return removeChannel(devFPath(dev_from), devFPath(dev_to));
} }
/*! \brief Remove from connection all channels from "name_from" //! \~english Remove from connection all channels from "name_from"
* \details "name_from" can be full path of device or filter name. //! \~russian Удаляет из подключения все каналы от "name_from"
* Returns \b false if there if no such device or filter, else remove channels and returns \b true */ //! \details "name_from" can be full path of device or filter name.
//! \~english Returns \b false if there if no such device or filter, else remove channels and returns \b true
//! \~russian Возвращает \b false, если такого устройства или фильтра нет, иначе удаляет каналы и возвращает \b true
bool removeChannel(const PIString & name_from); bool removeChannel(const PIString & name_from);
//! Remove from connection all channels from "dev_from" //! \~english Remove from connection all channels from "dev_from"
//! \~russian Удаляет из подключения все каналы от "dev_from"
bool removeChannel(const PIIODevice * dev_from) { return removeChannel(devFPath(dev_from)); } bool removeChannel(const PIIODevice * dev_from) { return removeChannel(devFPath(dev_from)); }
//! Remove from connection all channels //! \~english Remove from connection all channels
//! \~russian Удаляет из подключения все каналы
void removeAllChannels(); void removeAllChannels();
//! Returns all channels of this connection as full pathes or filter names pair array (from, to) //! \~english Returns all channels of this connection as full pathes or filter names pair array (from, to)
//! \~russian Возвращает все каналы этого подключения в виде массива пар полных путей или имен фильтров (от, до)
PIVector<PIPair<PIString, PIString>> channels() const; PIVector<PIPair<PIString, PIString>> channels() const;
/*! \brief Add to connection sender with name "name" device with full path "full_path" //! \~english Add to connection sender with name "name" device with full path "full_path"
* \details If there is no sender with name "name", connection create new, bound //! \~russian Добавляет в подключение отправителя с именем "name" устройство с полным путем "full_path"
* to it device "full_path_name" and start sender timer with frequency "frequency". //! \details If there is no sender with name "name", connection create new, bound
* If sender with name "name" already exists, device "full_path_name" add to this sender //! \~english to it device "full_path_name" and start sender timer with frequency "frequency".
* If "start" is true, sender is started immediately. Else, you can start sender with //! \~russian к нему устройство "full_path_name" и запускает таймер отправителя с частотой "frequency".
* functions \a startSender() //! \~english If sender with name "name" already exists, device "full_path_name" add to this sender
* \n \b Attention! "frequency" is actual olny if new sender was created! */ //! \~russian Если отправитель с именем "name" уже существует, устройство "full_path_name" добавляется к этому отправителю
//! \~english If "start" is true, sender is started immediately. Else, you can start sender with
//! \~russian Если "start" равно true, отправитель запускается немедленно. В противном случае можно запустить отправителя с помощью
//! \~english functions \a startSender()
//! \~russian функций \a startSender()
//! \~\sa startSender()
//! \details \b Attention! "frequency" is actual olny if new sender was created!
//! \~russian \b Внимание! "frequency" актуален только если был создан новый отправитель!
void addSender(const PIString & name, const PIString & full_path_name, float frequency, bool start = false); void addSender(const PIString & name, const PIString & full_path_name, float frequency, bool start = false);
//! Add to connection sender with name "name" device "dev" //! \~english Add to connection sender with name "name" device "dev"
//! \~russian Добавляет в подключение отправителя с именем "name" устройство "dev"
void addSender(const PIString & name, const PIIODevice * dev, float frequency, bool start = false) { void addSender(const PIString & name, const PIIODevice * dev, float frequency, bool start = false) {
addSender(name, devFPath(dev), frequency, start); addSender(name, devFPath(dev), frequency, start);
} }
/*! \brief Remove from sender with name "name" device with full path "full_path_name" //! \~english Remove from sender with name "name" device with full path "full_path_name"
* \details If there is no devices bounded to this sender, it will be removed. Returns if sender was removed */ //! \~russian Удаляет из отправителя с именем "name" устройство с полным путем "full_path_name"
//! \details If there is no devices bounded to this sender, it will be removed. Returns if sender was removed
//! \~russian Если к этому отправителю не привязано устройств, он будет удален. Возвращает успешность удаления отправителя
bool removeSender(const PIString & name, const PIString & full_path_name); bool removeSender(const PIString & name, const PIString & full_path_name);
//! Remove from sender with name "name" device "dev" //! \~english Remove from sender with name "name" device "dev"
//! \~russian Удаляет из отправителя с именем "name" устройство "dev"
bool removeSender(const PIString & name, const PIIODevice * dev) { return removeSender(name, devFPath(dev)); } bool removeSender(const PIString & name, const PIIODevice * dev) { return removeSender(name, devFPath(dev)); }
//! Remove sender with name "name", returns if sender was removed //! \~english Remove sender with name "name", returns if sender was removed
//! \~russian Удаляет отправителя с именем "name", возвращает успешность удаления отправителя
bool removeSender(const PIString & name); bool removeSender(const PIString & name);
//! Set sender "name" fixed send data "data", returns if sender exists //! \~english Set sender "name" fixed send data "data", returns if sender exists
//! \~russian Устанавливает фиксированные данные отправки для отправителя "name", возвращает существование отправителя
bool setSenderFixedData(const PIString & name, const PIByteArray & data); bool setSenderFixedData(const PIString & name, const PIByteArray & data);
//! Remove sender "name" fixed send data, returns if sender exists //! \~english Remove sender "name" fixed send data, returns if sender exists
//! \~russian Удаляет фиксированные данные отправки для отправителя "name", возвращает существование отправителя
bool clearSenderFixedData(const PIString & name); bool clearSenderFixedData(const PIString & name);
//! Returns sender "name" fixed send data //! \~english Returns sender "name" fixed send data
//! \~russian Возвращает фиксированные данные отправки для отправителя "name"
PIByteArray senderFixedData(const PIString & name) const; PIByteArray senderFixedData(const PIString & name) const;
//! Returns sender "name" timer frequency, -1 if there is no such sender, or 0 if sender is not started yet //! \~english Returns sender "name" timer frequency, -1 if there is no such sender, or 0 if sender is not started yet
//! \~russian Возвращает частоту таймера отправителя "name", -1 если такого отправителя нет, или 0 если отправитель еще не запущен
float senderFrequency(const PIString & name) const; float senderFrequency(const PIString & name) const;
//! Remove from connection all senders //! \~english Remove from connection all senders
//! \~russian Удаляет из подключения всех отправителей
void removeAllSenders(); void removeAllSenders();
//! Start read thread of device with full path "full_path" //! \~english Start read thread of device with full path "full_path"
//! \~russian Запускает поток чтения устройства с полным путем "full_path"
void startThreadedRead(const PIString & full_path_name); void startThreadedRead(const PIString & full_path_name);
//! Start read thread of device "dev" //! \~english Start read thread of device "dev"
//! \~russian Запускает поток чтения устройства "dev"
void startThreadedRead(const PIIODevice * dev) { startThreadedRead(devFPath(dev)); } void startThreadedRead(const PIIODevice * dev) { startThreadedRead(devFPath(dev)); }
//! Start read threads of all Device pool device //! \~english Start read threads of all Device pool device
//! \~russian Запускает потоки чтения всех устройств пула устройств
void startAllThreadedReads(); void startAllThreadedReads();
//! Start sender "name" timer //! \~english Start sender "name" timer
//! \~russian Запускает таймер отправителя "name"
void startSender(const PIString & name); void startSender(const PIString & name);
//! Start all senders timers //! \~english Start all senders timers
//! \~russian Запускает все таймеры отправителей
void startAllSenders(); void startAllSenders();
//! Start all read threads and senders //! \~english Start all read threads and senders
//! \~russian Запускает все потоки чтения и отправителей
void start() { void start() {
startAllThreadedReads(); startAllThreadedReads();
startAllSenders(); startAllSenders();
} }
//! Stop read thread of device with full path "full_path" //! \~english Stop read thread of device with full path "full_path"
//! \~russian Останавливает поток чтения устройства с полным путем "full_path"
void stopThreadedRead(const PIString & full_path_name); void stopThreadedRead(const PIString & full_path_name);
//! Stop read thread of device "dev" //! \~english Stop read thread of device "dev"
//! \~russian Останавливает поток чтения устройства "dev"
void stopThreadedRead(const PIIODevice * dev) { stopThreadedRead(devFPath(dev)); } void stopThreadedRead(const PIIODevice * dev) { stopThreadedRead(devFPath(dev)); }
//! Stop read threads of all Device pool device //! \~english Stop read threads of all Device pool device
//! \~russian Останавливает потоки чтения всех устройств пула устройств
void stopAllThreadedReads(); void stopAllThreadedReads();
//! Stop sender "name" timer //! \~english Stop sender "name" timer
//! \~russian Останавливает таймер отправителя "name"
void stopSender(const PIString & name); void stopSender(const PIString & name);
//! Stop all senders timers //! \~english Stop all senders timers
//! \~russian Останавливает все таймеры отправителей
void stopAllSenders(); void stopAllSenders();
//! Stop all read threads and senders //! \~english Stop all read threads and senders
//! \~russian Останавливает все потоки чтения и отправителей
void stop() { void stop() {
stopAllThreadedReads(); stopAllThreadedReads();
stopAllSenders(); stopAllSenders();
} }
//! Stop connection and remove all devices //! \~english Stop connection and remove all devices
//! \~russian Останавливает подключение и удаляет все устройства
void destroy() { void destroy() {
stop(); stop();
removeAllDevices(); removeAllDevices();
} }
//! Returns if there are no devices in this connection //! \~english Returns if there are no devices in this connection
//! \~russian Возвращает, если в этом подключении нет устройств
bool isEmpty() const { return device_modes.isEmpty(); } bool isEmpty() const { return device_modes.isEmpty(); }
//! Returns PIDiagnostics * assosiated with device with full path "full_path_name", name "full_path_name" or filter "full_path_name" //! \~english Returns PIDiagnostics * assosiated with device with full path "full_path_name", name "full_path_name" or filter "full_path_name"
//! \~russian Возвращает PIDiagnostics *, связанный с устройством с полным путем "full_path_name", именем "full_path_name" или фильтром "full_path_name"
PIDiagnostics * diagnostic(const PIString & full_path_name) const; PIDiagnostics * diagnostic(const PIString & full_path_name) const;
//! Returns PIDiagnostics * assosiated with device or filter "dev" //! \~english Returns PIDiagnostics * assosiated with device or filter "dev"
//! \~russian Возвращает PIDiagnostics *, связанный с устройством или фильтром "dev"
PIDiagnostics * diagnostic(const PIIODevice * dev) const { return diags_.value(const_cast<PIIODevice *>(dev), 0); } PIDiagnostics * diagnostic(const PIIODevice * dev) const { return diags_.value(const_cast<PIIODevice *>(dev), 0); }
//! Write data "data" to device with full path "full_path" and returns result of \a write() function of device //! \~english Write data "data" to device with full path "full_path" and returns result of \a write() function of device
//! \~russian Записывает данные "data" в устройство с полным путем "full_path" и возвращает результат функции \a write() устройства
int writeByFullPath(const PIString & full_path, const PIByteArray & data); int writeByFullPath(const PIString & full_path, const PIByteArray & data);
//! Write data "data" to device with name "name" and returns result of \a write() function of device //! \~english Write data "data" to device with name "name" and returns result of \a write() function of device
//! \~russian Записывает данные "data" в устройство с именем "name" и возвращает результат функции \a write() устройства
int writeByName(const PIString & name, const PIByteArray & data); int writeByName(const PIString & name, const PIByteArray & data);
//! Write data "data" to device "dev" and returns result of \a write() function of device //! \~english Write data "data" to device "dev" and returns result of \a write() function of device
//! \~russian Записывает данные "data" в устройство "dev" и возвращает результат функции \a write() устройства
int write(PIIODevice * dev, const PIByteArray & data); int write(PIIODevice * dev, const PIByteArray & data);
//! Returns all connections in application //! \~english Returns all connections in application
//! \~russian Возвращает все подключения в приложении
static PIVector<PIConnection *> allConnections(); static PIVector<PIConnection *> allConnections();
//! Returns all devices in Device pool //! \~english Returns all devices in Device pool
//! \~russian Возвращает все устройства в пуле устройств
static PIVector<PIIODevice *> allDevices(); static PIVector<PIIODevice *> allDevices();
//! Set Device pool fake mode to \"yes\" and returns previous mode //! \~english Set Device pool fake mode to \"yes\" and returns previous mode
//! \~russian Устанавливает фальшивый режим пула устройств в \"yes\" и возвращает предыдущий режим
static bool setFakeMode(bool yes); static bool setFakeMode(bool yes);
//! Returns if Device pool works in fake mode //! \~english Returns if Device pool works in fake mode
//! \~russian Возвращает, работает ли пул устройств в фальшивом режиме
static bool isFakeMode(); static bool isFakeMode();
//! \~english Device pool class
//! \~russian Класс пула устройств
class PIP_EXPORT DevicePool: public PIThread { class PIP_EXPORT DevicePool: public PIThread {
PIOBJECT_SUBCLASS(DevicePool, PIThread); PIOBJECT_SUBCLASS(DevicePool, PIThread);
friend void __DevicePool_threadReadDP(void * ddp); friend void __DevicePool_threadReadDP(void * ddp);
@@ -314,54 +421,95 @@ public:
void unboundConnection(PIConnection * parent); void unboundConnection(PIConnection * parent);
PIIODevice * device(const PIString & fp) const; PIIODevice * device(const PIString & fp) const;
DeviceData * deviceData(PIIODevice * d) const; DeviceData * deviceData(PIIODevice * d) const;
//! \~english Returns list of bounded connections
//! \~russian Возвращает список привязанных подключений
PIVector<PIConnection *> boundedConnections() const; PIVector<PIConnection *> boundedConnections() const;
//! \~english Returns list of bounded devices
//! \~russian Возвращает список привязанных устройств
PIVector<PIIODevice *> boundedDevices() const; PIVector<PIIODevice *> boundedDevices() const;
//! \~english Returns list of bounded devices for specific parent connection
//! \~russian Возвращает список привязанных устройств для конкретного родительского подключения
PIVector<PIIODevice *> boundedDevices(const PIConnection * parent) const; PIVector<PIIODevice *> boundedDevices(const PIConnection * parent) const;
protected: protected:
//! \~english Device data structure
//! \~russian Структура данных устройства
struct PIP_EXPORT DeviceData { struct PIP_EXPORT DeviceData {
//! \~english Constructor
//! \~russian Конструктор
DeviceData(): dev(0), rthread(0), started(false) {} DeviceData(): dev(0), rthread(0), started(false) {}
//! \~english Destructor
//! \~russian Деструктор
~DeviceData(); ~DeviceData();
//! \~english Device pointer
//! \~russian Указатель на устройство
PIIODevice * dev; PIIODevice * dev;
//! \~english Read thread pointer
//! \~russian Указатель на поток чтения
PIThread * rthread; PIThread * rthread;
//! \~english Started flag
//! \~russian Флаг запуска
bool started; bool started;
//! \~english List of listeners
//! \~russian Список слушателей
PIVector<PIConnection *> listeners; PIVector<PIConnection *> listeners;
}; };
//! \~english Thread execution function
//! \~russian Функция выполнения потока
void run() override; void run() override;
//! \~english Called when device is read
//! \~russian Вызывается при чтении устройства
void deviceReaded(DeviceData * dd, const PIByteArray & data); void deviceReaded(DeviceData * dd, const PIByteArray & data);
//! \~english Map of devices
//! \~russian Карта устройств
PIMap<PIString, DeviceData *> devices; PIMap<PIString, DeviceData *> devices;
//! \~english Fake mode flag
//! \~russian Флаг фальшивого режима
bool fake; bool fake;
}; };
//! \~english Data received event
//! \~russian Событие получения данных
EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data); EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data);
//! \~english Packet received event
//! \~russian Событие получения пакета
EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data); EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data);
//! \~english Quality changed event
//! \~russian Событие изменения качества
EVENT3(qualityChanged, const PIIODevice *, dev, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality); EVENT3(qualityChanged, const PIIODevice *, dev, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \events //! \~english Events
//! \~russian События
//! \{ //! \{
//! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data) //! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data)
//! \brief Raise on data received from device with full path "from" //! \~english Raise on data received from device with full path "from"
//! \~russian Возникает при получении данных от устройства с полным путем "from"
//! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data) //! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data)
//! \brief Raise on packet received from filter with name "from" //! \~english Raise on packet received from filter with name "from"
//! \~russian Возникает при получении пакета от фильтра с именем "from"
//! \fn void qualityChanged(const PIIODevice * device, PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) //! \fn void qualityChanged(const PIIODevice * device, PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
//! \brief Raise on diagnostic quality of device "device" changed from "old_quality" to "new_quality" //! \~english Raise on diagnostic quality of device "device" changed from "old_quality" to "new_quality"
//! \~russian Возникает при изменении диагностического качества устройства "device" с "old_quality" на "new_quality"
//! \} //! \}
protected: protected:
//! Executes on data received from device with full path "from" //! \~english Executes on data received from device with full path "from"
//! \~russian Выполняется при получении данных от устройства с полным путем "from"
virtual void dataReceived(const PIString & from, const PIByteArray & data) {} virtual void dataReceived(const PIString & from, const PIByteArray & data) {}
//! Executes on packet received from filter with name "from" //! \~english Executes on packet received from filter with name "from"
//! \~russian Выполняется при получении пакета от фильтра с именем "from"
virtual void packetReceived(const PIString & from, const PIByteArray & data) {} virtual void packetReceived(const PIString & from, const PIByteArray & data) {}
//! You should returns data for sender "sender_name" //! \~english You should returns data for sender "sender_name"
//! \~russian Вы должны возвращать данные для отправителя "sender_name"
virtual PIByteArray senderData(const PIString & sender_name); virtual PIByteArray senderData(const PIString & sender_name);
private: private:

View File

@@ -29,14 +29,26 @@
#include "pibasetransfer.h" #include "pibasetransfer.h"
//! \~english Class for send and receive PIByteArray via \a PIBaseTransfer
//! \~russian Класс для отправки и приема PIByteArray с помощью \a PIBaseTransfer
class PIP_EXPORT PIDataTransfer: public PIBaseTransfer { class PIP_EXPORT PIDataTransfer: public PIBaseTransfer {
PIOBJECT_SUBCLASS(PIDataTransfer, PIBaseTransfer); PIOBJECT_SUBCLASS(PIDataTransfer, PIBaseTransfer);
public: public:
//! \~english Constructs empty data transfer
//! \~russian Создает пустой transfer данных
PIDataTransfer() { ; } PIDataTransfer() { ; }
//! \~english Destructor
//! \~russian Деструктор
~PIDataTransfer() { ; } ~PIDataTransfer() { ; }
//! \~english Send data
//! \~russian Отправить данные
bool send(const PIByteArray & ba); bool send(const PIByteArray & ba);
//! \~english Get received data
//! \~russian Получить принятые данные
const PIByteArray & data() { return data_; } const PIByteArray & data() { return data_; }
private: private:

View File

@@ -1,9 +1,13 @@
/*! \file pidiagnostics.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file pidiagnostics.h
* \~english Connection quality diagnostics //! \brief
* \~russian Диагностика качества связи //! \~english Connection quality diagnostics
*/ //! \~russian Диагностика качества связи
//! \details
//! \~english This class provides connection quality diagnostics based on packet reception statistics
//! \~russian Класс обеспечивает диагностику качества связи на основе статистики приема пакетов
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Speed and quality in/out diagnostics Speed and quality in/out diagnostics
@@ -30,6 +34,8 @@
#include "pitimer.h" #include "pitimer.h"
//! \~english Connection quality diagnostics class based on packet statistics
//! \~russian Класс диагностики качества связи на основе статистики пакетов
class PIP_EXPORT PIDiagnostics: public PITimer { class PIP_EXPORT PIDiagnostics: public PITimer {
PIOBJECT_SUBCLASS(PIDiagnostics, PITimer); PIOBJECT_SUBCLASS(PIDiagnostics, PITimer);
friend class PIConnection; friend class PIConnection;
@@ -37,118 +43,215 @@ class PIP_EXPORT PIDiagnostics: public PITimer {
public: public:
NO_COPY_CLASS(PIDiagnostics); NO_COPY_CLASS(PIDiagnostics);
//! Constructs an empty diagnostics and if "start_" start it //! \~english Constructs an empty diagnostics and if "start_" start it
//! \~russian Создает пустую диагностику и запускает её, если "start_" установлено
PIDiagnostics(bool start_ = true); PIDiagnostics(bool start_ = true);
//! \~english Virtual destructor
//! \~russian Виртуальный деструктор
virtual ~PIDiagnostics(); virtual ~PIDiagnostics();
//! Connection quality //! \~english Connection quality enumeration
//! \~russian Перечисление качества связи
enum Quality { enum Quality {
Unknown /** Unknown, no one packet received yet */ = 1, //! \~english Unknown, no one packet received yet
Failure /** No connection, no one correct packet received for last period */ = 2, //! \~russian Неизвестно, еще не получен ни один пакет
Bad /** Bad connection, correct packets received <= 20% */ = 3, Unknown = 1,
Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, //! \~english No connection, no one correct packet received for last period
Good /** Good connection, correct packets received > 80% */ = 5 //! \~russian Нет соединения, за последний период не получено ни одного корректного пакета
Failure = 2,
//! \~english Bad connection, correct packets received <= 20%
//! \~russian Плохое соединение, корректных пакетов получено <= 20%
Bad = 3,
//! \~english Average connection, correct packets received > 20% and <= 80%
//! \~russian Среднее соединение, корректных пакетов получено > 20% и <= 80%
Average = 4,
//! \~english Good connection, correct packets received > 80%
//! \~russian Хорошее соединение, корректных пакетов получено > 80%
Good = 5
}; };
//! Information about current diagnostics state //! \~english Information about current diagnostics state
//! \~russian Информация о текущем состоянии диагностики
struct PIP_EXPORT State { struct PIP_EXPORT State {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
State(); State();
//! \~english Immediate frequency in Hz
//! \~russian Мгновенная частота в Гц
float immediate_freq = 0.f; float immediate_freq = 0.f;
//! \~english Integral frequency in Hz
//! \~russian Интегральная частота в Гц
float integral_freq = 0.f; float integral_freq = 0.f;
//! \~english Received packets per second
//! \~russian Принятых пакетов в секунду
ullong received_packets_per_sec = 0ull; ullong received_packets_per_sec = 0ull;
//! \~english Total received packets count
//! \~russian Общее количество принятых пакетов
ullong received_packets = 0ull; ullong received_packets = 0ull;
//! \~english Total received wrong packets count
//! \~russian Общее количество неправильно принятых пакетов
ullong received_packets_wrong = 0ull; ullong received_packets_wrong = 0ull;
//! \~english Received bytes per second
//! \~russian Принятых байт в секунду
ullong received_bytes_per_sec = 0ull; ullong received_bytes_per_sec = 0ull;
//! \~english Total received bytes count
//! \~russian Общее количество принятых байт
ullong received_bytes = 0ull; ullong received_bytes = 0ull;
//! \~english Total received wrong bytes count
//! \~russian Общее количество неправильно принятых байт
ullong received_bytes_wrong = 0ull; ullong received_bytes_wrong = 0ull;
//! \~english Sended packets per second
//! \~russian Отправленных пакетов в секунду
ullong sended_packets_per_sec = 0ull; ullong sended_packets_per_sec = 0ull;
//! \~english Total sended packets count
//! \~russian Общее количество отправленных пакетов
ullong sended_packets = 0ull; ullong sended_packets = 0ull;
//! \~english Sended bytes per second
//! \~russian Отправленных байт в секунду
ullong sended_bytes_per_sec = 0ull; ullong sended_bytes_per_sec = 0ull;
//! \~english Total sended bytes count
//! \~russian Общее количество отправленных байт
ullong sended_bytes = 0ull; ullong sended_bytes = 0ull;
//! \~english Receive speed string in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Строка скорости приема в формате "n {B|kB|MB|GB|TB}/s"
PIString receive_speed; PIString receive_speed;
//! \~english Send speed string in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Строка скорости отправки в формате "n {B|kB|MB|GB|TB}/s"
PIString send_speed; PIString send_speed;
//! \~english Current connection quality
//! \~russian Текущее качество соединения
PIDiagnostics::Quality quality = PIDiagnostics::Unknown; PIDiagnostics::Quality quality = PIDiagnostics::Unknown;
}; };
//! Returns current state //! \~english Returns current diagnostics state
//! \~russian Возвращает текущее состояние диагностики
PIDiagnostics::State state() const; PIDiagnostics::State state() const;
//! Returns period of full disconnect in seconds and period of averaging frequency //! \~english Returns period of full disconnect in seconds and period of averaging frequency
//! \~russian Возвращает период полного отключения в секундах и период усреднения частоты
PISystemTime disconnectTimeout() const { return disconn_; } PISystemTime disconnectTimeout() const { return disconn_; }
//! Returns period of full disconnect in seconds and period of averaging frequency //! \~english Set disconnect timeout (deprecated, use PISystemTime version)
//! \~russian Установить таймаут отключения (устаревший, используйте версию с PISystemTime)
void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") { void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") {
setDisconnectTimeout(PISystemTime::fromSeconds(s)); setDisconnectTimeout(PISystemTime::fromSeconds(s));
} }
//! Returns period of full disconnect and period of averaging frequency //! \~english Set disconnect timeout
//! \~russian Установить таймаут отключения
void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); } void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); }
//! Returns connection quality //! \~english Returns connection quality
//! \~russian Возвращает качество соединения
PIDiagnostics::Quality quality() const; PIDiagnostics::Quality quality() const;
//! Returns receive speed in format "n {B|kB|MB|GB|TB}/s" //! \~english Returns receive speed in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Возвращает скорость приема в формате "n {B|kB|MB|GB|TB}/s"
PIString receiveSpeed() const; PIString receiveSpeed() const;
//! Returns send speed in format "n {B|kB|MB|GB|TB}/s" //! \~english Returns send speed in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Возвращает скорость отправки в формате "n {B|kB|MB|GB|TB}/s"
PIString sendSpeed() const; PIString sendSpeed() const;
EVENT_HANDLER0(void, start);
EVENT_HANDLER1(void, start, PISystemTime, interval);
EVENT_HANDLER0(void, reset);
EVENT_HANDLER1(void, received, int, size) { received(size, true); }
EVENT_HANDLER2(void, received, int, size, bool, correct);
EVENT_HANDLER1(void, sended, int, size);
EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \handlers //! \handlers
//! \{ //! \{
//! \fn void start(double msecs = 1000.) //! \fn void start()
//! \brief Start diagnostics evaluations with period "msecs" milliseconds //! \~english Start diagnostics with default period (1000ms)
//! \~russian Запустить диагностику с периодом по умолчанию (1000мс)
EVENT_HANDLER0(void, start);
//! \fn void start(PISystemTime interval)
//! \~english Start diagnostics with specified period
//! \~russian Запустить диагностику с указанным периодом
EVENT_HANDLER1(void, start, PISystemTime, interval);
//! \fn void reset() //! \fn void reset()
//! \brief Reset diagnostics counters //! \~english Reset diagnostics counters
//! \~russian Сбросить счетчики диагностики
EVENT_HANDLER0(void, reset);
//! \fn void received(int size, bool correct = true) //! \fn void received(int size)
//! \brief Notify diagnostics about "correct" corected received packet //! \~english Notify diagnostics about received packet
//! \~russian Уведомить диагностику о принятом пакете
EVENT_HANDLER1(void, received, int, size) { received(size, true); }
//! \fn void received(int size, bool correct)
//! \~english Notify diagnostics about received packet with correctness flag
//! \~russian Уведомить диагностику о принятом пакете с флагом корректности
EVENT_HANDLER2(void, received, int, size, bool, correct);
//! \fn void sended(int size) //! \fn void sended(int size)
//! \brief Notify diagnostics about sended packet //! \~english Notify diagnostics about sended packet
//! \~russian Уведомить диагностику об отправленном пакете
EVENT_HANDLER1(void, sended, int, size);
//! \} //! \}
//! \events //! \events
//! \{ //! \{
//! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) //! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
//! \brief Raise on change receive quality from "old_quality" to "new_quality" //! \~english Emitted when receive quality changes
//! \~russian Генерируется при изменении качества приема
EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \} //! \}
private: private:
//! \~english Internal structure for packet statistics history
//! \~russian Внутренняя структура для истории статистики пакетов
struct PIP_EXPORT Entry { struct PIP_EXPORT Entry {
//! \~english Number of correct bytes
//! \~russian Количество корректных байт
ullong bytes_ok = 0; ullong bytes_ok = 0;
//! \~english Number of wrong bytes
//! \~russian Количество неправильных байт
ullong bytes_fail = 0; ullong bytes_fail = 0;
//! \~english Count of correct packets
//! \~russian Количество корректных пакетов
uint cnt_ok = 0; uint cnt_ok = 0;
//! \~english Count of wrong packets
//! \~russian Количество неправильных пакетов
uint cnt_fail = 0; uint cnt_fail = 0;
//! \~english Flag indicating if entry is empty
//! \~russian Флаг, указывающий, что запись пустая
bool empty = true; bool empty = true;
}; };
//! \~english Equality operator for Entry structure
//! \~russian Оператор равенства для структуры Entry
friend bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
//! \~english Inequality operator for Entry structure
//! \~russian Оператор неравенства для структуры Entry
friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
//! \~english Less-than operator for Entry structure
//! \~russian Оператор меньше для структуры Entry
friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
//! \~english Timer tick handler
//! \~russian Обработчик тика таймера
void tick(int) override; void tick(int) override;
//! \~english Calculate history statistics
//! \~russian Вычислить статистику истории
Entry calcHistory(PIQueue<Entry> & hist, int & cnt); Entry calcHistory(PIQueue<Entry> & hist, int & cnt);
//! \~english Property changed handler
//! \~russian Обработчик изменения свойства
void propertyChanged(const char *) override; void propertyChanged(const char *) override;
//! \~english Change disconnect timeout
//! \~russian Изменить таймаут отключения
void changeDisconnectTimeout(PISystemTime disct); void changeDisconnectTimeout(PISystemTime disct);
//! \~english History queue for received packets
//! \~russian Очередь истории для принятых пакетов
PIQueue<Entry> history_rec, history_send; PIQueue<Entry> history_rec, history_send;
//! \~english Disconnect timeout
//! \~russian Таймаут отключения
PISystemTime disconn_; PISystemTime disconn_;
//! \~english Current state
//! \~russian Текущее состояние
State cur_state; State cur_state;
//! \~english Mutex for state access protection
//! \~russian Мьютекс для защиты доступа к состоянию
mutable PIMutex mutex_state; mutable PIMutex mutex_state;
}; };

View File

@@ -29,45 +29,61 @@
#include "pibytearray.h" #include "pibytearray.h"
#include "pip_io_utils_export.h" #include "pip_io_utils_export.h"
//! \~english Base class for ethernet utils
//! \~russian Базовый класс для утилит ethernet
class PIP_IO_UTILS_EXPORT PIEthUtilBase { class PIP_IO_UTILS_EXPORT PIEthUtilBase {
public: public:
//! \~english Constructs PIEthUtilBase
//! \~russian Создает PIEthUtilBase
PIEthUtilBase(); PIEthUtilBase();
//! \~english Destructor
//! \~russian Деструктор
~PIEthUtilBase(); ~PIEthUtilBase();
//! Set crypt layer enabled //! \~english Set crypt layer enabled
//! \~russian Включить слой шифрования
void setCryptEnabled(bool on); void setCryptEnabled(bool on);
//! Enable crypt layer //! \~english Enable crypt layer
//! \~russian Включить слой шифрования
void cryptEnable(); void cryptEnable();
//! Disable crypt layer //! \~english Disable crypt layer
//! \~russian Выключить слой шифрования
void cryptDisable(); void cryptDisable();
//! Returns if crypt layer enabled //! \~english Returns if crypt layer enabled
//! \~russian Возвращает, включен ли слой шифрования
bool isCryptEnabled() const; bool isCryptEnabled() const;
//! Set crypt layer key to \"k\" //! \~english Set crypt layer key to "k"
//! \~russian Установить ключ шифрования в "k"
void setCryptKey(const PIByteArray & k); void setCryptKey(const PIByteArray & k);
//! Generate crypt layer key by \a PICrypt::hash and //! \~english Generate crypt layer key by \a PICrypt::hash and set crypt layer enabled
//! set crypt layer enabled //! \~russian Сгенерировать ключ шифрования с помощью \a PICrypt::hash и включить шифрование
void createCryptKey(const PIString & k); void createCryptKey(const PIString & k);
//! Returns crypt layer key //! \~english Returns crypt layer key
//! \~russian Возвращает ключ шифрования
PIByteArray cryptKey() const; PIByteArray cryptKey() const;
//! \brief Returns addition size for crypted data. //! \~english Returns addition size for crypted data
//! \~russian Возвращает дополнительный размер для зашифрованных данных
static size_t cryptSizeAddition(); static size_t cryptSizeAddition();
protected: protected:
/*! \brief Returns encrypted data if layer enabled, //! \~english Returns encrypted data if layer enabled, otherwise returns unchanged "data"
* otherwise returns unchanged \"data\" */ //! \~russian Возвращает зашифрованные данные, если слой включен, иначе возвращает неизмененные "data"
PIByteArray cryptData(const PIByteArray & data); PIByteArray cryptData(const PIByteArray & data);
/*! \brief Returns decrypted data if layer enabled, //! \~english Returns decrypted data if layer enabled, otherwise returns unchanged "data". If decryption was unsuccessful returns empty
* otherwise returns unchanged \"data\". If decryption //! %PIByteArray
* was unsuccessfull returns empty %PIByteArray. */ //! \~russian Возвращает расшифрованные данные, если слой включен, иначе возвращает неизмененные "data". Если расшифровка неуспешна,
//! возвращает пустой %PIByteArray
PIByteArray decryptData(const PIByteArray & data); PIByteArray decryptData(const PIByteArray & data);
private: private:

View File

@@ -31,25 +31,40 @@
#define __PIFILETRANSFER_VERSION 2 #define __PIFILETRANSFER_VERSION 2
//! \~english Class for send and receive files and directories via \a PIBaseTransfer
//! \~russian Класс для отправки и приема файлов и папок с помощью \a PIBaseTransfer
class PIP_EXPORT PIFileTransfer: public PIBaseTransfer { class PIP_EXPORT PIFileTransfer: public PIBaseTransfer {
PIOBJECT_SUBCLASS(PIFileTransfer, PIBaseTransfer); PIOBJECT_SUBCLASS(PIFileTransfer, PIBaseTransfer);
public: public:
//! \~english Constructs empty file transfer
//! \~russian Создает пустой transfer файлов
PIFileTransfer(); PIFileTransfer();
//! \~english Destructor
//! \~russian Деструктор
~PIFileTransfer(); ~PIFileTransfer();
//! \~english Step type for file transfer
//! \~russian Тип шага для передачи файлов
enum StepType { enum StepType {
pft_None, pft_None,
pft_Description, pft_Description,
pft_Data pft_Data
}; };
//! \~english File information structure
//! \~russian Структура информации о файле
struct PIP_EXPORT PFTFileInfo: public PIFile::FileInfo { struct PIP_EXPORT PFTFileInfo: public PIFile::FileInfo {
//! \~english Constructor
//! \~russian Конструктор
PFTFileInfo(const PIFile::FileInfo & fi = PIFile::FileInfo()): PIFile::FileInfo(fi) {} PFTFileInfo(const PIFile::FileInfo & fi = PIFile::FileInfo()): PIFile::FileInfo(fi) {}
PIString dest_path; PIString dest_path;
}; };
#pragma pack(push, 1) #pragma pack(push, 1)
//! \~english File transfer header structure
//! \~russian Структура заголовка передачи файлов
struct PIP_EXPORT PFTHeader { struct PIP_EXPORT PFTHeader {
union { union {
struct { struct {
@@ -60,6 +75,8 @@ public:
}; };
int step; // PacketType int step; // PacketType
int session_id; int session_id;
//! \~english Check if signature is valid
//! \~russian Проверка валидности подписи
bool check_sig() { bool check_sig() {
if (sig[0] != sign[0] || sig[1] != sign[1] || sig[2] != sign[2] || version != __PIFILETRANSFER_VERSION) return false; if (sig[0] != sign[0] || sig[1] != sign[1] || sig[2] != sign[2] || version != __PIFILETRANSFER_VERSION) return false;
return true; return true;
@@ -67,23 +84,64 @@ public:
}; };
#pragma pack(pop) #pragma pack(pop)
//! \~english Send file
//! \~russian Отправить файл
bool send(const PIFile & file); bool send(const PIFile & file);
//! \~english Send file by path
//! \~russian Отправить файл по пути
bool send(const PIString & file); bool send(const PIString & file);
//! \~english Send files list
//! \~russian Отправить список файлов
bool send(const PIStringList & files); bool send(const PIStringList & files);
//! \~english Send file info
//! \~russian Отправить информацию о файле
bool send(PIFile::FileInfo entry) { return send(PIVector<PIFile::FileInfo>() << entry); } bool send(PIFile::FileInfo entry) { return send(PIVector<PIFile::FileInfo>() << entry); }
//! \~english Send file info vector
//! \~russian Отправить вектор информации о файлах
bool send(PIVector<PIFile::FileInfo> entries); bool send(PIVector<PIFile::FileInfo> entries);
//! \~english Set directory
//! \~russian Установить директорию
void setDirectory(const PIDir & d) { dir = d; } void setDirectory(const PIDir & d) { dir = d; }
//! \~english Set directory by path
//! \~russian Установить директорию по пути
void setDirectory(const PIString & path) { dir.setDir(path); } void setDirectory(const PIString & path) { dir.setDir(path); }
//! \~english Get directory
//! \~russian Получить директорию
PIDir directory() const { return dir; } PIDir directory() const { return dir; }
//! \~english Check if transfer is started
//! \~russian Проверить, начата ли передача
bool isStarted() const { return started_; } bool isStarted() const { return started_; }
//! \~english Get current file name
//! \~russian Получить имя текущего файла
PIString curFile() const; PIString curFile() const;
//! \~english Get total bytes of current file
//! \~russian Получить общее количество байт текущего файла
llong bytesFileAll() const { return bytes_file_all; } llong bytesFileAll() const { return bytes_file_all; }
//! \~english Get current bytes of current file
//! \~russian Получить текущие байты текущего файла
llong bytesFileCur() const { return bytes_file_cur; } llong bytesFileCur() const { return bytes_file_cur; }
//! \~english Get pointer to current file name
//! \~russian Получить указатель на имя текущего файла
const PIString * curFile_ptr() const { return &cur_file_string; } const PIString * curFile_ptr() const { return &cur_file_string; }
//! \~english Get pointer to total bytes of current file
//! \~russian Получить указатель на общее количество байт текущего файла
const llong * bytesFileAll_ptr() const { return &bytes_file_all; } const llong * bytesFileAll_ptr() const { return &bytes_file_all; }
//! \~english Get pointer to current bytes of current file
//! \~russian Получить указатель на текущие байты текущего файла
const llong * bytesFileCur_ptr() const { return &bytes_file_cur; } const llong * bytesFileCur_ptr() const { return &bytes_file_cur; }
EVENT(receiveFilesStarted); EVENT(receiveFilesStarted);

View File

@@ -34,31 +34,45 @@
class PIEthernet; class PIEthernet;
//! \~english Ethernet device
//! \~russian Устройство Ethernet
class PIP_IO_UTILS_EXPORT PIPackedTCP: public PIIODevice { class PIP_IO_UTILS_EXPORT PIPackedTCP: public PIIODevice {
PIIODEVICE(PIPackedTCP, "ptcp"); PIIODEVICE(PIPackedTCP, "ptcp");
public: public:
//! \brief Role of %PIPackedTCP //! \~english Role of %PIPackedTCP
//! \~russian Роль %PIPackedTCP
enum Role { enum Role {
Client /** TCP client */, Client /** TCP client */,
Server /** TCP server for one client */ Server /** TCP server for one client */
}; };
//! Contructs %PIPackedTCP with "role" and "addr" address //! \~english Constructs %PIPackedTCP with "role" and "addr" address
//! \~russian Создает %PIPackedTCP с ролью "role" и адресом "addr"
explicit PIPackedTCP(Role role = Client, const PINetworkAddress & addr = {}); explicit PIPackedTCP(Role role = Client, const PINetworkAddress & addr = {});
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIPackedTCP(); virtual ~PIPackedTCP();
//! Set server address for Server role or connect address for Client //! \~english Set server address for Server role or connect address for Client
//! \~russian Установить адрес сервера для роли Server или адрес подключения для Client
void setAddress(const PINetworkAddress & addr); void setAddress(const PINetworkAddress & addr);
//! \~english Check if connected
//! \~russian Проверить подключение
bool isConnected() const; bool isConnected() const;
//! \~english Check if connecting
//! \~russian Проверить подключение
bool isConnecting() const; bool isConnecting() const;
//! Returns read address in format "i.i.i.i:p" //! \~english Returns read address in format "i.i.i.i:p"
//! \~russian Возвращает адрес чтения в формате "i.i.i.i:p"
PINetworkAddress address() const { return m_addr; } PINetworkAddress address() const { return m_addr; }
//! Returns %PIEthernet type //! \~english Returns %PIEthernet type
//! \~russian Возвращает тип %PIEthernet
Role role() const { return m_role; } Role role() const { return m_role; }
EVENT0(connected); EVENT0(connected);

View File

@@ -1,9 +1,13 @@
/*! \file pipacketextractor.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file pipacketextractor.h
* \~english Packets extractor //! \brief
* \~russian Извлекатель пакетов //! \~english Packets extractor
*/ //! \~russian Извлекатель пакетов
//! \details
//! \~english The PIPacketExtractor class provides packet recognition from data stream using various algorithms.
//! \~russian Класс PIPacketExtractor предоставляет распознавание пакетов из потока данных с использованием различных алгоритмов.
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Packets extractor Packets extractor
@@ -28,25 +32,35 @@
#include "piiodevice.h" #include "piiodevice.h"
/// TODO: написать документацию, тут ничего не понятно //! \~english Header validation function type
/// Pass SourceHeaderPtr, ReceivedHeaderPtr, HeaderSize. //! \~russian Тип функции проверки заголовка
/// Return size of payload if packet is correct, or -1 if incorrect.
typedef std::function<int(const uchar *, const uchar *, int)> PacketExtractorHeaderFunc; typedef std::function<int(const uchar *, const uchar *, int)> PacketExtractorHeaderFunc;
/// Pass ReceivedDataPtr, DataSize. //! \~english Payload validation function type
/// Return true if packet is correct, false otherwise. //! \~russian Тип функции проверки полезной нагрузки
typedef std::function<bool(const uchar *, int)> PacketExtractorPayloadFunc; typedef std::function<bool(const uchar *, int)> PacketExtractorPayloadFunc;
/// Pass SourceFooterPtr, ReceivedFooterPtr, FooterSize. //! \~english Footer validation function type
/// Return true if packet is correct, false otherwise. //! \~russian Тип функции проверки окончания
typedef std::function<bool(const uchar *, const uchar *, int)> PacketExtractorFooterFunc; typedef std::function<bool(const uchar *, const uchar *, int)> PacketExtractorFooterFunc;
//! \~english Packets extractor
//! \~russian Извлекатель пакетов
//! \details
//! \~english The PIPacketExtractor class provides packet recognition from data stream using various algorithms such as header detection,
//! footer detection, size-based extraction, and timeout-based extraction.
//! \~russian Класс PIPacketExtractor предоставляет распознавание пакетов из потока данных с использованием различных алгоритмов, таких как
//! обнаружение заголовка, обнаружение окончания, извлечение по размеру и извлечение по таймауту.
class PIP_EXPORT PIPacketExtractor: public PIIODevice { class PIP_EXPORT PIPacketExtractor: public PIIODevice {
PIIODEVICE(PIPacketExtractor, "pckext"); PIIODEVICE(PIPacketExtractor, "pckext");
friend class PIConnection; friend class PIConnection;
public: public:
//! Extract algorithms //! \~english Extract algorithms
//! \~russian Алгоритмы извлечения
//! \details
//! \~english Defines the packet extraction algorithms supported by PIPacketExtractor
//! \~russian Определяет алгоритмы извлечения пакетов, поддерживаемые PIPacketExtractor
enum SplitMode { enum SplitMode {
None /** No data processing */, None /** No data processing */,
Header /** Detect packets with \a header() and following \a payloadSize() */, Header /** Detect packets with \a header() and following \a payloadSize() */,
@@ -56,73 +70,143 @@ public:
Timeout /** Wait for first read, then read for \a timeout() */ Timeout /** Wait for first read, then read for \a timeout() */
}; };
//! Contructs extractor with child device "device_" and extract algorithm "mode" //! \~english Constructs extractor with child device "device_" and extract algorithm "mode"
//! \~russian Создает экстрактор с дочерним устройством "device_" и алгоритмом извлечения "mode"
explicit PIPacketExtractor(PIIODevice * device_ = nullptr, SplitMode mode = None); explicit PIPacketExtractor(PIIODevice * device_ = nullptr, SplitMode mode = None);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIPacketExtractor() { stop(); } virtual ~PIPacketExtractor() { stop(); }
//! Returns child %device //! \~english Returns child %device
//! \~russian Возвращает дочернее устройство
PIIODevice * device() { return dev; } PIIODevice * device() { return dev; }
//! Set child %device to "device_" //! \~english Set child %device to "device_"
//! \~russian Установить дочернее устройство в "device_"
void setDevice(PIIODevice * device_); void setDevice(PIIODevice * device_);
//! \~english Get bytes available
//! \~russian Получить доступные байты
//! \details
//! \~english Returns the number of bytes available for reading from the child device
//! \~russian Возвращает количество байт, доступных для чтения из дочернего устройства
ssize_t bytesAvailable() const override; ssize_t bytesAvailable() const override;
//! \~english Set header check function
//! \~russian Установить функцию проверки заголовка
//! \details
//! \~english Sets the callback function used to validate packet headers
//! \~russian Устанавливает функцию обратного вызова, используемую для проверки заголовков пакетов
void setHeaderCheckSlot(PacketExtractorHeaderFunc f) { func_header = f; } void setHeaderCheckSlot(PacketExtractorHeaderFunc f) { func_header = f; }
//! \~english Set payload check function
//! \~russian Установить функцию проверки полезной нагрузки
//! \details
//! \~english Sets the callback function used to validate packet payload
//! \~russian Устанавливает функцию обратного вызова, используемую для проверки полезной нагрузки пакетов
void setPayloadCheckSlot(PacketExtractorPayloadFunc f) { func_payload = f; } void setPayloadCheckSlot(PacketExtractorPayloadFunc f) { func_payload = f; }
//! \~english Set footer check function
//! \~russian Установить функцию проверки окончания
//! \details
//! \~english Sets the callback function used to validate packet footers
//! \~russian Устанавливает функцию обратного вызова, используемую для проверки окончаний пакетов
void setFooterCheckSlot(PacketExtractorFooterFunc f) { func_footer = f; } void setFooterCheckSlot(PacketExtractorFooterFunc f) { func_footer = f; }
//! Set extract algorithm //! \~english Set extract algorithm
//! \~russian Установить алгоритм извлечения
//! \details
//! \~english Sets the packet extraction algorithm to be used
//! \~russian Устанавливает алгоритм извлечения пакетов, который будет использоваться
void setSplitMode(SplitMode mode) { setProperty("splitMode", int(mode)); } void setSplitMode(SplitMode mode) { setProperty("splitMode", int(mode)); }
//! Set payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms //! \~english Set payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms
//! \~russian Установить размер полезной нагрузки
//! \details
//! \~english Sets the expected payload size for Header and Footer extraction algorithms
//! \~russian Устанавливает ожидаемый размер полезной нагрузки для алгоритмов извлечения Header и Footer
void setPayloadSize(int size); void setPayloadSize(int size);
//! Set header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms //! \~english Set header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms
//! \~russian Установить данные заголовка
//! \details
//! \~english Sets the header pattern used to identify packet start
//! \~russian Устанавливает шаблон заголовка, используемый для идентификации начала пакета
void setHeader(const PIByteArray & data); void setHeader(const PIByteArray & data);
//! Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms //! \~english Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms
//! \~russian Установить данные окончания
//! \details
//! \~english Sets the footer pattern used to identify packet end
//! \~russian Устанавливает шаблон окончания, используемый для идентификации конца пакета
void setFooter(const PIByteArray & data); void setFooter(const PIByteArray & data);
//! Set timeout, used for PIPacketExtractor::Timeout algorithm //! \~english Set timeout, used for PIPacketExtractor::Timeout algorithm
//! \~russian Установить таймаут
//! \details Sets the timeout duration for the Timeout extraction algorithm
//! \~russian Устанавливает длительность таймаута для алгоритма извлечения Timeout
void setTimeout(PISystemTime tm) { setProperty("timeout", tm); } void setTimeout(PISystemTime tm) { setProperty("timeout", tm); }
//! Returns current extract algorithm //! \~english Returns current extract algorithm
//! \~russian Возвращает текущий алгоритм извлечения
//! \details
//! \~english Returns the currently configured packet extraction algorithm
//! \~russian Возвращает текущий настроенный алгоритм извлечения пакетов
SplitMode splitMode() const { return mode_; } SplitMode splitMode() const { return mode_; }
//! Returns current payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer and PIPacketExtractor::Size //! \~english Returns current payload size
//! algorithms //! \~russian Возвращает текущий размер полезной нагрузки
//! \details
//! \~english Returns the expected payload size used by Header and Footer algorithms
//! \~russian Возвращает ожидаемый размер полезной нагрузки, используемый алгоритмами Header и Footer
int payloadSize() const { return dataSize; } int payloadSize() const { return dataSize; }
//! Returns current header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms //! \~english Returns current header data
//! \~russian Возвращает текущие данные заголовка
//! \details
//! \~english Returns the configured header pattern
//! \~russian Возвращает настроенный шаблон заголовка
PIByteArray header() const { return src_header; } PIByteArray header() const { return src_header; }
//! Returns current footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms //! \~english Returns current footer data
//! \~russian Возвращает текущие данные окончания
//! \details
//! \~english Returns the configured footer pattern
//! \~russian Возвращает настроенный шаблон окончания
PIByteArray footer() const { return src_footer; } PIByteArray footer() const { return src_footer; }
//! Returns current timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm //! \~english Returns current timeout in milliseconds
//! \~russian Возвращает текущий таймаут в миллисекундах
//! \details
//! \~english Returns the configured timeout duration
//! \~russian Возвращает настроенную длительность таймаута
PISystemTime timeout() const { return time_; } PISystemTime timeout() const { return time_; }
//! Returns missed by validating functions bytes count //! \~english Returns missed by validating functions bytes count
//! \~russian Возвращает количество байт, пропущенных функциями проверки
//! \details
//! \~english Returns the number of bytes that were skipped during validation failures
//! \~russian Возвращает количество байт, которые были пропущены при неудачных проверках
ullong missedBytes() const { return missed; } ullong missedBytes() const { return missed; }
//! Add data to extractor, raise \a packetReceived() if packet is ready //! \~english Add data to extractor, raise \a packetReceived() if packet is ready
//! \~russian Добавить данные в экстрактор, вызвать \a packetReceived() если пакет готов
void appendData(const uchar * d, int s) { threadedRead(d, s); } void appendData(const uchar * d, int s) { threadedRead(d, s); }
//! Add data to extractor, raise \a packetReceived() if packet is ready //! \~english Add data to extractor, raise \a packetReceived() if packet is ready
//! \~russian Добавить данные в экстрактор, вызвать \a packetReceived() если пакет готов
void appendData(const PIByteArray & data) { threadedRead(data.data(), data.size_s()); } void appendData(const PIByteArray & data) { threadedRead(data.data(), data.size_s()); }
EVENT2(packetReceived, const uchar *, data, int, size);
//! \events //! \events
//! \{ //! \{
//! \fn void packetReceived(const uchar * data, int size) //! \fn void packetReceived(const uchar * data, int size)
//! \brief Raise on successfull \a packetValidate() function //! \brief Raise on successfull \a packetValidate() function
EVENT2(packetReceived, const uchar *, data, int, size);
//! \} //! \}

View File

@@ -1,9 +1,16 @@
/*! \file piparsehelper.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file piparsehelper.h
* \~english Helper class to automate structs receive //! \brief
* \~russian Класс для автоматизации приема структур //! \~english Template helper class to automate structs receive and data packet deserialization
*/ //! \~russian Шаблонный класс для автоматизации приема структур и десериализации пакетов данных
//! \details
//! \~english The PIParseHelper class provides a mechanism to deserialize data packets and automatically invoke assigned handler methods. It
//! supports member functions, lambda functions, and functors with 0 or 1 arguments.
//! \~russian Класс PIParseHelper предоставляет механизм для десериализации пакетов данных и автоматического вызова назначаемых
//! обработчиков. Поддерживаются member-функции, lambda-функции и функторы с 0 или 1 аргументами.
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Helper class to automate structs receive Helper class to automate structs receive
@@ -30,60 +37,49 @@
#include "pip_io_utils_export.h" #include "pip_io_utils_export.h"
/** \class PIParseHelper //! \class PIParseHelper
* \brief Helper class to automate structs receive //! \~english Template helper class to automate structs receive and data packet deserialization
* //! \~russian Шаблонный класс для автоматизации приема структур и десериализации пакетов данных
* //! \details
* \section PIParseHelper_synopsis Synopsis //! \~english The PIParseHelper class provides a mechanism to deserialize data packets and automatically invoke assigned handler methods. It
* This class helps to deserialize and invoke neccessarily methods. //! supports member functions, lambda functions, and functors with 0 or 1 arguments. The class eliminates the need for switch-case
* //! statements by mapping keys to event handlers via assign() calls. Data type extraction is automatically performed from the handler
* Data packets with header and various data types can be automated by this class. //! signature.
* Every key value mapped to object member function, lambda-function or functor. //! \~russian Класс PIParseHelper предоставляет механизм для десериализации пакетов данных и автоматического вызова назначаемых
* //! обработчиков. Поддерживаются member-функции, lambda-функции и функторы с 0 или 1 аргументами. Класс устраняет необходимость операторов
* This class can remove \b switch-case with deserialization code and //! switch-case, сопоставляя ключи с обработчиками событий через вызовы assign(). Извлечение типа данных автоматически выполняется из
* replace it with several \a assign() calls, binded to ready-to-use event handlers. //! сигнатуры обработчика.
* Moreover data type automatic takes from event handler or lambda argument. One should
* only make \"PIByteArray & operator <<()\" with used types, deserialization will be
* performed by %PIParseHelper.
*
*
* \section PIParseHelper_usage Usage
*
* Create instance of %PIParseHelper, or subclass.
*
* In \a assign() methods you can use object member function, lambda-function
* or functor with 0 or 1 arguments,
*
*
* \section PIParseHelper_lambda Lambda-functions
* \code assign(1, [this](const SomeStruct & s){}) \endcode
*
*
* \section PIParseHelper_examples Examples
* First example describes subclass variant. As one can see, it`s a single place to change
* type of received data - event handler argument.
* \snippet piparsehelper.cpp 0
*
* Second example show separate variant:
* \snippet piparsehelper.cpp 1
*
**/
template<typename Key> template<typename Key>
class PIParseHelper { class PIParseHelper {
public: public:
//! \brief Construct %PIParseHelper //! \~english Construct PIParseHelper
//! \~russian Создать PIParseHelper
PIParseHelper() {} PIParseHelper() {}
//! \brief Assign key \"key\" to lambda-function \"func\" without arguments //! \~english Assign key to lambda-function without arguments
//! \~russian Сопоставить ключ с lambda-функцией без аргументов
//! \param key The key to assign
//! \param func The lambda function to call when key is parsed
//! \~english \param key Ключ для сопоставления
//! \~russian \param key Ключ для сопоставления
//! \~english \param func Lambda-функция, вызываемая при разборе ключа
//! \~russian \param func Lambda-функция, вызываемая при разборе ключа
void assign(Key key, std::function<void()> func) { void assign(Key key, std::function<void()> func) {
auto lf = [func](PIByteArray) { func(); }; auto lf = [func](PIByteArray) { func(); };
functions[key] << lf; functions[key] << lf;
} }
//! \brief Assign key \"key\" to lambda-function \"func\" with 1 argument //! \~english Assign key to lambda-function with 1 argument
//! \~russian Сопоставить ключ с lambda-функцией с 1 аргументом
//! \param key The key to assign
//! \param func The lambda function to call when key is parsed
//! \~english \param key Ключ для сопоставления
//! \~russian \param key Ключ для сопоставления
//! \~english \param func Lambda-функция, вызываемая при разборе ключа
//! \~russian \param func Lambda-функция, вызываемая при разборе ключа
template<typename T> template<typename T>
void assign(Key key, std::function<void(const T &)> func) { void assign(Key key, std::function<void(const T &)> func) {
auto lf = [func](PIByteArray data) { auto lf = [func](PIByteArray data) {
@@ -97,7 +93,17 @@ public:
} }
//! \brief Assign key \"key\" to member function of object \"obj\" without arguments //! \~english Assign key to member function of object without arguments
//! \~russian Сопоставить ключ с member-функцией объекта без аргументов
//! \param key The key to assign
//! \param obj Pointer to the object
//! \param member_func Pointer to the member function
//! \~english \param key Ключ для сопоставления
//! \~russian \param key Ключ для сопоставления
//! \~english \param obj Указатель на объект
//! \~russian \param obj Указатель на объект
//! \~english \param member_func Указатель на member-функцию
//! \~russian \param member_func Указатель на member-функцию
template<typename O> template<typename O>
void assign(Key key, O * obj, void (O::*member_func)()) { void assign(Key key, O * obj, void (O::*member_func)()) {
auto lf = [member_func, obj](PIByteArray) { (obj->*member_func)(); }; auto lf = [member_func, obj](PIByteArray) { (obj->*member_func)(); };
@@ -105,7 +111,17 @@ public:
} }
//! \brief Assign key \"key\" to member function of object \"obj\" with 1 argument //! \~english Assign key to member function of object with 1 argument
//! \~russian Сопоставить ключ с member-функцией объекта с 1 аргументом
//! \param key The key to assign
//! \param obj Pointer to the object
//! \param member_func Pointer to the member function
//! \~english \param key Ключ для сопоставления
//! \~russian \param key Ключ для сопоставления
//! \~english \param obj Указатель на объект
//! \~russian \param obj Указатель на объект
//! \~english \param member_func Указатель на member-функцию
//! \~russian \param member_func Указатель на member-функцию
template<typename T, typename O> template<typename T, typename O>
void assign(Key key, O * obj, void (O::*member_func)(const T &)) { void assign(Key key, O * obj, void (O::*member_func)(const T &)) {
auto lf = [member_func, obj](PIByteArray data) { auto lf = [member_func, obj](PIByteArray data) {
@@ -119,14 +135,28 @@ public:
} }
//! \brief Assign key \"key\" to functor \"func\" with 0 or 1 argument //! \~english Assign key to functor with 0 or 1 argument
//! \~russian Сопоставить ключ с функтором с 0 или 1 аргументом
//! \param key The key to assign
//! \param func The functor to call when key is parsed
//! \~english \param key Ключ для сопоставления
//! \~russian \param key Ключ для сопоставления
//! \~english \param func Функтор, вызываемый при разборе ключа
//! \~russian \param func Функтор, вызываемый при разборе ключа
template<typename L> template<typename L>
void assign(Key key, L func) { void assign(Key key, L func) {
return assign(key, toStdFunction(func)); return assign(key, toStdFunction(func));
} }
//! \brief Deserialize data and invoke assigned to \"key\" methods //! \~english Deserialize data and invoke assigned methods
//! \~russian Десериализовать данные и вызвать назначенные методы
//! \param key The key to look up
//! \param ba The byte array to deserialize
//! \~english \param key Ключ для поиска
//! \~russian \param key Ключ для поиска
//! \~english \param ba Байтовый массив для десериализации
//! \~russian \param ba Байтовый массив для десериализации
void parse(Key key, PIByteArray ba) { void parse(Key key, PIByteArray ba) {
auto fl = functions.value(key); auto fl = functions.value(key);
for (auto f: fl) for (auto f: fl)
@@ -134,8 +164,11 @@ public:
} }
private: private:
//! \~english Map of assigned functions
//! \~russian Карта назначенных функций
PIMap<Key, PIVector<std::function<void(PIByteArray)>>> functions; PIMap<Key, PIVector<std::function<void(PIByteArray)>>> functions;
}; };
//! \}
#endif // PIPARSEHELPER_H #endif // PIPARSEHELPER_H

View File

@@ -33,45 +33,65 @@
class PIIODevice; class PIIODevice;
//! \~english Stream packer configuration
//! \~russian Конфигурация упаковщика потока
class PIStreamPackerConfig: public PIEthUtilBase { class PIStreamPackerConfig: public PIEthUtilBase {
friend class PIStreamPacker; friend class PIStreamPacker;
public: public:
//! \~english Constructs default configuration
//! \~russian Создает конфигурацию по умолчанию
PIStreamPackerConfig() { PIStreamPackerConfig() {
crypt_size = false; crypt_size = false;
aggressive_optimization = true; aggressive_optimization = true;
max_packet_size = 1400; max_packet_size = 1400;
packet_sign = 0xAFBE; packet_sign = 0xAFBE;
} }
//! Set maximum size of single packet //! \~english Set maximum size of single packet
//! \~russian Установить максимальный размер одного пакета
void setMaxPacketSize(int max_size) { max_packet_size = max_size; } void setMaxPacketSize(int max_size) { max_packet_size = max_size; }
//! Returns maximum size of single packet, default 1400 bytes //! \~english Returns maximum size of single packet, default 1400 bytes
//! \~russian Возвращает максимальный размер одного пакета, по умолчанию 1400 байт
int maxPacketSize() const { return max_packet_size; } int maxPacketSize() const { return max_packet_size; }
//! Set packet sinature //! \~english Set packet signature
//! \~russian Установить подпись пакета
void setPacketSign(ushort sign_) { packet_sign = sign_; } void setPacketSign(ushort sign_) { packet_sign = sign_; }
//! Returns packet sinature, default 0xAFBE //! \~english Returns packet signature, default 0xAFBE
//! \~russian Возвращает подпись пакета, по умолчанию 0xAFBE
ushort packetSign() const { return packet_sign; } ushort packetSign() const { return packet_sign; }
//! Set receive aggressive optimization. If yes then %PIStreamPacker doesn`t //! \~english Set receive aggressive optimization. If yes then %PIStreamPacker doesn`t check every byte in incoming stream but check
//! check every byte in incoming stream but check only begin of each read() //! only begin of each read() result. Default is \b true.
//! result. Default is \b true. //! \~russian Установить агрессивную оптимизацию приема. Если да, то %PIStreamPacker не проверяет каждый байт во входящем потоке, а
//! только начало каждого результата read(). По умолчанию \b true.
void setaAggressiveOptimization(bool yes) { aggressive_optimization = yes; } void setaAggressiveOptimization(bool yes) { aggressive_optimization = yes; }
//! Returns aggressive optimization //! \~english Returns aggressive optimization
//! \~russian Возвращает агрессивную оптимизацию
bool aggressiveOptimization() const { return aggressive_optimization; } bool aggressiveOptimization() const { return aggressive_optimization; }
//! \~english Check if crypt size enabled
//! \~russian Проверить, включен ли размер шифрования
bool cryptSizeEnabled() const { return crypt_size; } bool cryptSizeEnabled() const { return crypt_size; }
//! \~english Set crypt size enabled
//! \~russian Установить включенный размер шифрования
void setCryptSizeEnabled(bool on) { crypt_size = on; } void setCryptSizeEnabled(bool on) { crypt_size = on; }
//! Get configuration //! \~english Get configuration
//! \~russian Получить конфигурацию
const PIStreamPackerConfig & configuration() const { return *this; } const PIStreamPackerConfig & configuration() const { return *this; }
//! \~english Get configuration
//! \~russian Получить конфигурацию
PIStreamPackerConfig & configuration() { return *this; } PIStreamPackerConfig & configuration() { return *this; }
//! Apply configuration //! \~english Apply configuration
//! \~russian Применить конфигурацию
void setConfiguration(const PIStreamPackerConfig & config) { *this = config; } void setConfiguration(const PIStreamPackerConfig & config) { *this = config; }
private: private:
@@ -81,31 +101,40 @@ private:
}; };
//! \~english Simple packet wrap around any PIIODevice
//! \~russian Простая фрагментация пакетов, использует любой PIIODevice
class PIP_IO_UTILS_EXPORT PIStreamPacker class PIP_IO_UTILS_EXPORT PIStreamPacker
: public PIObject : public PIObject
, public PIStreamPackerConfig { , public PIStreamPackerConfig {
PIOBJECT(PIStreamPacker) PIOBJECT(PIStreamPacker)
public: public:
//! Contructs packer and try to assign \"dev\" //! \~english Constructs packer and try to assign "dev"
//! \~russian Создает упаковщик и пытается присвоить "dev"
PIStreamPacker(PIIODevice * dev = nullptr); PIStreamPacker(PIIODevice * dev = nullptr);
//! Returns progress of current packet receive in bytes //! \~english Returns progress of current packet receive in bytes
//! \~russian Возвращает прогресс приема текущего пакета в байтах
int receivePacketProgress() const { return packet.size_s(); } int receivePacketProgress() const { return packet.size_s(); }
//! \~english Clear all buffers
//! \~russian Очистить все буферы
void clear(); void clear();
//! Prepare data for send and raise \a sendRequest() events //! \~english Prepare data for send and raise \a sendRequest() events
//! \~russian Подготовить данные для отправки и вызвать события \a sendRequest()
void send(const PIByteArray & data); void send(const PIByteArray & data);
//! Receive data part. If packet is ready, raise \a packetReceiveEvent() event //! \~english Receive data part. If packet is ready, raise \a packetReceiveEvent() event and \a packetReceived() virtual method
//! and \a packetReceived() virtual method //! \~russian Принять часть данных. Если пакет готов, вызвать событие \a packetReceiveEvent() и виртуальный метод \a packetReceived()
void received(const PIByteArray & data); void received(const PIByteArray & data);
EVENT_HANDLER2(void, received, const uchar *, readed, ssize_t, size); EVENT_HANDLER2(void, received, const uchar *, readed, ssize_t, size);
//! Connect \"dev\" \a PIIODevice::threadedReadEvent() event to \a received() handler //! \~english Connect "dev" \a PIIODevice::threadedReadEvent() event to \a received() handler and \a sendRequest() event to "dev" \a
//! and \a sendRequest() event to \"dev\" \a PIIODevice::write() handler //! PIIODevice::write() handler
//! \~russian Подключить событие \a PIIODevice::threadedReadEvent() устройства "dev" к обработчику \a received() и событие \a
//! sendRequest() к обработчику \a PIIODevice::write()
void assignDevice(PIIODevice * dev); void assignDevice(PIIODevice * dev);
EVENT1(packetReceiveEvent, PIByteArray &, data); EVENT1(packetReceiveEvent, PIByteArray &, data);

View File

@@ -1,15 +1,25 @@
/*! \file piliterals.h //! \addtogroup Core
* \ingroup Core //! \{}
* \~\brief //! \file piliterals.h
* \~english C++11 literals //! \brief C++11 user-defined literals
* \~russian C++11 суффиксы //! \~english C++11 user-defined literals for PIP library types
* //! \~russian C++11 пользовательские литералы для типов библиотеки PIP
* \~\details //! \details
* \~english //! \~english
* Include all literals_*.h files //! Includes all literals_*.h files providing user-defined literals (UDL) for:
* \~russian //! * PIByteArray (hex, base64)
* Включает все файлы literals_*.h //! * Bytes (KB, MB, GB, TB, PB, KiB, MiB, GiB, TiB, PiB)
*/ //! * PIString (ASCII, UTF-8)
//! * PIRegularExpression (regex, glob)
//! * PISystemTime (d, h, m, s, ms, us, ns, Hz, KHz, MHz, GHz)
//! \~russian
//! Включает все файлы literals_*.h с пользовательскими литералами (UDL) для:
//! * PIByteArray (hex, base64)
//! * Bytes (KB, MB, GB, TB, PB, KiB, MiB, GiB, TiB, PiB)
//! * PIString (ASCII, UTF-8)
//! * PIRegularExpression (regex, glob)
//! * PISystemTime (d, h, m, s, ms, us, ns, Hz, KHz, MHz, GHz)
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
C++11 literals C++11 literals

View File

@@ -1,9 +1,13 @@
/*! \file piluaprogram.h //! \addtogroup Lua
* \ingroup Lua //! \{
* \~\brief //! \file piluaprogram.h
* \~english Lua Program //! \brief
* \~russian Программа Lua //! \~english Lua Program wrapper
*/ //! \~russian Обёртка программы Lua
//! \details
//! \~english Provides interface for loading and executing Lua scripts using LuaBridge
//! \~russian Предоставляет интерфейс для загрузки и выполнения скриптов Lua с использованием LuaBridge
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PILuaProgram PILuaProgram
@@ -29,21 +33,46 @@
#include "pip_lua.h" #include "pip_lua.h"
#include "pip_lua_export.h" #include "pip_lua_export.h"
//! \~english Lua Program class provides interface for loading and executing Lua scripts
//! \~russian Класс PILuaProgram предоставляет интерфейс для загрузки и выполнения скриптов Lua
class PIP_LUA_EXPORT PILuaProgram { class PIP_LUA_EXPORT PILuaProgram {
public: public:
//! Constructs an empty PILuaProgram, initialize Lua context //! \~english Constructs an empty PILuaProgram and initializes Lua context
//! \~russian Создаёт пустой PILuaProgram и инициализирует контекст Lua
PILuaProgram(); PILuaProgram();
//! Load Lua script from PIString //! \~english Loads Lua script from PIString
//! \~russian Загружает скрипт Lua из PIString
//! \param script
//! \~english The Lua script to load
//! \~russian Загружаемый скрипт Lua
//! \return
//! \~english true if script loaded successfully
//! \~russian true, если скрипт успешно загружен
bool load(const PIString & script); bool load(const PIString & script);
//! Execute script //! \~english Prepares the loaded script for execution
//! \~russian Подготавливает загруженный скрипт к выполнению
//! \return
//! \~english true if preparation successful
//! \~russian true, если подготовка успешна
bool prepare(); bool prepare();
//! Get Lua Object or Function //! \~english Gets a global Lua object or function by name
//! \~russian Получает глобальный объект или функцию Lua по имени
//! \param name
//! \~english Name of the global object or function
//! \~russian Имя глобального объекта или функции
//! \return
//! \~english LuaRef to the global object or function
//! \~russian LuaRef на глобальный объект или функцию
luabridge::LuaRef getGlobal(const PIString & name); luabridge::LuaRef getGlobal(const PIString & name);
//! Return Lua global namespace //! \~english Returns the global namespace of the Lua state
//! \~russian Возвращает глобальное пространство имён состояния Lua
//! \return
//! \~english Namespace object representing global scope
//! \~russian Объект Namespace, представляющий глобальную область видимости
luabridge::Namespace getGlobalNamespace(); luabridge::Namespace getGlobalNamespace();
private: private:

View File

@@ -1,10 +1,10 @@
/*! \file picrc.h //! \file picrc.h
* \ingroup Math //! \ingroup Math
* \~\brief //! \~\brief
* \~english CRC checksum calculation //! \~english CRC checksum calculation
* \~russian Вычисление CRC контрольной суммы //! \~russian Вычисление CRC контрольной суммы
*/
/* /*!
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
CRC checksum calculator CRC checksum calculator
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -28,67 +28,113 @@
#include "pistring.h" #include "pistring.h"
//! \addtogroup Math
//! \{
//! \class uint_cl
//! \brief
//! \~english Fixed-size unsigned integer class for CRC calculations
//! \~russian Класс целого числа фиксированного размера для вычисления CRC
//! \details
//! \~english Provides arbitrary length unsigned integer support for CRC computation
//! \~russian Обеспечивает поддержку целых чисел произвольной длины для вычисления CRC
//! \}
template<int L> template<int L>
class PIP_EXPORT uint_cl { class PIP_EXPORT uint_cl {
public: public:
//! \~english Default constructor, initializes to zero
//! \~russian Конструктор по умолчанию, инициализирует нулём
uint_cl() { uint_cl() {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Copy constructor
//! \~russian Конструктор копирования
uint_cl(const uint_cl<L> & v) { uint_cl(const uint_cl<L> & v) {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
data_[i] = v.data_[i]; data_[i] = v.data_[i];
} }
//! \~english Construct from unsigned char
//! \~russian Конструктор из unsigned char
uint_cl(uchar v) { uint_cl(uchar v) {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
data_[i] = (i == 0 ? v : 0); data_[i] = (i == 0 ? v : 0);
} }
//! \~english Construct from char
//! \~russian Конструктор из char
uint_cl(char v) { uint_cl(char v) {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
data_[i] = (i == 0 ? v : 0); data_[i] = (i == 0 ? v : 0);
} }
//! \~english Construct from unsigned short
//! \~russian Конструктор из unsigned short
uint_cl(ushort v) { uint_cl(ushort v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i) for (int i = l; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Construct from short
//! \~russian Конструктор из short
uint_cl(short v) { uint_cl(short v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i) for (int i = l; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Construct from unsigned int
//! \~russian Конструктор из unsigned int
uint_cl(uint v) { uint_cl(uint v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i) for (int i = l; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Construct from int
//! \~russian Конструктор из int
uint_cl(int v) { uint_cl(int v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i) for (int i = l; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Construct from unsigned long
//! \~russian Конструктор из unsigned long
uint_cl(ulong v) { uint_cl(ulong v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i) for (int i = l; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Construct from long
//! \~russian Конструктор из long
uint_cl(long v) { uint_cl(long v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i) for (int i = l; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Construct from unsigned long long
//! \~russian Конструктор из unsigned long long
uint_cl(ullong v) { uint_cl(ullong v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
for (int i = l; i < L / 8; ++i) for (int i = l; i < L / 8; ++i)
data_[i] = 0; data_[i] = 0;
} }
//! \~english Construct from long long
//! \~russian Конструктор из long long
uint_cl(llong v) { uint_cl(llong v) {
int l = piMin<uint>(L / 8, sizeof(v)); int l = piMin<uint>(L / 8, sizeof(v));
memcpy(data_, &v, l); memcpy(data_, &v, l);
@@ -96,55 +142,87 @@ public:
data_[i] = 0; data_[i] = 0;
} }
//! \~english Convert to bool
//! \~russian Преобразование в bool
operator bool() { operator bool() {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
if (data_[i] > 0) return true; if (data_[i] > 0) return true;
return false; return false;
} }
//! \~english Convert to char
//! \~russian Преобразование в char
operator char() { return (char)data_[0]; } operator char() { return (char)data_[0]; }
//! \~english Convert to short
//! \~russian Преобразование в short
operator short() { operator short() {
short t(0); short t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l); memcpy(&t, data_, l);
return t; return t;
} }
//! \~english Convert to int
//! \~russian Преобразование в int
operator int() { operator int() {
int t(0); int t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l); memcpy(&t, data_, l);
return t; return t;
} }
//! \~english Convert to long
//! \~russian Преобразование в long
operator long() { operator long() {
long t(0); long t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l); memcpy(&t, data_, l);
return t; return t;
} }
//! \~english Convert to long long
//! \~russian Преобразование в long long
operator llong() { operator llong() {
llong t(0); llong t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l); memcpy(&t, data_, l);
return t; return t;
} }
//! \~english Convert to unsigned char
//! \~russian Преобразование в unsigned char
operator uchar() { return data_[0]; } operator uchar() { return data_[0]; }
//! \~english Convert to unsigned short
//! \~russian Преобразование в unsigned short
operator ushort() { operator ushort() {
ushort t(0); ushort t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l); memcpy(&t, data_, l);
return t; return t;
} }
//! \~english Convert to unsigned int
//! \~russian Преобразование в unsigned int
operator uint() { operator uint() {
uint t(0); uint t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l); memcpy(&t, data_, l);
return t; return t;
} }
//! \~english Convert to unsigned long
//! \~russian Преобразование в unsigned long
operator ulong() { operator ulong() {
ulong t(0); ulong t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
memcpy(&t, data_, l); memcpy(&t, data_, l);
return t; return t;
} }
//! \~english Convert to unsigned long long
//! \~russian Преобразование в unsigned long long
operator ullong() { operator ullong() {
ullong t(0); ullong t(0);
int l = piMin<uint>(L / 8, sizeof(t)); int l = piMin<uint>(L / 8, sizeof(t));
@@ -152,6 +230,8 @@ public:
return t; return t;
} }
//! \~english Addition operator
//! \~russian Оператор сложения
uint_cl<L> operator+(const uint_cl<L> & v) { uint_cl<L> operator+(const uint_cl<L> & v) {
uint_cl<L> t; uint_cl<L> t;
uint cv; uint cv;
@@ -165,12 +245,15 @@ public:
return t; return t;
} }
//! \~english Bitwise AND operator
//! \~russian Побитовый оператор И
uint_cl<L> operator&(const uint_cl<L> & v) const { uint_cl<L> operator&(const uint_cl<L> & v) const {
uint_cl<L> t; uint_cl<L> t;
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
t.data_[i] = v.data_[i] & data_[i]; t.data_[i] = v.data_[i] & data_[i];
return t; return t;
} }
uint_cl<L> operator&(const uchar & v) const { return *this & uint_cl<L>(v); } uint_cl<L> operator&(const uchar & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const ushort & v) const { return *this & uint_cl<L>(v); } uint_cl<L> operator&(const ushort & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const uint & v) const { return *this & uint_cl<L>(v); } uint_cl<L> operator&(const uint & v) const { return *this & uint_cl<L>(v); }
@@ -182,12 +265,15 @@ public:
uint_cl<L> operator&(const long & v) const { return *this & uint_cl<L>(v); } uint_cl<L> operator&(const long & v) const { return *this & uint_cl<L>(v); }
uint_cl<L> operator&(const llong & v) const { return *this & uint_cl<L>(v); } uint_cl<L> operator&(const llong & v) const { return *this & uint_cl<L>(v); }
//! \~english Bitwise OR operator
//! \~russian Побитовый оператор ИЛИ
uint_cl<L> operator|(const uint_cl<L> & v) const { uint_cl<L> operator|(const uint_cl<L> & v) const {
uint_cl<L> t; uint_cl<L> t;
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
t.data_[i] = v.data_[i] | data_[i]; t.data_[i] = v.data_[i] | data_[i];
return t; return t;
} }
uint_cl<L> operator|(const uchar & v) const { return *this | uint_cl<L>(v); } uint_cl<L> operator|(const uchar & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const ushort & v) const { return *this | uint_cl<L>(v); } uint_cl<L> operator|(const ushort & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const uint & v) const { return *this | uint_cl<L>(v); } uint_cl<L> operator|(const uint & v) const { return *this | uint_cl<L>(v); }
@@ -199,12 +285,15 @@ public:
uint_cl<L> operator|(const long & v) const { return *this | uint_cl<L>(v); } uint_cl<L> operator|(const long & v) const { return *this | uint_cl<L>(v); }
uint_cl<L> operator|(const llong & v) const { return *this | uint_cl<L>(v); } uint_cl<L> operator|(const llong & v) const { return *this | uint_cl<L>(v); }
//! \~english Bitwise XOR operator
//! \~russian Побитовый оператор исключающее ИЛИ
uint_cl<L> operator^(const uint_cl<L> & v) const { uint_cl<L> operator^(const uint_cl<L> & v) const {
uint_cl<L> t; uint_cl<L> t;
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
t.data_[i] = v.data_[i] ^ data_[i]; t.data_[i] = v.data_[i] ^ data_[i];
return t; return t;
} }
uint_cl<L> operator^(const uchar & v) const { return *this ^ uint_cl<L>(v); } uint_cl<L> operator^(const uchar & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const ushort & v) const { return *this ^ uint_cl<L>(v); } uint_cl<L> operator^(const ushort & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const uint & v) const { return *this ^ uint_cl<L>(v); } uint_cl<L> operator^(const uint & v) const { return *this ^ uint_cl<L>(v); }
@@ -216,6 +305,8 @@ public:
uint_cl<L> operator^(const long & v) const { return *this ^ uint_cl<L>(v); } uint_cl<L> operator^(const long & v) const { return *this ^ uint_cl<L>(v); }
uint_cl<L> operator^(const llong & v) const { return *this ^ uint_cl<L>(v); } uint_cl<L> operator^(const llong & v) const { return *this ^ uint_cl<L>(v); }
//! \~english Less than operator
//! \~russian Оператор меньше
bool operator<(const uint_cl<L> & v) const { bool operator<(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) { for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] > data_[i]) return true; if (v.data_[i] > data_[i]) return true;
@@ -223,6 +314,9 @@ public:
} }
return false; return false;
} }
//! \~english Less than or equal operator
//! \~russian Оператор меньше или равно
bool operator<=(const uint_cl<L> & v) const { bool operator<=(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) { for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] > data_[i]) return true; if (v.data_[i] > data_[i]) return true;
@@ -230,6 +324,9 @@ public:
} }
return true; return true;
} }
//! \~english Greater than operator
//! \~russian Оператор больше
bool operator>(const uint_cl<L> & v) const { bool operator>(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) { for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] < data_[i]) return true; if (v.data_[i] < data_[i]) return true;
@@ -237,6 +334,9 @@ public:
} }
return false; return false;
} }
//! \~english Greater than or equal operator
//! \~russian Оператор больше или равно
bool operator>=(const uint_cl<L> & v) const { bool operator>=(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) { for (int i = 0; i < L / 8; ++i) {
if (v.data_[i] < data_[i]) return true; if (v.data_[i] < data_[i]) return true;
@@ -244,18 +344,27 @@ public:
} }
return true; return true;
} }
//! \~english Equality operator
//! \~russian Оператор равенства
bool operator==(const uint_cl<L> & v) const { bool operator==(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
if (v.data_[i] != data_[i]) return false; if (v.data_[i] != data_[i]) return false;
return true; return true;
} }
//! \~english Inequality operator
//! \~russian Оператор неравенства
bool operator!=(const uint_cl<L> & v) const { bool operator!=(const uint_cl<L> & v) const {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
if (v.data_[i] != data_[i]) return true; if (v.data_[i] != data_[i]) return true;
return false; return false;
} }
bool operator<=(const uint_cl<8> & v1) { return (*(uchar *)data()) <= (*(uchar *)v1.data()); } bool operator<=(const uint_cl<8> & v1) { return (*(uchar *)data()) <= (*(uchar *)v1.data()); }
//! \~english Right shift operator
//! \~russian Оператор побитового сдвига вправо
uint_cl<L> operator>>(const int & c) const { uint_cl<L> operator>>(const int & c) const {
uint_cl<L> t; uint_cl<L> t;
int l = L - c; int l = L - c;
@@ -270,7 +379,11 @@ public:
} }
return t; return t;
} }
uint_cl<L> operator>>(const uint & c) const { return (*this << (int)c); } uint_cl<L> operator>>(const uint & c) const { return (*this << (int)c); }
//! \~english Left shift operator
//! \~russian Оператор побитового сдвига влево
uint_cl<L> operator<<(const int & c) const { uint_cl<L> operator<<(const int & c) const {
uint_cl<L> t; uint_cl<L> t;
int l = L - c; int l = L - c;
@@ -285,19 +398,28 @@ public:
} }
return t; return t;
} }
uint_cl<L> operator<<(const uint & c) const { return (*this >> (int)c); } uint_cl<L> operator<<(const uint & c) const { return (*this >> (int)c); }
//! \~english In-place bitwise inversion
//! \~russian Побитовая инверсия на месте
uint_cl<L> & inverse() const { uint_cl<L> & inverse() const {
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
data_[i] = ~data_[i]; data_[i] = ~data_[i];
return *this; return *this;
} }
//! \~english Returns bitwise inverted copy
//! \~russian Возвращает копию с побитовой инверсией
uint_cl<L> inversed() const { uint_cl<L> inversed() const {
uint_cl<L> t(*this); uint_cl<L> t(*this);
for (int i = 0; i < L / 8; ++i) for (int i = 0; i < L / 8; ++i)
t.data_[i] = ~t.data_[i]; t.data_[i] = ~t.data_[i];
return t; return t;
} }
//! \~english Returns bit-reversed copy
//! \~russian Возвращает копию с переставленными битами
uint_cl<L> reversed() const { uint_cl<L> reversed() const {
uint_cl<L> t; uint_cl<L> t;
bool bit; bool bit;
@@ -311,8 +433,16 @@ public:
return t; return t;
} }
//! \~english Get const pointer to data
//! \~russian Получить константный указатель на данные
const uchar * data() const { return data_; } const uchar * data() const { return data_; }
//! \~english Get pointer to data
//! \~russian Получить указатель на данные
uchar * data() { return data_; } uchar * data() { return data_; }
//! \~english Get data length in bytes
//! \~russian Получить длину данных в байтах
uint length() const { return L / 8; } uint length() const { return L / 8; }
private: private:
@@ -320,6 +450,11 @@ private:
}; };
//! \~english Reverse byte order
//! \~russian Реверс порядка байтов
//! \details
//! \~english Reverses the bit order within a byte
//! \~russian Инвертирует порядок битов в байте
inline uchar reverseByte(uchar b) { inline uchar reverseByte(uchar b) {
uchar ret = 0; uchar ret = 0;
bool bit; bool bit;
@@ -330,9 +465,26 @@ inline uchar reverseByte(uchar b) {
return ret; return ret;
} }
//! \addtogroup Math
//! \{
//! \class PICRC
//! \brief
//! \~english CRC calculator class
//! \~russian Класс калькулятора CRC
//! \details
//! \~english Calculates CRC checksum using configurable polynomial and parameters
//! \~russian Вычисляет контрольную сумму CRC с использованием настраиваемого полинома и параметров
//! \sa CRC_32, CRC_16, CRC_8
//! \}
template<uint L, typename N = uint_cl<L>> template<uint L, typename N = uint_cl<L>>
class PIP_EXPORT PICRC { class PIP_EXPORT PICRC {
public: public:
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
//! \note
//! \~english Polynomial value defaults to zero
//! \~russian Значение полинома по умолчанию ноль
PICRC(const N & poly = N()) { PICRC(const N & poly = N()) {
poly_ = poly; poly_ = poly;
reverse_poly = true; reverse_poly = true;
@@ -341,6 +493,13 @@ public:
reverse_before_xor = reverse_data = false; reverse_before_xor = reverse_data = false;
initTable(); initTable();
} }
//! \~english Constructor with full parameters
//! \~russian Конструктор с полными параметрами
//! \param poly polynomial value
//! \param reverse_poly_ whether to reverse polynomial bits
//! \param initial initial CRC value
//! \param out_xor XOR value for output
PICRC(const N & poly, bool reverse_poly_, const N & initial, const N & out_xor) { PICRC(const N & poly, bool reverse_poly_, const N & initial, const N & out_xor) {
poly_ = poly; poly_ = poly;
reverse_poly = reverse_poly_; reverse_poly = reverse_poly_;
@@ -350,18 +509,33 @@ public:
initTable(); initTable();
} }
//! \~english Set initial CRC value
//! \~russian Установить начальное значение CRC
void setInitial(const N & v) { init_ = v; } void setInitial(const N & v) { init_ = v; }
//! \~english Set output XOR value
//! \~russian Установить значение XOR для вывода
void setOutXor(const N & v) { out_ = v; } void setOutXor(const N & v) { out_ = v; }
//! \~english Set polynomial bit reversal
//! \~russian Установить реверс битов полинома
void setReversePolynome(bool yes) { void setReversePolynome(bool yes) {
reverse_poly = yes; reverse_poly = yes;
initTable(); initTable();
} }
//! \~english Set output bit reversal before XOR
//! \~russian Установить реверс битов вывода перед XOR
void setReverseOutBeforeXOR(bool yes) { reverse_before_xor = yes; } void setReverseOutBeforeXOR(bool yes) { reverse_before_xor = yes; }
//! \~english Set data byte reversal
//! \~russian Установить реверс байтов данных
void setReverseDataBytes(bool yes) { reverse_data = yes; } void setReverseDataBytes(bool yes) { reverse_data = yes; }
//! \~english Initialize lookup table
//! \~russian Инициализировать таблицу поиска
void initTable() { void initTable() {
N tmp, pol = reverse_poly ? reversed(poly_) : poly_; N tmp, pol = reverse_poly ? reversed(poly_) : poly_;
// cout << std::hex << "poly " << (uint)N(poly_) << " -> " << (uint)N(pol) << endl;
for (int i = 0; i < 256; ++i) { for (int i = 0; i < 256; ++i) {
tmp = uchar(i); tmp = uchar(i);
for (int j = 0; j < 8; ++j) for (int j = 0; j < 8; ++j)
@@ -370,10 +544,11 @@ public:
} }
} }
//! \~english Calculate CRC from raw data
//! \~russian Вычислить CRC из сырых данных
N calculate(const void * data, int size) { N calculate(const void * data, int size) {
N crc = init_; N crc = init_;
uchar *data_ = (uchar *)data, cb; uchar *data_ = (uchar *)data, cb;
// cout << "process " << size << endl;
uchar nTemp; uchar nTemp;
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
cb = data_[i]; cb = data_[i];
@@ -385,7 +560,13 @@ public:
if (reverse_before_xor) crc = reversed(crc); if (reverse_before_xor) crc = reversed(crc);
return crc ^ out_; return crc ^ out_;
} }
//! \~english Calculate CRC from PIByteArray
//! \~russian Вычислить CRC из PIByteArray
N calculate(const PIByteArray & d) { return calculate(d.data(), d.size()); } N calculate(const PIByteArray & d) { return calculate(d.data(), d.size()); }
//! \~english Calculate CRC from null-terminated string
//! \~russian Вычислить CRC из нуль-терминированной строки
N calculate(const char * str) { N calculate(const char * str) {
PIByteArray s(PIString(str).toByteArray()); PIByteArray s(PIString(str).toByteArray());
return calculate(s.data(), s.size_s()); return calculate(s.data(), s.size_s());
@@ -425,22 +606,46 @@ inline uint PICRC<32, uint>::inversed(const uint & v) {
return ~v; return ~v;
} }
//! \~english Standard CRC-32 (Ethernet, ZIP, etc.)
//! \~russian Стандартный CRC-32 (Ethernet, ZIP и т.д.)
typedef PICRC<32, uint> CRC_32; typedef PICRC<32, uint> CRC_32;
//! \~english Standard CRC-24
//! \~russian Стандартный CRC-24
typedef PICRC<24> CRC_24; typedef PICRC<24> CRC_24;
//! \~english Standard CRC-16
//! \~russian Стандартный CRC-16
typedef PICRC<16, ushort> CRC_16; typedef PICRC<16, ushort> CRC_16;
//! \~english Standard CRC-8
//! \~russian Стандартный CRC-8
typedef PICRC<8, uchar> CRC_8; typedef PICRC<8, uchar> CRC_8;
//! \~english Create standard CRC-32 calculator
//! \~russian Создать стандартный калькулятор CRC-32
inline CRC_32 standardCRC_32() { inline CRC_32 standardCRC_32() {
return CRC_32(0x04C11DB7, true, 0xFFFFFFFF, 0xFFFFFFFF); return CRC_32(0x04C11DB7, true, 0xFFFFFFFF, 0xFFFFFFFF);
} }
//! \~english Create standard CRC-16 calculator
//! \~russian Создать стандартный калькулятор CRC-16
inline CRC_16 standardCRC_16() { inline CRC_16 standardCRC_16() {
return CRC_16(0x8005, true, 0x0, 0x0); return CRC_16(0x8005, true, 0x0, 0x0);
} }
//! \~english Create standard CRC-16 Modbus calculator
//! \~russian Создать стандартный калькулятор CRC-16 Modbus
inline CRC_16 standardCRC_16_Modbus() { inline CRC_16 standardCRC_16_Modbus() {
return CRC_16(0x8005, 0xFFFF, 0xFFFF, false); return CRC_16(0x8005, 0xFFFF, 0xFFFF, false);
} }
//! \~english Create standard CRC-8 calculator
//! \~russian Создать стандартный калькулятор CRC-8
inline CRC_8 standardCRC_8() { inline CRC_8 standardCRC_8() {
return CRC_8(0xD5, true, 0x0, 0x0); return CRC_8(0xD5, true, 0x0, 0x0);
} }
//! \}
#endif // CRC_H #endif // CRC_H

View File

@@ -1,9 +1,15 @@
/*! \file pievaluator.h //! \addtogroup Math
* \ingroup Math //! \{
* \~\brief //! \file pievaluator.h
* \~english Mathematic expressions calculator //! \brief Mathematical expressions evaluator
* \~russian Вычислитель математических выражений //! \~english Mathematical expressions evaluator for parsing and calculating math expressions
*/ //! \~russian Вычислитель математических выражений для разбора и вычисления математических выражений
//! \details
//! \~english PIEvaluator provides functionality to parse and evaluate mathematical expressions. It supports variables, functions (both
//! built-in and custom), and various operators including arithmetic, comparison, and logical operations.
//! \~russian PIEvaluator предоставляет функциональность для разбора и вычисления математических выражений. Поддерживаются переменные,
//! функции (как встроенные, так и пользовательские), а также различные операторы: арифметические, сравнения и логические.
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Evaluator designed for stream calculations Evaluator designed for stream calculations
@@ -32,146 +38,292 @@
namespace PIEvaluatorTypes { namespace PIEvaluatorTypes {
//! \~english Handler function type for custom functions
//! \~russian Тип обработчика для пользовательских функций
typedef std::function<complexd(void *, int, complexd *)> FuncHanlder; typedef std::function<complexd(void *, int, complexd *)> FuncHanlder;
//! \~english Type of evaluator element
//! \~russian Тип элемента вычислителя
enum eType { enum eType {
etNumber, etNumber, //! \~english Number value
etOperator, //! \~russian Числовое значение
etVariable, etOperator, //! \~english Operator symbol
etFunction //! \~russian Символ оператора
}; etVariable, //! \~english Variable reference
enum Operation { //! \~russian Ссылка на переменную
oNone, etFunction //! \~english Function call
oAdd, //! \~russian Вызов функции
oSubtract,
oMultiply,
oDivide,
oResidue,
oPower,
oEqual,
oNotEqual,
oGreater,
oSmaller,
oGreaterEqual,
oSmallerEqual,
oAnd,
oOr,
oFunction
};
enum BaseFunctions {
bfUnknown,
bfSin,
bfCos,
bfTg,
bfCtg,
bfArcsin,
bfArccos,
bfArctg,
bfArcctg,
bfExp,
bfRandom,
bfRandomn,
bfSh,
bfCh,
bfTh,
bfCth,
bfSqrt,
bfSqr,
bfPow,
bfAbs,
bfLn,
bfLg,
bfLog,
bfSign,
bfIm,
bfRe,
bfArg,
bfLen,
bfConj,
bfRad,
bfDeg,
bfJ0,
bfJ1,
bfJN,
bfY0,
bfY1,
bfYN,
bfMin,
bfMax,
bfClamp,
bfStep,
bfMix,
bfDefined,
bfRound,
bfCustom = 0xFFFF
}; };
//! \~english Operation types supported by evaluator
//! \~russian Типы операций, поддерживаемые вычислителем
enum Operation {
oNone, //! \~english No operation
//! \~russian Нет операции
oAdd, //! \~english Addition operator (+)
//! \~russian Оператор сложения (+)
oSubtract, //! \~english Subtraction operator (-)
//! \~russian Оператор вычитания (-)
oMultiply, //! \~english Multiplication operator (*)
//! \~russian Оператор умножения (*)
oDivide, //! \~english Division operator (/)
//! \~russian Оператор деления (/)
oResidue, //! \~english Residue operator
//! \~russian Оператор остатка
oPower, //! \~english Power operator (^)
//! \~russian Оператор возведения в степень (^)
oEqual, //! \~english Equal comparison operator (=)
//! \~russian Оператор равенства (=)
oNotEqual, //! \~english Not equal comparison operator (<>)
//! \~russian Оператор неравенства (<>)
oGreater, //! \~english Greater than comparison operator (>)
//! \~russian Оператор больше (>)
oSmaller, //! \~english Smaller than comparison operator (<)
//! \~russian Оператор меньше (<)
oGreaterEqual, //! \~english Greater or equal comparison operator (>=)
//! \~russian Оператор больше или равно (>=)
oSmallerEqual, //! \~english Smaller or equal comparison operator (<=)
//! \~russian Оператор меньше или равно (<=)
oAnd, //! \~english Logical AND operator
//! \~russian Логический оператор И
oOr, //! \~english Logical OR operator
//! \~russian Логический оператор ИЛИ
oFunction //! \~english Function call
//! \~russian Вызов функции
};
//! \~english Built-in base functions supported by evaluator
//! \~russian Встроенные базовые функции, поддерживаемые вычислителем
enum BaseFunctions {
bfUnknown, //! \~english Unknown function
//! \~russian Неизвестная функция
bfSin, //! \~english Sine function
//! \~russian Синус
bfCos, //! \~english Cosine function
//! \~russian Косинус
bfTg, //! \~english Tangent function
//! \~russian Тангенс
bfCtg, //! \~english Cotangent function
//! \~russian Котангенс
bfArcsin, //! \~english Arcsine function
//! \~russian Арксинус
bfArccos, //! \~english Arccosine function
//! \~russian Арккосинус
bfArctg, //! \~english Arctangent function
//! \~russian Арктангенс
bfArcctg, //! \~english Arccotangent function
//! \~russian Арккотангенс
bfExp, //! \~english Exponential function (e^x)
//! \~russian Экспонента (e^x)
bfRandom, //! \~english Random number generator [0,1]
//! \~russian Генератор случайных чисел [0,1]
bfRandomn, //! \~english Normal distribution random number
//! \~russian Случайное число с нормальным распределением
bfSh, //! \~english Hyperbolic sine
//! \~russian Гиперболический синус
bfCh, //! \~english Hyperbolic cosine
//! \~russian Гиперболический косинус
bfTh, //! \~english Hyperbolic tangent
//! \~russian Гиперболический тангенс
bfCth, //! \~english Hyperbolic cotangent
//! \~russian Гиперболический котангенс
bfSqrt, //! \~english Square root
//! \~russian Квадратный корень
bfSqr, //! \~english Square function (x^2)
//! \~russian Возведение в квадрат (x^2)
bfPow, //! \~english Power function
//! \~russian Возведение в степень
bfAbs, //! \~english Absolute value
//! \~russian Модуль (абсолютное значение)
bfLn, //! \~english Natural logarithm
//! \~russian Натуральный логарифм
bfLg, //! \~english Base-10 logarithm
//! \~russian Десятичный логарифм
bfLog, //! \~english Base-N logarithm
//! \~russian Логарифм по основанию N
bfSign, //! \~english Sign function
//! \~russian Знак числа
bfIm, //! \~english Imaginary part of complex number
//! \~russian Мнимая часть комплексного числа
bfRe, //! \~english Real part of complex number
//! \~russian Действительная часть комплексного числа
bfArg, //! \~english Argument (phase) of complex number
//! \~russian Аргумент (фаза) комплексного числа
bfLen, //! \~english Length (magnitude) of complex number
//! \~russian Модуль (длина) комплексного числа
bfConj, //! \~english Complex conjugate
//! \~russian Комплексно-сопряженное
bfRad, //! \~english Convert degrees to radians
//! \~russian Перевод градусов в радианы
bfDeg, //! \~english Convert radians to degrees
//! \~russian Перевод радианов в градусы
bfJ0, //! \~english Bessel function J0
//! \~russian Функция Бесселя J0
bfJ1, //! \~english Bessel function J1
//! \~russian Функция Бесселя J1
bfJN, //! \~english Bessel function Jn
//! \~russian Функция Бесселя Jn
bfY0, //! \~english Bessel function Y0
//! \~russian Функция Бесселя Y0
bfY1, //! \~english Bessel function Y1
//! \~russian Функция Бесселя Y1
bfYN, //! \~english Bessel function Yn
//! \~russian Функция Бесселя Yn
bfMin, //! \~english Minimum of two values
//! \~russian Минимум из двух значений
bfMax, //! \~english Maximum of two values
//! \~russian Максимум из двух значений
bfClamp, //! \~english Clamp value to range
//! \~russian Ограничение значения диапазоном
bfStep, //! \~english Step function
//! \~russian Ступенчатая функция
bfMix, //! \~english Mix/interpolation function
//! \~russian Смешивание/интерполяция
bfDefined, //! \~english Check if variable is defined
//! \~russian Проверка определена ли переменная
bfRound, //! \~english Round to nearest integer
//! \~russian Округление до ближайшего целого
bfCustom = 0xFFFF //! \~english Custom user-defined function
//! \~russian Пользовательская функция
};
//! \~english Instruction for evaluator - contains operation, output index, function index and operator indices
//! \~russian Инструкция для вычислителя - содержит операцию, индекс вывода, индекс функции и индексы операторов
struct PIP_EXPORT Instruction { struct PIP_EXPORT Instruction {
//! \~english Constructs empty instruction with default values
//! \~russian Создает пустую инструкцию со значениями по умолчанию
Instruction() { Instruction() {
out = -1; out = -1;
function = -1; function = -1;
operation = oNone; operation = oNone;
} }
//! \~english Constructs instruction with operation, operators, output index and optional function index
//! \~russian Создает инструкцию с указанной операцией, операторами, индексом вывода и опционально индексом функции
Instruction(Operation oper, PIVector<short> opers, short out_ind, short func = -1) { Instruction(Operation oper, PIVector<short> opers, short out_ind, short func = -1) {
operation = oper; operation = oper;
operators = opers; operators = opers;
out = out_ind; out = out_ind;
function = func; function = func;
} }
//! \~english Operation to perform
//! \~russian Операция для выполнения
Operation operation; Operation operation;
//! \~english Output variable index
//! \~russian Индекс переменной вывода
short out; short out;
//! \~english Function index (if operation is function call)
//! \~russian Индекс функции (если операция - вызов функции)
short function; short function;
//! \~english Input operator indices
//! \~russian Индексы входных операторов
PIVector<short> operators; PIVector<short> operators;
}; };
//! \~english Evaluator element representing a number, variable, operator or function
//! \~russian Элемент вычислителя, представляющий число, переменную, оператор или функцию
struct PIP_EXPORT Element { struct PIP_EXPORT Element {
//! \~english Constructs empty element (number type with value 0)
//! \~russian Создает пустой элемент (тип число со значением 0)
Element() { Element() {
num = 0; num = 0;
var_num = -1; var_num = -1;
type = etNumber; type = etNumber;
} }
//! \~english Constructs element with specified type and numeric/variable indices
//! \~russian Создает элемент с указанным типом и числовыми/переменными индексами
Element(eType new_type, short new_num, short new_var_num = -1) { set(new_type, new_num, new_var_num); } Element(eType new_type, short new_num, short new_var_num = -1) { set(new_type, new_num, new_var_num); }
//! \~english Sets element type and numeric/variable indices
//! \~russian Устанавливает тип элемента и числовые/переменные индексы
void set(eType new_type, short new_num, short new_var_num = -1) { void set(eType new_type, short new_num, short new_var_num = -1) {
type = new_type; type = new_type;
num = new_num; num = new_num;
var_num = new_var_num; var_num = new_var_num;
} }
//! \~english Element type (number, operator, variable or function)
//! \~russian Тип элемента (число, оператор, переменная или функция)
eType type; eType type;
//! Numeric value or operator index
//! \~english Numeric value or operator index
//! \~russian Числовое значение или индекс оператора
short num; short num;
//! Variable index (for variables)
//! \~english Variable index (for variables)
//! \~russian Индекс переменной (для переменных)
short var_num; short var_num;
}; };
//! \~english Function definition with name, type and handler
//! \~russian Определение функции с именем, типом и обработчиком
struct PIP_EXPORT Function { struct PIP_EXPORT Function {
//! \~english Constructs unknown function with 0 arguments
//! \~russian Создает неизвестную функцию с 0 аргументами
Function() { Function() {
arguments = 0; arguments = 0;
type = bfUnknown; type = bfUnknown;
handler = nullptr; handler = nullptr;
} }
//! \~english Constructs built-in function with name, argument count and base function type
//! \~russian Создает встроенную функцию с именем, количеством аргументов и типом базовой функции
Function(const PIString & name, short args, BaseFunctions ftype) { Function(const PIString & name, short args, BaseFunctions ftype) {
identifier = name; identifier = name;
arguments = args; arguments = args;
type = ftype; type = ftype;
handler = nullptr; handler = nullptr;
} }
//! \~english Constructs custom function with name, argument count and handler function
//! \~russian Создает пользовательскую функцию с именем, количеством аргументов и обработчиком
Function(const PIString & name, short args, FuncHanlder h) { Function(const PIString & name, short args, FuncHanlder h) {
identifier = name; identifier = name;
arguments = args; arguments = args;
type = bfCustom; type = bfCustom;
handler = h; handler = h;
} }
//! \~english Function identifier (name)
//! \~russian Идентификатор функции (имя)
PIString identifier; PIString identifier;
//! \~english Function type (built-in or custom)
//! \~russian Тип функции (встроенная или пользовательская)
BaseFunctions type; BaseFunctions type;
//! \~english Handler function for custom functions
//! \~russian Обработчик для пользовательских функций
FuncHanlder handler; FuncHanlder handler;
//! \~english Number of arguments
//! \~russian Количество аргументов
short arguments; short arguments;
}; };
//! \~english Variable definition with name and value
//! \~russian Определение переменной с именем и значением
struct PIP_EXPORT Variable { struct PIP_EXPORT Variable {
//! \~english Constructs variable with value 0
//! \~russian Создает переменную со значением 0
Variable() { value = 0.; } Variable() { value = 0.; }
//! \~english Constructs variable with name and value
//! \~russian Создает переменную с именем и значением
Variable(const PIString & var_name, complexd val) { Variable(const PIString & var_name, complexd val) {
name = var_name; name = var_name;
value = val; value = val;
} }
//! \~english Variable name
//! \~russian Имя переменной
PIString name; PIString name;
//! \~english Variable value
//! \~russian Значение переменной
complexd value; complexd value;
}; };
} // namespace PIEvaluatorTypes } // namespace PIEvaluatorTypes
//! \~english Evaluator types namespace containing enums, structs and types for PIEvaluator
//! \~russian Пространство имен типов вычислителя, содержащее перечисления, структуры и типы для PIEvaluator
/* /*
≠ : ≠ :
≥ } ≥ }
@@ -180,36 +332,106 @@ struct PIP_EXPORT Variable {
| |
*/ */
//! Content container for variables and functions
//! \~english Container for variables and functions of the evaluator
//! \~russian Контейнер для переменных и функций вычислителя
//! \details
//! \~english PIEvaluatorContent manages variables and functions for the evaluator. It provides methods to add, find,
//! and retrieve functions and variables.
//! \~russian PIEvaluatorContent управляет переменными и функциями вычислителя. Он предоставляет методы для добавления,
//! поиска и получения функций и переменных.
class PIP_EXPORT PIEvaluatorContent { class PIP_EXPORT PIEvaluatorContent {
friend class PIEvaluator; friend class PIEvaluator;
BINARY_STREAM_FRIEND(PIEvaluatorContent); BINARY_STREAM_FRIEND(PIEvaluatorContent);
public: public:
//! \~english Constructs an empty evaluator content
//! \~russian Создает пустой контент вычислителя
PIEvaluatorContent(); PIEvaluatorContent();
~PIEvaluatorContent() { ; } ~PIEvaluatorContent() { ; }
//! \~english Add function with name and default 1 argument
//! \~russian Добавить функцию с указанным именем и количеством аргументов (по умолчанию 1)
void addFunction(const PIString & name, int args = 1); void addFunction(const PIString & name, int args = 1);
//! \~english Add variable with name and optional value, returns variable index
//! \~russian Добавить переменную с указанным именем и значением, возвращает индекс переменной
int addVariable(const PIString & name, const complexd & val = 0.); int addVariable(const PIString & name, const complexd & val = 0.);
//! \~english Add custom function with name, argument count and handler function
//! \~russian Добавить пользовательскую функцию с обработчиком
void addCustomFunction(const PIString & name, int args_count, PIEvaluatorTypes::FuncHanlder func); void addCustomFunction(const PIString & name, int args_count, PIEvaluatorTypes::FuncHanlder func);
//! \~english Returns number of registered functions
//! \~russian Возвращает количество зарегистрированных функций
int functionsCount() const { return functions.size(); } int functionsCount() const { return functions.size(); }
//! \~english Returns number of registered variables
//! \~russian Возвращает количество зарегистрированных переменных
int variablesCount() const { return variables.size(); } int variablesCount() const { return variables.size(); }
//! \~english Returns number of custom variables
//! \~russian Возвращает количество пользовательских переменных
int customVariablesCount() const; int customVariablesCount() const;
//! \~english Finds function index by name, returns -1 if not found
//! \~russian Находит индекс функции по имени, возвращает -1 если не найдена
int findFunction(const PIString & name) const; int findFunction(const PIString & name) const;
//! \~english Finds variable index by name, returns -1 if not found
//! \~russian Находит индекс переменной по имени, возвращает -1 если не найдена
int findVariable(const PIString & var_name) const; int findVariable(const PIString & var_name) const;
//! \~english Returns function by index
//! \~russian Возвращает функцию по индексу
PIEvaluatorTypes::Function function(int index); PIEvaluatorTypes::Function function(int index);
//! \~english Returns variable by index
//! \~russian Возвращает переменную по индексу
PIEvaluatorTypes::Variable variable(int index); PIEvaluatorTypes::Variable variable(int index);
//! \~english Returns function by name, convenience wrapper
//! \~russian Возвращает функцию по имени, удобная обертка
PIEvaluatorTypes::Function function(const PIString & name) { return function(findFunction(name)); } PIEvaluatorTypes::Function function(const PIString & name) { return function(findFunction(name)); }
//! \~english Returns variable by name, convenience wrapper
//! \~russian Возвращает переменную по имени, удобная обертка
PIEvaluatorTypes::Variable variable(const PIString & name) { return variable(findVariable(name)); } PIEvaluatorTypes::Variable variable(const PIString & name) { return variable(findVariable(name)); }
//! \~english Returns custom variable by index
//! \~russian Возвращает пользовательскую переменную по индексу
PIEvaluatorTypes::Variable customVariable(int index); PIEvaluatorTypes::Variable customVariable(int index);
//! \~english Set variable value by index, returns true on success
//! \~russian Установить значение переменной по индексу, возвращает true при успехе
bool setVariableValue(int index, complexd new_value); bool setVariableValue(int index, complexd new_value);
//! \~english Set variable value by name, returns true on success
//! \~russian Установить значение переменной по имени, возвращает true при успехе
bool setVariableValue(const PIString & var_name, const complexd & new_value) { bool setVariableValue(const PIString & var_name, const complexd & new_value) {
return setVariableValue(findVariable(var_name), new_value); return setVariableValue(findVariable(var_name), new_value);
} }
//! \~english Set variable name by index
//! \~russian Установить имя переменной по индексу
bool setVariableName(int index, const PIString & new_name); bool setVariableName(int index, const PIString & new_name);
bool setVariableName(const PIString & var_name, const PIString & new_name) { return setVariableName(findVariable(var_name), new_name); }
//! \~english Set variable name by name, convenience wrapper
//! \~russian Установить имя переменной по имени, удобная обертка
bool setVariableName(const PIString & var_name, const PIString & new_name) {
return setVariableName(findVariable(var_name), new_name);
}
//! \~english Clears all custom variables
//! \~russian Очищает все пользовательские переменные
void clearCustomVariables(); void clearCustomVariables();
//! \~english Returns base function type by name
//! \~russian Возвращает тип базовой функции по имени
PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name); PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name);
//! \~english Print all functions and variables to console
//! \~russian Вывести все функции и переменные в консоль
void dump(); void dump();
private: private:
@@ -219,9 +441,18 @@ private:
}; };
//! Main evaluator class for parsing and calculating mathematical expressions
//! \~english Main class for parsing and evaluating mathematical expressions
//! \~russian Главный класс для разбора и вычисления математических выражений
//! \details
//! \~english PIEvaluator provides functionality to parse and evaluate mathematical expressions. It supports variables, functions (both
//! built-in and custom), and various operators including arithmetic, comparison, and logical operations.
//! \~russian PIEvaluator предоставляет функциональность для разбора и вычисления математических выражений. Поддерживаются переменные,
//! функции (как встроенные, так и пользовательские), а также различные операторы: арифметические, сравнения и логические.
class PIP_EXPORT PIEvaluator { class PIP_EXPORT PIEvaluator {
public: public:
//! Constructs an empty evaluator //! \~english Constructs an empty evaluator
//! \~russian Создает пустой вычислитель
PIEvaluator() { PIEvaluator() {
correct = false; correct = false;
data_ = 0; data_ = 0;
@@ -230,53 +461,68 @@ public:
~PIEvaluator() { ; } ~PIEvaluator() { ; }
//! Returns custom data //! \~english Returns custom data pointer
//! \~russian Возвращает указатель на пользовательские данные
void * data() { return data_; } void * data() { return data_; }
//! Set custom data to "_data" //! \~english Sets custom data pointer to "_data"
//! \~russian Устанавливает указатель на пользовательские данные в "_data"
void setData(void * _data) { data_ = _data; } void setData(void * _data) { data_ = _data; }
//! \~english Checks mathematical expression and parses it to list of instructions
//! Check mathematical expression and parse it to list of instructions //! \~russian Проверяет математическое выражение и разбирает его в список инструкций
bool check(const PIString & string); bool check(const PIString & string);
//! Returns true if expression was checked succesfully //! \~english Returns true if expression was checked successfully
//! \~russian Возвращает true если выражение было успешно проверено
bool isCorrect() const { return correct; } bool isCorrect() const { return correct; }
//! Set variable value with name "name" to value "value". Add variable if it doesn`t exists //! \~english Set variable value by name, adds variable if it does not exist, returns variable index
//! \~russian Устанавливает значение переменной по имени, добавляет переменную если она не существует, возвращает индекс переменной
int setVariable(const PIString & name, complexd value = complexd(0.)); int setVariable(const PIString & name, complexd value = complexd(0.));
//! Set variable value with index "index" to value "value". Don`t add variable if it doesn`t exists //! \~english Set variable value by index, does not add variable if it does not exist
//! \~russian Устанавливает значение переменной по индексу, не добавляет переменную если она не существует
void setVariable(int index, complexd value = 0.); void setVariable(int index, complexd value = 0.);
//! Evaluate last successfully checked with function \a check() expression and returns result //! \~english Evaluates the last successfully checked expression and returns result
//! \~russian Вычисляет последнее успешно проверенное выражение и возвращает результат
complexd evaluate(); complexd evaluate();
//! Remove all manually added variables //! \~english Removes all manually added variables
//! \~russian Удаляет все вручную добавленные переменные
void clearCustomVariables() { content.clearCustomVariables(); } void clearCustomVariables() { content.clearCustomVariables(); }
//! Returns index of variable with name "name" //! \~english Returns index of variable by name
//! \~russian Возвращает индекс переменной по имени
int variableIndex(const PIString & name) const { return content.findVariable(name); } int variableIndex(const PIString & name) const { return content.findVariable(name); }
//! Returns all unknown variables founded in last expression passed to \a check() function //! \~english Returns list of unknown variables found in the last expression passed to check()
//! \~russian Возвращает список неизвестных переменных, найденных в последнем выражении, переданном в check()
const PIStringList & unknownVariables() const { return unknownVars; } const PIStringList & unknownVariables() const { return unknownVars; }
//! Returns all used variables founded in last expression passed to \a check() function //! \~english Returns list of used variables found in the last expression passed to check()
//! \~russian Возвращает список используемых переменных, найденных в последнем выражении, переданном в check()
const PIStringList & usedVariables() const { return usedVars; } const PIStringList & usedVariables() const { return usedVars; }
//! Returns processed last expression passed to \a check() function //! \~english Returns the last expression passed to check()
//! \~russian Возвращает последнее выражение, переданное в check()
const PIString & expression() const { return currentString; } const PIString & expression() const { return currentString; }
//! Returns last error description occured in \a check() function //! \~english Returns last error description from check() function
//! \~russian Возвращает описание последней ошибки из функции check()
const PIString & error() const { return lastError; } const PIString & error() const { return lastError; }
//! Returns last result of \a evaluate() //! \~english Returns last result of evaluate()
//! \~russian Возвращает последний результат evaluate()
const complexd & lastResult() const { return out; } const complexd & lastResult() const { return out; }
//! Save to %PIByteArray evaluator state (expression, variables, errors, compiled instructions) //! \~english Saves evaluator state to PIByteArray (expression, variables, errors, compiled instructions)
//! \~russian Сохраняет состояние вычислителя в PIByteArray (выражение, переменные, ошибки, скомпилированные инструкции)
PIByteArray save() const; PIByteArray save() const;
//! Restore from %PIByteArray evaluator state (expression, variables, errors, compiled instructions) //! \~english Restores evaluator state from PIByteArray (expression, variables, errors, compiled instructions)
//! \~russian Восстанавливает состояние вычислителя из PIByteArray (выражение, переменные, ошибки, скомпилированные инструкции)
void load(PIByteArray ba); void load(PIByteArray ba);
private: private:

View File

@@ -1,10 +1,13 @@
/*! \file pifft.h //! \addtogroup Math
* \ingroup Math //! \{
* \ingroup FFTW //! \file pifft.h
* \~\brief //! \brief
* \~english FFT, IFFT and Hilbert transformations //! \~english Declares \a PIFFT classes
* \~russian БПФ, ОБПФ и преобразования Гильберта //! \~russian Объявление классов \a PIFFT
*/ //! \~\authors
//! \~english Ivan Pelipenko peri4ko@yandex.ru; Andrey Bychkov work.a.b@yandex.ru
//! \~russian Иван Пелипенко peri4ko@yandex.ru; Андрей Бычков work.a.b@yandex.ru
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for FFT, IFFT and Hilbert transformations Class for FFT, IFFT and Hilbert transformations
@@ -64,16 +67,40 @@
# include "pip_fftw_export.h" # include "pip_fftw_export.h"
//! \addtogroup Math
//! \{
//! \class PIFFT_double
//! \brief
//! \~english Fast Fourier Transform implementation for double precision.
//! \~russian Реализация быстрого преобразования Фурье для двойной точности.
//! \~\}
//! \sa \a PIFFT_float, \a PIFFTW
class PIP_EXPORT PIFFT_double { class PIP_EXPORT PIFFT_double {
public: public:
//! \~english Default constructor.
//! \~russian Конструктор по умолчанию.
PIFFT_double(); PIFFT_double();
//! \~english Calculate FFT from complex vector.
//! \~russian Вычисление БПФ из комплексного вектора.
PIVector<complexd> * calcFFT(const PIVector<complexd> & val); PIVector<complexd> * calcFFT(const PIVector<complexd> & val);
//! \~english Calculate FFT from real vector.
//! \~russian Вычисление БПФ из вещественного вектора.
PIVector<complexd> * calcFFT(const PIVector<double> & val); PIVector<complexd> * calcFFT(const PIVector<double> & val);
//! \~english Calculate inverse FFT.
//! \~russian Вычисление обратного БПФ.
PIVector<complexd> * calcFFTinverse(const PIVector<complexd> & val); PIVector<complexd> * calcFFTinverse(const PIVector<complexd> & val);
//! \~english Calculate Hilbert transform.
//! \~russian Вычисление преобразования Гильберта.
PIVector<complexd> * calcHilbert(const PIVector<double> & val); PIVector<complexd> * calcHilbert(const PIVector<double> & val);
//! \~english Get amplitude spectrum.
//! \~russian Получить амплитудный спектр.
PIVector<double> getAmplitude() const; PIVector<double> getAmplitude() const;
//! \~english Get real part.
//! \~russian Получить действительную часть.
PIVector<double> getReal() const; PIVector<double> getReal() const;
//! \~english Get imaginary part.
//! \~russian Получить мнимую часть.
PIVector<double> getImag() const; PIVector<double> getImag() const;
private: private:
@@ -118,16 +145,40 @@ private:
void ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2); void ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2);
}; };
//! \addtogroup Math
//! \{
//! \class PIFFT_float
//! \brief
//! \~english Fast Fourier Transform implementation for single precision.
//! \~russian Реализация быстрого преобразования Фурье для одинарной точности.
//! \~\}
//! \sa \a PIFFT_double, \a PIFFTW
class PIP_EXPORT PIFFT_float { class PIP_EXPORT PIFFT_float {
public: public:
//! \~english Default constructor.
//! \~russian Конструктор по умолчанию.
PIFFT_float(); PIFFT_float();
//! \~english Calculate FFT from complex vector.
//! \~russian Вычисление БПФ из комплексного вектора.
PIVector<complexf> * calcFFT(const PIVector<complexf> & val); PIVector<complexf> * calcFFT(const PIVector<complexf> & val);
//! \~english Calculate FFT from real vector.
//! \~russian Вычисление БПФ из вещественного вектора.
PIVector<complexf> * calcFFT(const PIVector<float> & val); PIVector<complexf> * calcFFT(const PIVector<float> & val);
//! \~english Calculate inverse FFT.
//! \~russian Вычисление обратного БПФ.
PIVector<complexf> * calcFFTinverse(const PIVector<complexf> & val); PIVector<complexf> * calcFFTinverse(const PIVector<complexf> & val);
//! \~english Calculate Hilbert transform.
//! \~russian Вычисление преобразования Гильберта.
PIVector<complexf> * calcHilbert(const PIVector<float> & val); PIVector<complexf> * calcHilbert(const PIVector<float> & val);
//! \~english Get amplitude spectrum.
//! \~russian Получить амплитудный спектр.
PIVector<float> getAmplitude() const; PIVector<float> getAmplitude() const;
//! \~english Get real part.
//! \~russian Получить действительную часть.
PIVector<float> getReal() const; PIVector<float> getReal() const;
//! \~english Get imaginary part.
//! \~russian Получить мнимую часть.
PIVector<float> getImag() const; PIVector<float> getImag() const;
private: private:
@@ -171,6 +222,7 @@ private:
void ftbase_fftirltrec(PIVector<float> * a, int astart, int astride, PIVector<float> * b, int bstart, int bstride, int m, int n); void ftbase_fftirltrec(PIVector<float> * a, int astart, int astride, PIVector<float> * b, int bstart, int bstride, int m, int n);
void ftbase_ffttwcalc(PIVector<float> * a, int aoffset, int n1, int n2); void ftbase_ffttwcalc(PIVector<float> * a, int aoffset, int n1, int n2);
}; };
//! \~\}
typedef PIFFT_double PIFFT; typedef PIFFT_double PIFFT;
typedef PIFFT_double PIFFTd; typedef PIFFT_double PIFFTd;
@@ -178,40 +230,63 @@ typedef PIFFT_float PIFFTf;
# ifndef CC_VC # ifndef CC_VC
# define _PIFFTW_H(type) \ # define _PIFFTW_H(type) \
class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \ class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \
public: \ public: \
_PIFFTW_P_##type##_(); \ _PIFFTW_P_##type##_(); \
~_PIFFTW_P_##type##_(); \ ~_PIFFTW_P_##type##_(); \
const PIVector<complex<type>> & calcFFT(const PIVector<complex<type>> & in); \ const PIVector<complex<type>> & calcFFT(const PIVector<complex<type>> & in); \
const PIVector<complex<type>> & calcFFTR(const PIVector<type> & in); \ const PIVector<complex<type>> & calcFFTR(const PIVector<type> & in); \
const PIVector<complex<type>> & calcFFTI(const PIVector<complex<type>> & in); \ const PIVector<complex<type>> & calcFFTI(const PIVector<complex<type>> & in); \
void preparePlan(int size, int op); \ void preparePlan(int size, int op); \
void * impl; \ void * impl; \
}; };
_PIFFTW_H(float) _PIFFTW_H(float)
_PIFFTW_H(double) _PIFFTW_H(double)
_PIFFTW_H(ldouble) _PIFFTW_H(ldouble)
//! \addtogroup FFTW
//! \{
//! \class PIFFTW
//! \brief
//! \~english FFTW wrapper for arbitrary precision types.
//! \~russian Обёртка FFTW для типов произвольной точности.
//! \~\}
//! \note Requires linking against libfftw3
//! \sa \a PIFFT_double, \a PIFFT_float
template<typename T> template<typename T>
class PIFFTW { class PIFFTW {
public: public:
//! \~english Default constructor.
//! \~russian Конструктор по умолчанию.
explicit PIFFTW() { explicit PIFFTW() {
p = 0; p = 0;
newP(p); newP(p);
} }
//! \~english Destructor.
//! \~russian Деструктор.
~PIFFTW() { deleteP(p); } ~PIFFTW() { deleteP(p); }
//! \~english Calculate FFT from complex vector.
//! \~russian Вычисление БПФ из комплексного вектора.
inline const PIVector<complex<T>> & calcFFT(const PIVector<complex<T>> & in) { return PIVector<complex<T>>().resize(in.size()); } inline const PIVector<complex<T>> & calcFFT(const PIVector<complex<T>> & in) { return PIVector<complex<T>>().resize(in.size()); }
//! \~english Calculate FFT from real vector.
//! \~russian Вычисление БПФ из вещественного вектора.
inline const PIVector<complex<T>> & calcFFT(const PIVector<T> & in) { return PIVector<complex<T>>().resize(in.size()); } inline const PIVector<complex<T>> & calcFFT(const PIVector<T> & in) { return PIVector<complex<T>>().resize(in.size()); }
//! \~english Calculate inverse FFT.
//! \~russian Вычисление обратного БПФ.
inline const PIVector<complex<T>> & calcFFTinverse(const PIVector<complex<T>> & in) { return PIVector<complex<T>>().resize(in.size()); } inline const PIVector<complex<T>> & calcFFTinverse(const PIVector<complex<T>> & in) { return PIVector<complex<T>>().resize(in.size()); }
//! \~english FFT operation type.
//! \~russian Тип операции БПФ.
enum FFT_Operation { enum FFT_Operation {
foReal, foReal,
foComplex, foComplex,
foInverse foInverse
}; };
//! \~english Prepare computation plan.
//! \~russian Подготовить план вычислений.
inline void preparePlan(int size, FFT_Operation op) {} inline void preparePlan(int size, FFT_Operation op) {}
private: private:
@@ -222,6 +297,7 @@ private:
void * p; void * p;
}; };
//! \~\}
template<> template<>

View File

@@ -1,21 +1,13 @@
/*! \file pigeometry.h //! \addtogroup Math
* \ingroup Math //! \{
* \brief //! \file pigeometry.h
* \~english Geometry base classes //! \brief
* \~russian Базовые геометрические классы //! \~english Geometry utilities
* \~\details //! \~russian Геометрические утилиты
* \~english //! \~\authors
* Add \a PIPoint, \a PILine and \a PIRect classes. //! \~english Ivan Pelipenko peri4ko@yandex.ru; Andrey Bychkov work.a.b@yandex.ru
* \~russian //! \~russian Иван Пелипенко peri4ko@yandex.ru; Андрей Бычков work.a.b@yandex.ru
* Содержит классы: \a PIPoint, \a PILine и \a PIRect. //! \~\}
* * \~\authors
* \~english
* Ivan Pelipenko peri4ko@yandex.ru;
* Andrey Bychkov work.a.b@yandex.ru;
* \~russian
* Иван Пелипенко peri4ko@yandex.ru;
* Андрей Бычков work.a.b@yandex.ru;
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Geometry base classes Geometry base classes

View File

@@ -43,98 +43,99 @@ public:
PIPoint<Type> p0; PIPoint<Type> p0;
PIPoint<Type> p1; PIPoint<Type> p1;
//! \~russian //! \~english Default constructor.
//! Пустой конструктор. //! \~russian Пустой конструктор.
//! \details //! \details
//! При выполнении пустого конструктора координаты не изменяются. //! \~english Creates an empty line where start and end points coincide.
//! Начало и конец совпадают. //! \~russian При выполнении пустого конструктора координаты не изменяются. Начало и конец совпадают.
PILine() {} PILine() {}
//! \~russian //! \~english Creates a line from two points.
//! Создает линию по двум принятым точкам \a PIPoint начала и конца. //! \~russian Создает линию по двум принятым точкам \a PIPoint начала и конца.
PILine(const PIPoint<Type> & p0_, const PIPoint<Type> & p1_) { PILine(const PIPoint<Type> & p0_, const PIPoint<Type> & p1_) {
p0 = p0_; p0 = p0_;
p1 = p1_; p1 = p1_;
} }
//! \~russian //! \~english Creates a line from coordinates.
//! Создает линию по принятым координатам начала и конца. //! \~russian Создает линию по принятым координатам начала и конца.
PILine(Type x0, Type y0, Type x1, Type y1) { PILine(Type x0, Type y0, Type x1, Type y1) {
p0.set(x0, y0); p0.set(x0, y0);
p1.set(x1, y1); p1.set(x1, y1);
} }
//! \~russian //! \~english Set new coordinates from two points.
//! Задать новые координаты начала и конца по двум принятым точкам \a PIPoint. //! \~russian Задать новые координаты начала и конца по двум принятым точкам \a PIPoint.
PILine<Type> & set(const PIPoint<Type> & p0_, const PIPoint<Type> & p1_) { PILine<Type> & set(const PIPoint<Type> & p0_, const PIPoint<Type> & p1_) {
p0 = p0_; p0 = p0_;
p1 = p1_; p1 = p1_;
return *this; return *this;
} }
//! \~russian //! \~english Set new coordinates.
//! Задать новые координаты начала и конца. //! \~russian Задать новые координаты начала и конца.
PILine<Type> & set(Type x0, Type y0, Type x1, Type y1) { PILine<Type> & set(Type x0, Type y0, Type x1, Type y1) {
p0.set(x0, y0); p0.set(x0, y0);
p1.set(x1, y1); p1.set(x1, y1);
return *this; return *this;
} }
//! \~russian //! \~english Check if start and end points coincide.
//! Проверить на совпадение координат начала и конца. //! \~russian Проверить на совпадение координат начала и конца.
bool isEmpty() const { return (p0 == p1); } bool isEmpty() const { return (p0 == p1); }
//! \~russian //! \~english Calculate width of the rectangle whose diagonal is this line.
//! Вычислить ширину прямоугольника, диагональю которого является данный отрезок. //! \~russian Вычислить ширину прямоугольника, диагональю которого является данный отрезок.
Type width() const { return piAbs<Type>(p1.x - p0.x); } Type width() const { return piAbs<Type>(p1.x - p0.x); }
//! \~russian //! \~english Calculate height of the rectangle whose diagonal is this line.
//! Вычислить высоту прямоугольника, диагональю которого является данный отрезок. //! \~russian Вычислить высоту прямоугольника, диагональю которого является данный отрезок.
Type height() const { return piAbs<Type>(p1.y - p0.y); } Type height() const { return piAbs<Type>(p1.y - p0.y); }
//! \~russian //! \~english Translate line by x and y.
//! Сдвинуть линию на \a x, \a y. //! \~russian Сдвинуть линию на \a x, \a y.
PILine<Type> & translate(Type x, Type y) { PILine<Type> & translate(Type x, Type y) {
p0.translate(x, y); p0.translate(x, y);
p1.translate(x, y); p1.translate(x, y);
return *this; return *this;
} }
//! \~russian //! \~english Translate line by point coordinates.
//! Сдвинуть линию на значение координат точки \a PIPoint. //! \~russian Сдвинуть линию на значение координат точки \a PIPoint.
PILine<Type> & translate(const PIPoint<Type> & p) { PILine<Type> & translate(const PIPoint<Type> & p) {
p0.translate(p); p0.translate(p);
p1.translate(p); p1.translate(p);
return *this; return *this;
} }
//! Создать копию отрезка и сдвинуть её на `x` и `y`. //! \~english Create a copy of the line and translate it by x and y.
//! \~russian Создать копию отрезка и сдвинуть её на `x` и `y`.
PILine<Type> translated(Type x, Type y) const { PILine<Type> translated(Type x, Type y) const {
PILine<Type> l(*this); PILine<Type> l(*this);
l.translate(x, y); l.translate(x, y);
return l; return l;
} }
//! \~russian //! \~english Create a copy of the line and translate it by point coordinates.
//! Создать копию отрезка и сдвинуть её на значение координат точки \a PIPoint. //! \~russian Создать копию отрезка и сдвинуть её на значение координат точки \a PIPoint.
PILine<Type> translated(const PIPoint<Type> & p) const { PILine<Type> translated(const PIPoint<Type> & p) const {
PILine<Type> l(*this); PILine<Type> l(*this);
l.translate(p); l.translate(p);
return l; return l;
} }
//! \~russian //! \~english Translate line by x and y. Alias for \a translate().
//! Сдвинуть линию на \a x, \a y. //! \~russian Сдвинуть линию на \a x, \a y.
//! \details Является копией метода \a translate(). //! \details Является копией метода \a translate().
PILine<Type> & move(Type x, Type y) { return translate(x, y); } PILine<Type> & move(Type x, Type y) { return translate(x, y); }
//! \~russian //! \~english Translate line by point coordinates. Alias for \a translate().
//! Сдвинуть линию на значение координат точки \a PIPoint. //! \~russian Сдвинуть линию на значение координат точки \a PIPoint.
//! \details Является копией метода \a translate(). //! \details Является копией метода \a translate().
PILine<Type> & move(const PIPoint<Type> & p) { return translate(p); } PILine<Type> & move(const PIPoint<Type> & p) { return translate(p); }
//! \~russian //! \~english Create a copy of the line and translate it by x and y. Alias for \a translated().
//! Создать копию отрезка и сдвинуть её на \a x, \a y. //! \~russian Создать копию отрезка и сдвинуть её на \a x, \a y.
//! \details Является копией метода \a translated(). //! \details Является копией метода \a translated().
PILine<Type> moved(Type x, Type y) const { PILine<Type> moved(Type x, Type y) const {
PILine<Type> l(*this); PILine<Type> l(*this);
@@ -142,8 +143,8 @@ public:
return l; return l;
} }
//! \~russian //! \~english Create a copy of the line and translate it by point coordinates. Alias for \a translated().
//! Создать копию отрезка и сдвинуть её на значение координат точки \a PIPoint. //! \~russian Создать копию отрезка и сдвинуть её на значение координат точки \a PIPoint.
//! \details Является копией метода \a translated(). //! \details Является копией метода \a translated().
PILine<Type> moved(const PIPoint<Type> & p) const { PILine<Type> moved(const PIPoint<Type> & p) const {
PILine<Type> l(*this); PILine<Type> l(*this);
@@ -151,31 +152,40 @@ public:
return l; return l;
} }
//! \~english Translate line by x value on both coordinates.
//! \~russian Сдвинуть линию по двум координатам на значение \a x. //! \~russian Сдвинуть линию по двум координатам на значение \a x.
void operator+=(Type x) { translate(x, x); } void operator+=(Type x) { translate(x, x); }
//! \~english Translate line by point coordinates.
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint. //! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
void operator+=(const PIPoint<Type> & p) { translate(p); } void operator+=(const PIPoint<Type> & p) { translate(p); }
//! \~english Translate line by negative x value on both coordinates.
//! \~russian Сдвинуть линию по двум координатам на значение \a x. //! \~russian Сдвинуть линию по двум координатам на значение \a x.
void operator-=(Type x) { translate(-x, -x); } void operator-=(Type x) { translate(-x, -x); }
//! \~english Translate line by negative point coordinates.
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint. //! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
void operator-=(const PIPoint<Type> & p) { translate(-p); } void operator-=(const PIPoint<Type> & p) { translate(-p); }
//! \~english Translate line by point coordinates.
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint. //! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
PILine<Type> operator+(const PIPoint<Type> & p) { return translated(p); } PILine<Type> operator+(const PIPoint<Type> & p) { return translated(p); }
//! \~english Translate line by negative point coordinates.
//! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint. //! \~russian Сдвинуть линию по двум координатам на величину координат точки \a PIPoint.
PILine<Type> operator-(const PIPoint<Type> & p) { return translated(-p); } PILine<Type> operator-(const PIPoint<Type> & p) { return translated(-p); }
//! \~english Check equality of two lines.
//! \~russian Проверить равенство координат двух отрезков. //! \~russian Проверить равенство координат двух отрезков.
bool operator==(const PILine<Type> & r) const { return (p0 == r.p0 && p1 == r.p1); } bool operator==(const PILine<Type> & r) const { return (p0 == r.p0 && p1 == r.p1); }
//! \~english Check inequality of two lines.
//! \~russian Проверить неравенство координат двух отрезков. //! \~russian Проверить неравенство координат двух отрезков.
bool operator!=(const PILine<Type> & r) const { return (p1 != r.p1 || p1 != r.p1); } bool operator!=(const PILine<Type> & r) const { return (p1 != r.p1 || p1 != r.p1); }
}; };
//! \~english Stream output operator for PILine.
//! \~russian Перегруженный оператор для вывода координат в \a PICout. //! \~russian Перегруженный оператор для вывода координат в \a PICout.
template<typename Type> template<typename Type>
PICout operator<<(PICout & s, const PILine<Type> & v) { PICout operator<<(PICout & s, const PILine<Type> & v) {

View File

@@ -1,9 +1,13 @@
/*! \file pimathbase.h //! \addtogroup Math
* \ingroup Math //! \{
* \~\brief //! \file pimathbase.h
* \~english Basic mathematical functions and defines //! \brief
* \~russian Базовые математические функции и дефайны //! \~english Basic mathematical functions and defines
*/ //! \~russian Базовые математические функции и дефайны
//! \details
//! \~english Common mathematical constants, conversion functions and utility functions
//! \~russian Общие математические константы, функции преобразования и утилиты
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic mathematical functions and defines Basic mathematical functions and defines
@@ -114,11 +118,29 @@ inline double sinc(const double & v) {
return sin(t) / t; return sin(t) / t;
} }
//! Bessel function of the first kind of order 0
//! \~english Bessel function J0(x)
//! \~russian Функция Бесселя первого рода порядка 0
PIP_EXPORT double piJ0(const double & v); PIP_EXPORT double piJ0(const double & v);
//! Bessel function of the first kind of order 1
//! \~english Bessel function J1(x)
//! \~russian Функция Бесселя первого рода порядка 1
PIP_EXPORT double piJ1(const double & v); PIP_EXPORT double piJ1(const double & v);
//! Bessel function of the first kind of order n
//! \~english Bessel function Jn(n, x)
//! \~russian Функция Бесселя первого рода порядка n
PIP_EXPORT double piJn(int n, const double & v); PIP_EXPORT double piJn(int n, const double & v);
//! Bessel function of the second kind of order 0
//! \~english Bessel function Y0(x)
//! \~russian Функция Бесселя второго рода порядка 0
PIP_EXPORT double piY0(const double & v); PIP_EXPORT double piY0(const double & v);
//! Bessel function of the second kind of order 1
//! \~english Bessel function Y1(x)
//! \~russian Функция Бесселя второго рода порядка 1
PIP_EXPORT double piY1(const double & v); PIP_EXPORT double piY1(const double & v);
//! Bessel function of the second kind of order n
//! \~english Bessel function Yn(n, x)
//! \~russian Функция Бесселя второго рода порядка n
PIP_EXPORT double piYn(int n, const double & v); PIP_EXPORT double piYn(int n, const double & v);
// clang-format off // clang-format off
@@ -129,24 +151,45 @@ inline constexpr float toDeg(float rad) {return rad * M_180_PI;}
inline constexpr double toDeg(double rad) {return rad * M_180_PI;} inline constexpr double toDeg(double rad) {return rad * M_180_PI;}
inline constexpr ldouble toDeg(ldouble rad) {return rad * M_180_PI;} inline constexpr ldouble toDeg(ldouble rad) {return rad * M_180_PI;}
// clang-format on // clang-format on
//! Square of a value
//! \~english Returns the square of value v (v * v)
//! \~russian Возвращает квадрат значения v (v * v)
template<typename T> template<typename T>
inline constexpr T sqr(const T & v) { inline constexpr T sqr(const T & v) {
return v * v; return v * v;
} }
//! Convert linear value to decibels
//! \~english Convert linear value to decibels: 10 * log10(val)
//! \~russian Преобразовать линейное значение в децибелы: 10 * log10(val)
template<typename T> template<typename T>
inline constexpr T toDb(T val) { inline constexpr T toDb(T val) {
return T(10.) * std::log10(val); return T(10.) * std::log10(val);
} }
//! Convert decibels to linear value
//! \~english Convert decibels to linear value: 10^(val/10)
//! \~russian Преобразовать децибелы в линейное значение: 10^(val/10)
template<typename T> template<typename T>
inline constexpr T fromDb(T val) { inline constexpr T fromDb(T val) {
return std::pow(T(10.), val / T(10.)); return std::pow(T(10.), val / T(10.));
} }
// [-1 ; 1] // [-1 ; 1]
//! Generate random double in range [-1, 1]
//! \~english Returns random double in range [-1, 1]
//! \~russian Генерирует случайное число double в диапазоне [-1, 1]
PIP_EXPORT double randomd(); PIP_EXPORT double randomd();
// [-1 ; 1] normal // [-1 ; 1] normal
//! Generate random double with normal (Gaussian) distribution
//! \~english Returns random double with normal distribution, mean=dv, stddev=sv
//! \~russian Генерирует случайное число double с нормальным распределением, среднее=dv, стандартное отклонение=sv
PIP_EXPORT double randomn(double dv = 0., double sv = 1.); PIP_EXPORT double randomn(double dv = 0., double sv = 1.);
//! Absolute value of vector elements
//! \~english Returns vector with absolute values of each element
//! \~russian Возвращает вектор с абсолютными значениями каждого элемента
template<typename T> template<typename T>
inline PIVector<T> piAbs(const PIVector<T> & v) { inline PIVector<T> piAbs(const PIVector<T> & v) {
PIVector<T> result; PIVector<T> result;
@@ -157,6 +200,9 @@ inline PIVector<T> piAbs(const PIVector<T> & v) {
} }
//! Normalize angle to [0, 360) range (in-place)
//! \~english Normalizes angle to range [0, 360) degrees
//! \~russian Нормализует угол в диапазон [0, 360) градусов (на месте)
template<typename T> template<typename T>
void normalizeAngleDeg360(T & a) { void normalizeAngleDeg360(T & a) {
while (a < 0.) while (a < 0.)
@@ -164,6 +210,9 @@ void normalizeAngleDeg360(T & a) {
while (a > 360.) while (a > 360.)
a -= 360.; a -= 360.;
} }
//! Normalize angle to [0, 360) range
//! \~english Returns angle normalized to range [0, 360) degrees
//! \~russian Возвращает угол нормализованный в диапазон [0, 360) градусов
template<typename T> template<typename T>
double normalizedAngleDeg360(T a) { double normalizedAngleDeg360(T a) {
normalizeAngleDeg360(a); normalizeAngleDeg360(a);
@@ -171,6 +220,9 @@ double normalizedAngleDeg360(T a) {
} }
//! Normalize angle to (-180, 180] range (in-place)
//! \~english Normalizes angle to range (-180, 180] degrees
//! \~russian Нормализует угол в диапазон (-180, 180] градусов (на месте)
template<typename T> template<typename T>
void normalizeAngleDeg180(T & a) { void normalizeAngleDeg180(T & a) {
while (a < -180.) while (a < -180.)
@@ -178,6 +230,9 @@ void normalizeAngleDeg180(T & a) {
while (a > 180.) while (a > 180.)
a -= 360.; a -= 360.;
} }
//! Normalize angle to (-180, 180] range
//! \~english Returns angle normalized to range (-180, 180] degrees
//! \~russian Возвращает угол нормализованный в диапазон (-180, 180] градусов
template<typename T> template<typename T>
double normalizedAngleDeg180(T a) { double normalizedAngleDeg180(T a) {
normalizeAngleDeg180(a); normalizeAngleDeg180(a);
@@ -185,6 +240,13 @@ double normalizedAngleDeg180(T a) {
} }
//! Ordinary Least Squares linear regression
//! \~english Calculates linear regression coefficients using OLS method
//! \~russian Вычисляет коэффициенты линейной регрессии методом наименьших квадратов
//! \param input Vector of (x, y) pairs
//! \param out_a Output pointer for slope coefficient (a), can be nullptr
//! \param out_b Output pointer for intercept coefficient (b), can be nullptr
//! \return true on success
template<typename T> template<typename T>
bool OLS_Linear(const PIVector<PIPair<T, T>> & input, T * out_a, T * out_b) { bool OLS_Linear(const PIVector<PIPair<T, T>> & input, T * out_a, T * out_b) {
static_assert(std::is_arithmetic<T>::value, "Type must be arithmetic"); static_assert(std::is_arithmetic<T>::value, "Type must be arithmetic");
@@ -207,6 +269,14 @@ bool OLS_Linear(const PIVector<PIPair<T, T>> & input, T * out_a, T * out_b) {
} }
//! Weighted Least Squares linear regression
//! \~english Calculates linear regression coefficients using WLS method
//! \~russian Вычисляет коэффициенты линейной регрессии методом взвешенных наименьших квадратов
//! \param input Vector of (x, y) pairs
//! \param weights Vector of weights for each point
//! \param out_a Output pointer for slope coefficient (a), can be nullptr
//! \param out_b Output pointer for intercept coefficient (b), can be nullptr
//! \return true on success
template<typename T> template<typename T>
bool WLS_Linear(const PIVector<PIPair<T, T>> & input, const PIVector<T> & weights, T * out_a, T * out_b) { bool WLS_Linear(const PIVector<PIPair<T, T>> & input, const PIVector<T> & weights, T * out_a, T * out_b) {
static_assert(std::is_arithmetic<T>::value, "Type must be arithmetic"); static_assert(std::is_arithmetic<T>::value, "Type must be arithmetic");

View File

@@ -32,9 +32,9 @@
/// Matrix templated /// Matrix templated
#define PIMM_FOR \ #define PIMM_FOR \
for (uint r = 0; r < Rows; ++r) \ for (uint r = 0; r < Rows; ++r) \
for (uint c = 0; c < Cols; ++c) for (uint c = 0; c < Cols; ++c)
#define PIMM_FOR_C for (uint i = 0; i < Cols; ++i) #define PIMM_FOR_C for (uint i = 0; i < Cols; ++i)
#define PIMM_FOR_R for (uint i = 0; i < Rows; ++i) #define PIMM_FOR_R for (uint i = 0; i < Rows; ++i)
@@ -891,9 +891,9 @@ class PIMathMatrix;
/// Matrix /// Matrix
#define PIMM_FOR \ #define PIMM_FOR \
for (uint r = 0; r < _V2D::rows_; ++r) \ for (uint r = 0; r < _V2D::rows_; ++r) \
for (uint c = 0; c < _V2D::cols_; ++c) for (uint c = 0; c < _V2D::cols_; ++c)
#define PIMM_FOR_A for (uint i = 0; i < _V2D::mat.size(); ++i) #define PIMM_FOR_A for (uint i = 0; i < _V2D::mat.size(); ++i)
#define PIMM_FOR_C for (uint i = 0; i < _V2D::cols_; ++i) #define PIMM_FOR_C for (uint i = 0; i < _V2D::cols_; ++i)
#define PIMM_FOR_R for (uint i = 0; i < _V2D::rows_; ++i) #define PIMM_FOR_R for (uint i = 0; i < _V2D::rows_; ++i)

View File

@@ -1,6 +1,13 @@
/*! \file pimathsolver.h //! \addtogroup Math
* \brief PIMathSolver //! \{
*/ //! \file pimathsolver.h
//! \brief
//! \~english Mathematical solver for differential equations
//! \~russian Математический решатель дифференциальных уравнений
//! \details
//! \~english Solver for ordinary differential equations using various numerical methods
//! \~russian Решатель обыкновенных дифференциальных уравнений с использованием различных численных методов
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PIMathSolver PIMathSolver
@@ -25,50 +32,110 @@
#include "pimathmatrix.h" #include "pimathmatrix.h"
/// Differential evaluations //! \~english Differential evaluations
//! \~russian Дифференциальные вычисления
//! \~english Transfer function representation
//! \~russian Представление передаточной функции
struct PIP_EXPORT TransferFunction { struct PIP_EXPORT TransferFunction {
PIVector<double> vector_Bm, vector_An; PIVector<double> vector_Bm, vector_An;
}; };
//! \~english Mathematical solver for differential equations
//! \~russian Математический решатель дифференциальных уравнений
class PIP_EXPORT PIMathSolver { class PIP_EXPORT PIMathSolver {
public: public:
//! \~english Solving methods for differential equations
//! \~russian Методы решения дифференциальных уравнений
enum Method { enum Method {
Global = -1, Global = -1, //!< \~english Use global method
Eyler_1 = 01, //! \~russian Использовать глобальный метод
Eyler_2 = 02, Eyler_1 = 01, //!< \~english Euler method (first order)
EylerKoshi = 03, //! \~russian Метод Эйлера (1-й порядок)
RungeKutta_4 = 14, Eyler_2 = 02, //!< \~english Euler method (second order)
AdamsBashfortMoulton_2 = 22, //! \~russian Метод Эйлера (2-й порядок)
AdamsBashfortMoulton_3 = 23, EylerKoshi = 03, //!< \~english Euler-Cauchy method
AdamsBashfortMoulton_4 = 24, //! \~russian Метод Эйлера-Коши
PolynomialApproximation_2 = 32, RungeKutta_4 = 14, //!< \~english Runge-Kutta 4th order
PolynomialApproximation_3 = 33, //! \~russian Метод Рунге-Кутта 4-го порядка
PolynomialApproximation_4 = 34, AdamsBashfortMoulton_2 = 22, //!< \~english Adams-Bashforth-Moulton 2nd order
PolynomialApproximation_5 = 35 //! \~russian Метод Адамса-Башфорта-Мултона 2-го порядка
AdamsBashfortMoulton_3 = 23, //!< \~english Adams-Bashforth-Moulton 3rd order
//! \~russian Метод Адамса-Башфорта-Мултона 3-го порядка
AdamsBashfortMoulton_4 = 24, //!< \~english Adams-Bashforth-Moulton 4th order
//! \~russian Метод Адамса-Башфорта-Мултона 4-го порядка
PolynomialApproximation_2 = 32, //!< \~english Polynomial approximation 2nd order
//! \~russian Метод полиномиальной аппроксимации 2-го порядка
PolynomialApproximation_3 = 33, //!< \~english Polynomial approximation 3rd order
//! \~russian Метод полиномиальной аппроксимации 3-го порядка
PolynomialApproximation_4 = 34, //!< \~english Polynomial approximation 4th order
//! \~russian Метод полиномиальной аппроксимации 4-го порядка
PolynomialApproximation_5 = 35 //!< \~english Polynomial approximation 5th order
//! \~russian Метод полиномиальной аппроксимации 5-го порядка
}; };
//! Constructs an empty solver
PIMathSolver(); PIMathSolver();
//! \~english Solve differential equation at point u with step h
//! \~russian Решить дифференциальное уравнение в точке u с шагом h
void solve(double u, double h); void solve(double u, double h);
//! Initialize from transfer function
//! \~english Set up solver from transfer function coefficients
//! \~russian Инициализировать решатель из коэффициентов передаточной функции
void fromTF(const TransferFunction & TF); void fromTF(const TransferFunction & TF);
//! Set solving method
//! \~english Set numerical method for solving
//! \~russian Установить численный метод решения
void setMethod(Method m) { method = m; } void setMethod(Method m) { method = m; }
//! Set simulation time
//! \~english Set simulation time
//! \~russian Установить время моделирования
void setTime(double time); void setTime(double time);
//! \~english Solve using Euler method (1st order)
//! \~russian Решение методом Эйлера (1-й порядок)
void solveEyler1(double u, double h); void solveEyler1(double u, double h);
//! \~english Solve using Euler method (2nd order)
//! \~russian Решение методом Эйлера (2-й порядок)
void solveEyler2(double u, double h); void solveEyler2(double u, double h);
//! \~english Solve using Runge-Kutta 4th order
//! \~russian Решение методом Рунге-Кутта 4-го порядка
void solveRK4(double u, double h); void solveRK4(double u, double h);
//! \~english Solve using Adams-Bashforth-Moulton 2nd order
//! \~russian Решение методом Адамса-Башфорта-Мултона 2-го порядка
void solveABM2(double u, double h); void solveABM2(double u, double h);
//! \~english Solve using Adams-Bashforth-Moulton 3rd order
//! \~russian Решение методом Адамса-Башфорта-Мултона 3-го порядка
void solveABM3(double u, double h); void solveABM3(double u, double h);
//! \~english Solve using Adams-Bashforth-Moulton 4th order
//! \~russian Решение методом Адамса-Башфорта-Мултона 4-го порядка
void solveABM4(double u, double h); void solveABM4(double u, double h);
//! \~english Solve using polynomial approximation
//! \~russian Решение методом полиномиальной аппроксимации
void solvePA(double u, double h, uint deg); void solvePA(double u, double h, uint deg);
//! \~english Solve using polynomial approximation 2nd order
//! \~russian Решение методом полиномиальной аппроксимации 2-го порядка
void solvePA2(double u, double h); void solvePA2(double u, double h);
//! \~english Solve using polynomial approximation 3rd order
//! \~russian Решение методом полиномиальной аппроксимации 3-го порядка
void solvePA3(double u, double h); void solvePA3(double u, double h);
//! \~english Solve using polynomial approximation 4th order
//! \~russian Решение методом полиномиальной аппроксимации 4-го порядка
void solvePA4(double u, double h); void solvePA4(double u, double h);
//! \~english Solve using polynomial approximation 5th order
//! \~russian Решение методом полиномиальной аппроксимации 5-го порядка
void solvePA5(double u, double h); void solvePA5(double u, double h);
//! \~english Solution vector
//! \~russian Вектор решения
PIMathVectord X; PIMathVectord X;
//! \~english Global default method
//! \~russian Глобальный метод по умолчанию
static Method method_global; static Method method_global;
//! \~english Description of available methods
//! \~russian Описание доступных методов
static const char methods_desc[]; static const char methods_desc[];
private: private:

View File

@@ -1,9 +1,16 @@
/*! \file pimathvector.h //! \addtogroup Math
* \ingroup Math //! \{
* \~\brief //! \file pimathvector.h
* \~english Math vector //! \brief
* \~russian Математический вектор //! \~english Math vector
*/ //! \~russian Математический вектор
//! \details
//! \~english Fixed-size and dynamic mathematical vector implementations. Provides PIMathVectorT for compile-time fixed-size vectors and
//! PIMathVector for runtime dynamic-size vectors with support for arithmetic and complex number types.
//! \~russian Реализации математических векторов фиксированного и динамического размера. Предоставляет PIMathVectorT для векторов
//! фиксированного размера во время компиляции и PIMathVector для векторов динамического размера во время выполнения с поддержкой
//! арифметических и комплексных типов чисел.
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PIMathVector PIMathVector
@@ -40,6 +47,15 @@ class PIMathMatrixT;
#define PIMV_FOR for (uint i = 0; i < Size; ++i) #define PIMV_FOR for (uint i = 0; i < Size; ++i)
//! \~english Template class for fixed-size mathematical vector
//! \~russian Шаблонный класс для математического вектора фиксированного размера
//! \brief Fixed-size mathematical vector with compile-time size
//! \~english Fixed-size mathematical vector with compile-time size
//! \~russian Вектор математический фиксированного размера с размером во время компиляции
//! \details Provides vector operations including arithmetic, normalization, angles, cross product, and dot product
//! \~russian Предоставляет операции вектора включая арифметику, нормализацию, углы, векторное произведение и скалярное произведение
//! \tparam Size The fixed size of the vector
//! \tparam Type The element type (arithmetic or complex)
template<uint Size, typename Type = double> template<uint Size, typename Type = double>
class PIP_EXPORT PIMathVectorT { class PIP_EXPORT PIMathVectorT {
typedef PIMathVectorT<Size, Type> _CVector; typedef PIMathVectorT<Size, Type> _CVector;
@@ -47,50 +63,93 @@ class PIP_EXPORT PIMathVectorT {
static_assert(Size > 0, "Size must be > 0"); static_assert(Size > 0, "Size must be > 0");
public: public:
//! \~english Constructor with default value for all elements
//! \~russian Конструктор со значением по умолчанию для всех элементов
//! \param v The value to initialize all elements
PIMathVectorT(const Type & v = Type()) { PIMV_FOR c[i] = v; } PIMathVectorT(const Type & v = Type()) { PIMV_FOR c[i] = v; }
//! \~english Constructor from PIVector
//! \~russian Конструктор из PIVector
//! \param val The PIVector to copy from
PIMathVectorT(const PIVector<Type> & val) { PIMathVectorT(const PIVector<Type> & val) {
assert(Size == val.size()); assert(Size == val.size());
PIMV_FOR c[i] = val[i]; PIMV_FOR c[i] = val[i];
} }
//! \~english Constructor from initializer list
//! \~russian Конструктор из списка инициализации
//! \param init_list The initializer list to copy from
PIMathVectorT(std::initializer_list<Type> init_list) { PIMathVectorT(std::initializer_list<Type> init_list) {
assert(Size == init_list.size()); assert(Size == init_list.size());
PIMV_FOR c[i] = init_list.begin()[i]; PIMV_FOR c[i] = init_list.begin()[i];
} }
//! \~english Create vector from two points (st -> fn)
//! \~russian Создать вектор из двух точек (st -> fn)
//! \param st The start point
//! \param fn The finish point
//! \returns Vector from st to fn
static _CVector fromTwoPoints(const _CVector & st, const _CVector & fn) { static _CVector fromTwoPoints(const _CVector & st, const _CVector & fn) {
_CVector tv; _CVector tv;
PIMV_FOR tv[i] = fn[i] - st[i]; PIMV_FOR tv[i] = fn[i] - st[i];
return tv; return tv;
} }
//! \~english Get vector size
//! \~russian Получить размер вектора
//! \returns The fixed size of the vector
constexpr uint size() const { return Size; } constexpr uint size() const { return Size; }
//! \~english Fill vector with a single value
//! \~russian Заполнить вектор одним значением
//! \param v The value to fill
//! \returns Reference to this vector
_CVector & fill(const Type & v) { _CVector & fill(const Type & v) {
PIMV_FOR c[i] = v; PIMV_FOR c[i] = v;
return *this; return *this;
} }
//! \~english Add value to all elements
//! \~russian Прибавить значение ко всем элементам
//! \param v The value to add
//! \returns Reference to this vector
_CVector & move(const Type & v) { _CVector & move(const Type & v) {
PIMV_FOR c[i] += v; PIMV_FOR c[i] += v;
return *this; return *this;
} }
//! \~english Add vector to this vector
//! \~russian Прибавить вектор к этому вектору
//! \param v The vector to add
//! \returns Reference to this vector
_CVector & move(const _CVector & v) { _CVector & move(const _CVector & v) {
PIMV_FOR c[i] += v[i]; PIMV_FOR c[i] += v[i];
return *this; return *this;
} }
//! \~english Swap two elements
//! \~russian Поменять два элемента местами
//! \param f First element index
//! \param s Second element index
//! \returns Reference to this vector
_CVector & swapElements(uint f, uint s) { _CVector & swapElements(uint f, uint s) {
piSwap<Type>(c[f], c[s]); piSwap<Type>(c[f], c[s]);
return *this; return *this;
} }
//! \~english Get squared length of vector
//! \~russian Получить квадрат длины вектора
//! \returns Sum of squares of all elements
Type lengthSqr() const { Type lengthSqr() const {
Type tv(0); Type tv(0);
PIMV_FOR tv += c[i] * c[i]; PIMV_FOR tv += c[i] * c[i];
return tv; return tv;
} }
//! \~english Get length of vector
//! \~russian Получить длину вектора
//! \returns Square root of lengthSqr, unavailable for complex types
Type length() const { Type length() const {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) return std::sqrt(lengthSqr()); if (std::is_arithmetic<Type>::value) return std::sqrt(lengthSqr());
// if (is_complex<Type>::value) return 1000.; // std::sqrt(lengthSqr()); // if (is_complex<Type>::value) return 1000.; // std::sqrt(lengthSqr());
} }
//! \~english Get Manhattan length (sum of absolute values)
//! \~russian Получить манхэттенскую длину (сумма абсолютных значений)
//! \returns Sum of absolute values of all elements, unavailable for complex types
Type manhattanLength() const { Type manhattanLength() const {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
@@ -99,6 +158,10 @@ public:
return tv; return tv;
} }
} }
//! \~english Get cosine of angle between two vectors
//! \~russian Получить косинус угла между двумя векторами
//! \param v The other vector
//! \returns cos(angle), unavailable for complex types
Type angleCos(const _CVector & v) const { Type angleCos(const _CVector & v) const {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
@@ -107,6 +170,10 @@ public:
return dot(v) / tv; return dot(v) / tv;
} }
} }
//! \~english Get sine of angle between two vectors
//! \~russian Получить синус угла между двумя векторами
//! \param v The other vector
//! \returns sin(angle), unavailable for complex types
Type angleSin(const _CVector & v) const { Type angleSin(const _CVector & v) const {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
@@ -114,24 +181,40 @@ public:
return std::sqrt(Type(1) - tv * tv); return std::sqrt(Type(1) - tv * tv);
} }
} }
//! \~english Get angle in radians between two vectors
//! \~russian Получить угол в радианах между двумя векторами
//! \param v The other vector
//! \returns Angle in radians, unavailable for complex types
Type angleRad(const _CVector & v) const { Type angleRad(const _CVector & v) const {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
return std::acos(angleCos(v)); return std::acos(angleCos(v));
} }
} }
//! \~english Get angle in degrees between two vectors
//! \~russian Получить угол в градусах между двумя векторами
//! \param v The other vector
//! \returns Angle in degrees, unavailable for complex types
Type angleDeg(const _CVector & v) const { Type angleDeg(const _CVector & v) const {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
return toDeg(angleRad(v)); return toDeg(angleRad(v));
} }
} }
//! \~english Get elevation angle
//! \~russian Получить угол возвышения
//! \param v The other vector
//! \returns Elevation angle in degrees, unavailable for complex types
Type angleElevation(const _CVector & v) const { Type angleElevation(const _CVector & v) const {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
return 90.0 - angleDeg(v - *this); return 90.0 - angleDeg(v - *this);
} }
} }
//! \~english Get projection of this vector onto another vector
//! \~russian Получить проекцию этого вектора на другой вектор
//! \param v The vector to project onto
//! \returns Projection vector, unavailable for complex types
_CVector projection(const _CVector & v) { _CVector projection(const _CVector & v) {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
@@ -140,6 +223,9 @@ public:
return v * (dot(v) / tv); return v * (dot(v) / tv);
} }
} }
//! \~english Normalize vector in place
//! \~russian Нормализовать вектор на месте
//! \returns Reference to this vector, unavailable for complex types
_CVector & normalize() { _CVector & normalize() {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
@@ -150,61 +236,134 @@ public:
return *this; return *this;
} }
} }
//! \~english Get normalized copy of vector
//! \~russian Получить нормализованную копию вектора
//! \returns New normalized vector, unavailable for complex types
_CVector normalized() { _CVector normalized() {
_CVector tv(*this); _CVector tv(*this);
tv.normalize(); tv.normalize();
return tv; return tv;
} }
//! \~english Check if vector is null (all elements zero)
//! \~russian Проверить, является ли вектор нулевым (все элементы нули)
//! \returns true if vector is null
bool isNull() const { bool isNull() const {
PIMV_FOR if (c[i] != Type{}) return false; PIMV_FOR if (c[i] != Type{}) return false;
return true; return true;
} }
//! \~english Check if vectors are orthogonal
//! \~russian Проверить, перпендикулярны ли векторы
//! \param v The other vector
//! \returns true if vectors are orthogonal
bool isOrtho(const _CVector & v) const { return ((*this) ^ v) == Type{}; } bool isOrtho(const _CVector & v) const { return ((*this) ^ v) == Type{}; }
//! \~english Get element at index (non-const)
//! \~russian Получить элемент по индексу (non-const)
//! \param index Element index
//! \returns Reference to element
Type & operator[](uint index) { return c[index]; } Type & operator[](uint index) { return c[index]; }
//! \~english Get element at index (const)
//! \~russian Получить элемент по индексу (const)
//! \param index Element index
//! \returns Copy of element
const Type & operator[](uint index) const { return c[index]; } const Type & operator[](uint index) const { return c[index]; }
//! \~english Get element at index (const version)
//! \~russian Получить элемент по индексу (версия const)
//! \param index Element index
//! \returns Copy of element
Type at(uint index) const { return c[index]; } Type at(uint index) const { return c[index]; }
//! \~english Get element at index (non-const, alternative)
//! \~russian Получить элемент по индексу (non-const, альтернативный метод)
//! \param index Element index
//! \returns Reference to element
inline Type & element(uint index) { return c[index]; } inline Type & element(uint index) { return c[index]; }
//! \~english Get element at index (const, alternative)
//! \~russian Получить элемент по индексу (const, альтернативный метод)
//! \param index Element index
//! \returns Copy of element
inline const Type & element(uint index) const { return c[index]; } inline const Type & element(uint index) const { return c[index]; }
//! \~english Assign value to all elements
//! \~russian Присвоить значение всем элементам
//! \param v The value to assign
//! \returns Reference to this vector
_CVector & operator=(const Type & v) { _CVector & operator=(const Type & v) {
PIMV_FOR c[i] = v; PIMV_FOR c[i] = v;
return *this; return *this;
} }
//! \~english Check equality with another vector
//! \~russian Проверить равенство с другим вектором
//! \param v The vector to compare with
//! \returns true if all elements are equal
bool operator==(const _CVector & v) const { bool operator==(const _CVector & v) const {
PIMV_FOR if (c[i] != v[i]) return false; PIMV_FOR if (c[i] != v[i]) return false;
return true; return true;
} }
//! \~english Check inequality with another vector
//! \~russian Проверить неравенство с другим вектором
//! \param v The vector to compare with
//! \returns true if any element differs
bool operator!=(const _CVector & v) const { return !(*this == c); } bool operator!=(const _CVector & v) const { return !(*this == c); }
//! \~english Add vector to this vector
//! \~russian Прибавить вектор к этому вектору
//! \param v The vector to add
void operator+=(const _CVector & v) { PIMV_FOR c[i] += v[i]; } void operator+=(const _CVector & v) { PIMV_FOR c[i] += v[i]; }
//! \~english Subtract vector from this vector
//! \~russian Вычесть вектор из этого вектора
//! \param v The vector to subtract
void operator-=(const _CVector & v) { PIMV_FOR c[i] -= v[i]; } void operator-=(const _CVector & v) { PIMV_FOR c[i] -= v[i]; }
//! \~english Multiply all elements by scalar
//! \~russian Умножить все элементы на скаляр
//! \param v The scalar to multiply by
void operator*=(const Type & v) { PIMV_FOR c[i] *= v; } void operator*=(const Type & v) { PIMV_FOR c[i] *= v; }
//! \~english Divide all elements by scalar
//! \~russian Разделить все элементы на скаляр
//! \param v The scalar to divide by
void operator/=(const Type & v) { void operator/=(const Type & v) {
assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP);
PIMV_FOR c[i] /= v; PIMV_FOR c[i] /= v;
} }
//! \~english Unary minus operator
//! \~russian Унарный оператор минус
//! \returns New vector with negated elements
_CVector operator-() const { _CVector operator-() const {
_CVector tv; _CVector tv;
PIMV_FOR tv[i] = -c[i]; PIMV_FOR tv[i] = -c[i];
return tv; return tv;
} }
//! \~english Add two vectors
//! \~russian Сложить два вектора
//! \param v The vector to add
//! \returns New vector with sum of elements
_CVector operator+(const _CVector & v) const { _CVector operator+(const _CVector & v) const {
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] += v[i]; PIMV_FOR tv[i] += v[i];
return tv; return tv;
} }
//! \~english Subtract two vectors
//! \~russian Вычесть два вектора
//! \param v The vector to subtract
//! \returns New vector with difference of elements
_CVector operator-(const _CVector & v) const { _CVector operator-(const _CVector & v) const {
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] -= v[i]; PIMV_FOR tv[i] -= v[i];
return tv; return tv;
} }
//! \~english Multiply vector by scalar
//! \~russian Умножить вектор на скаляр
//! \param v The scalar to multiply by
//! \returns New vector with scaled elements
_CVector operator*(const Type & v) const { _CVector operator*(const Type & v) const {
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] *= v; PIMV_FOR tv[i] *= v;
return tv; return tv;
} }
//! \~english Divide vector by scalar
//! \~russian Разделить вектор на скаляр
//! \param v The scalar to divide by
//! \returns New vector with scaled elements
_CVector operator/(const Type & v) const { _CVector operator/(const Type & v) const {
assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP);
_CVector tv = _CVector(*this); _CVector tv = _CVector(*this);
@@ -212,6 +371,10 @@ public:
return tv; return tv;
} }
//! \~english Compute cross product with another vector (3D only)
//! \~russian Вычислить векторное произведение с другим вектором (только 3D)
//! \param v The other vector
//! \returns Cross product vector
_CVector cross(const _CVector & v) const { _CVector cross(const _CVector & v) const {
static_assert(Size == 3, "cross product avalible only for 3D vectors"); static_assert(Size == 3, "cross product avalible only for 3D vectors");
_CVector tv; _CVector tv;
@@ -220,17 +383,33 @@ public:
tv[2] = c[0] * v[1] - v[0] * c[1]; tv[2] = c[0] * v[1] - v[0] * c[1];
return tv; return tv;
} }
//! \~english Compute dot product with another vector
//! \~russian Вычислить скалярное произведение с другим вектором
//! \param v The other vector
//! \returns Dot product (sum of element-wise products)
Type dot(const _CVector & v) const { Type dot(const _CVector & v) const {
Type tv{}; Type tv{};
PIMV_FOR tv += c[i] * v[i]; PIMV_FOR tv += c[i] * v[i];
return tv; return tv;
} }
//! \~english Element-wise multiplication with another vector
//! \~russian Покомпонентное умножение с другим вектором
//! \param v The other vector
//! \returns New vector with element-wise products
_CVector mul(const _CVector & v) const { _CVector mul(const _CVector & v) const {
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] *= v[i]; PIMV_FOR tv[i] *= v[i];
return tv; return tv;
} }
//! \~english Element-wise multiplication with scalar
//! \~russian Покомпонентное умножение на скаляр
//! \param v The scalar to multiply by
//! \returns New vector with scaled elements
_CVector mul(const Type & v) const { return (*this) * v; } _CVector mul(const Type & v) const { return (*this) * v; }
//! \~english Element-wise division by another vector
//! \~russian Покомпонентное деление на другой вектор
//! \param v The vector to divide by
//! \returns New vector with element-wise quotients
_CVector div(const _CVector & v) const { _CVector div(const _CVector & v) const {
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR { PIMV_FOR {
@@ -239,14 +418,26 @@ public:
} }
return tv; return tv;
} }
//! \~english Element-wise division by scalar
//! \~russian Покомпонентное деление на скаляр
//! \param v The scalar to divide by
//! \returns New vector with scaled elements
_CVector div(const Type & v) const { return (*this) / v; } _CVector div(const Type & v) const { return (*this) / v; }
//! \~english Transpose vector to 1xN matrix
//! \~russian Транспонировать вектор в матрицу 1xN
//! \returns 1xN matrix representation of this vector
PIMathMatrixT<1, Size, Type> transposed() const { PIMathMatrixT<1, Size, Type> transposed() const {
PIMathMatrixT<1, Size, Type> ret; PIMathMatrixT<1, Size, Type> ret;
PIMV_FOR ret[0][i] = c[i]; PIMV_FOR ret[0][i] = c[i];
return ret; return ret;
} }
//! \~english Get distance from this point to line defined by two points
//! \~russian Получить расстояние от этой точки до линии, заданной двумя точками
//! \param lp0 First point on the line
//! \param lp1 Second point on the line
//! \returns Distance from point to line, unavailable for complex types
Type distToLine(const _CVector & lp0, const _CVector & lp1) { Type distToLine(const _CVector & lp0, const _CVector & lp1) {
static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex"); static_assert(std::is_arithmetic<Type>::value, "Unavailable for complex");
if (std::is_arithmetic<Type>::value) { if (std::is_arithmetic<Type>::value) {
@@ -258,6 +449,11 @@ public:
} }
} }
//! \~english Convert vector to another size and type
//! \~russian Преобразовать вектор в другой размер и тип
//! \tparam Size1 New vector size
//! \tparam Type1 New element type
//! \returns Vector with new size and type
template<uint Size1, typename Type1> /// vector {Size, Type} to vector {Size1, Type1} template<uint Size1, typename Type1> /// vector {Size, Type} to vector {Size1, Type1}
PIMathVectorT<Size1, Type1> turnTo() const { PIMathVectorT<Size1, Type1> turnTo() const {
PIMathVectorT<Size1, Type1> tv; PIMathVectorT<Size1, Type1> tv;
@@ -267,10 +463,10 @@ public:
return tv; return tv;
} }
//! \~english //! \~english Returns this vector with another element type
//! \brief Returns this vector with another element type. //! \~russian Возвращает этот вектор с другим типом элементов
//! \~russian //! \tparam T New element type
//! \brief Возвращает этот вектор с другим типом элементов. //! \returns Vector with new element type
template<typename T> template<typename T>
PIMathVectorT<Size, T> toType() const { PIMathVectorT<Size, T> toType() const {
PIMathVectorT<Size, T> ret; PIMathVectorT<Size, T> ret;
@@ -278,13 +474,22 @@ public:
return ret; return ret;
} }
//! \~english //! \~english Returns the subvector with size SubSize. Elements are taken from coordinates "offset"
//! \brief Returns the subvector with size SubSize. Elements takes from coordinates "offset". //! \~russian Возвращает подвектор с размерами SubSize. Элементы берутся с координат "offset"
//! \details //! \tparam SubSize Size of the subvector
//! \~russian //! \param offset Starting coordinate (can be negative)
//! \brief Возвращает подвектор с размерами SubSize. Элементы берутся с координат "offset". //! \details Coordinates can be negative. The returned subvector can be of any size. If original elements are out of bounds, zeros will
//! \details Координаты могут быть отрицательными. Возвращаемый подвектор может быть любого размера. Если исходные элементы выходят //! be used
//! за границы исходного подвектора, то в подвекторе будут нули. //! \~russian Координаты могут быть отрицательными. Возвращаемый подвектор может быть любого размера. Если исходные элементы выходят за
//! границы исходного подвектора, то в подвекторе будут нули \returns Subvector of specified size
//! \~english Returns the subvector with size SubSize. Elements are taken from coordinates "offset"
//! \~russian Возвращает подвектор с размерами SubSize. Элементы берутся с координат "offset"
//! \tparam SubSize Size of the subvector
//! \param offset Starting coordinate (can be negative)
//! \details Coordinates can be negative. The returned subvector can be of any size. If original elements are out of bounds, zeros will
//! be used
//! \~russian Координаты могут быть отрицательными. Возвращаемый подвектор может быть любого размера. Если исходные элементы выходят за
//! границы исходного подвектора, то в подвекторе будут нули \returns Subvector of specified size
template<uint SubSize> template<uint SubSize>
PIMathVectorT<SubSize, Type> subvector(int offset = 0) const { PIMathVectorT<SubSize, Type> subvector(int offset = 0) const {
PIMathVectorT<SubSize, Type> ret; PIMathVectorT<SubSize, Type> ret;
@@ -296,14 +501,16 @@ public:
return ret; return ret;
} }
//! \~english //! \~english Set the subvector "v" at coordinates "index"
//! \brief Set the subvector "v" in coordinates "index". //! \~russian Устанавливает подвектор "v" в координаты "index"
//! \details //! \tparam SubSize Size of the subvector
//! \~russian //! \param index Starting coordinate (can be negative)
//! \brief Устанавливает подвектор "v" в координаты "index". //! \param v The subvector to set
//! \details Присваивает значения из вектора "v" в область текущиего вектора, ограниченную //! \details Assigns values from vector "v" to the area of current vector bounded by "v"'s size and vector boundaries, based on the
//! размерами "v", самого вектор и границами, исходя из координат установки. Координаты могут быть отрицательными. //! installation coordinates. Coordinates can be negative. Vector "v" can be of any size. Returns reference to this vector.
//! Вектор "v" может быть любого размера. Возвращает ссылку на этот вектор. //! \~russian Присваивает значения из вектора "v" в область текущего вектора, ограниченную размерами "v", самого вектор и границами,
//! исходя из координат установки. Координаты могут быть отрицательными. Вектор "v" может быть любого размера. Возвращает ссылку на этот
//! вектор. \returns Reference to this vector
template<uint SubSize> template<uint SubSize>
PIMathVectorT<Size, Type> & setSubvector(int index, const PIMathVectorT<SubSize, Type> & v) { PIMathVectorT<Size, Type> & setSubvector(int index, const PIMathVectorT<SubSize, Type> & v) {
for (int i = 0; i < (int)SubSize; ++i) { for (int i = 0; i < (int)SubSize; ++i) {
@@ -314,23 +521,68 @@ public:
return *this; return *this;
} }
//! \~english Static cross product of two vectors
//! \~russian Статическое векторное произведение двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns Cross product vector
static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); } static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); }
//! \~english Static dot product of two vectors
//! \~russian Статическое скалярное произведение двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns Dot product
static Type dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); } static Type dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); }
//! \~english Static element-wise multiplication of two vectors
//! \~russian Статическое покомпонентное умножение двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns New vector with element-wise products
static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); } static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); }
//! \~english Static scalar multiplication (scalar * vector)
//! \~russian Статическое скалярное умножение (скаляр * вектор)
//! \param v1 Scalar
//! \param v2 Vector
//! \returns Scaled vector
static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; } static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; }
//! \~english Static scalar multiplication (vector * scalar)
//! \~russian Статическое скалярное умножение (вектор * скаляр)
//! \param v1 Vector
//! \param v2 Scalar
//! \returns Scaled vector
static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; } static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; }
//! \~english Static element-wise division of two vectors
//! \~russian Статическое покомпонентное деление двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns New vector with element-wise quotients
static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); } static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); }
//! \~english Static scalar division (vector / scalar)
//! \~russian Статическое скалярное деление (вектор / скаляр)
//! \param v1 Vector
//! \param v2 Scalar
//! \returns Scaled vector
static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; } static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; }
private: private:
Type c[Size]; Type c[Size];
}; };
//! \~english Scalar multiplication (scalar * vector)
//! \~russian Скалярное умножение (скаляр * вектор)
//! \param x Scalar
//! \param v Vector
//! \returns Scaled vector
template<uint Size, typename Type> template<uint Size, typename Type>
inline PIMathVectorT<Size, Type> operator*(const Type & x, const PIMathVectorT<Size, Type> & v) { inline PIMathVectorT<Size, Type> operator*(const Type & x, const PIMathVectorT<Size, Type> & v) {
return v * x; return v * x;
} }
//! \~english Output vector to PIP stream
//! \~russian Вывести вектор в поток PIP
//! \param s The PIP output stream
//! \param v The vector to output
//! \returns Reference to the stream
template<uint Size, typename Type> template<uint Size, typename Type>
inline PICout operator<<(PICout s, const PIMathVectorT<Size, Type> & v) { inline PICout operator<<(PICout s, const PIMathVectorT<Size, Type> & v) {
s.space(); s.space();
@@ -345,12 +597,23 @@ inline PICout operator<<(PICout s, const PIMathVectorT<Size, Type> & v) {
return s; return s;
} }
//! \~english 2D integer vector
//! \~russian 2D целочисленный вектор
typedef PIMathVectorT<2u, int> PIMathVectorT2i; typedef PIMathVectorT<2u, int> PIMathVectorT2i;
//! \~english 3D integer vector
//! \~russian 3D целочисленный вектор
typedef PIMathVectorT<3u, int> PIMathVectorT3i; typedef PIMathVectorT<3u, int> PIMathVectorT3i;
//! \~english 4D integer vector
//! \~russian 4D целочисленный вектор
typedef PIMathVectorT<4u, int> PIMathVectorT4i; typedef PIMathVectorT<4u, int> PIMathVectorT4i;
//! \~english 2D double vector
//! \~russian 2D вектор с числами двойной точности
typedef PIMathVectorT<2u, double> PIMathVectorT2d; typedef PIMathVectorT<2u, double> PIMathVectorT2d;
//! \~english 3D double vector
//! \~russian 3D вектор с числами двойной точности
typedef PIMathVectorT<3u, double> PIMathVectorT3d; typedef PIMathVectorT<3u, double> PIMathVectorT3d;
//! \~english 4D double vector
//! \~russian 4D вектор с числами двойной точности
typedef PIMathVectorT<4u, double> PIMathVectorT4d; typedef PIMathVectorT<4u, double> PIMathVectorT4d;
@@ -360,6 +623,14 @@ typedef PIMathVectorT<4u, double> PIMathVectorT4d;
#define PIMV_FOR for (uint i = 0; i < c.size(); ++i) #define PIMV_FOR for (uint i = 0; i < c.size(); ++i)
//! \~english Template class for dynamic-size mathematical vector
//! \~russian Шаблонный класс для математического вектора динамического размера
//! \brief Dynamic-size mathematical vector with runtime size
//! \~english Dynamic-size mathematical vector with runtime size
//! \~russian Вектор математический динамического размера с размером во время выполнения
//! \details Provides vector operations including arithmetic, normalization, angles, cross product, and dot product for dynamic-size vectors
//! \~russian Предоставляет операции вектора включая арифметику, нормализацию, углы, векторное произведение и скалярное произведение для
//! векторов динамического размера \tparam Type The element type (arithmetic or complex)
template<typename Type> template<typename Type>
class PIP_EXPORT PIMathVector { class PIP_EXPORT PIMathVector {
typedef PIMathVector<Type> _CVector; typedef PIMathVector<Type> _CVector;
@@ -369,17 +640,38 @@ class PIP_EXPORT PIMathVector {
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathVector<Type1> & v); friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathVector<Type1> & v);
public: public:
//! \~english Constructor with size and initial value
//! \~russian Конструктор с размером и начальным значением
//! \param size The initial size of the vector
//! \param new_value The initial value for all elements
PIMathVector(const uint size = 0, const Type & new_value = Type()) { c.resize(size, new_value); } PIMathVector(const uint size = 0, const Type & new_value = Type()) { c.resize(size, new_value); }
//! \~english Constructor from PIVector
//! \~russian Конструктор из PIVector
//! \param val The PIVector to copy from
PIMathVector(const PIVector<Type> & val) { c = val; } PIMathVector(const PIVector<Type> & val) { c = val; }
//! \~english Constructor from move PIVector
//! \~russian Конструктор из move PIVector
//! \param val The PIVector to move from
PIMathVector(PIVector<Type> && val): c(std::move(val)) {} PIMathVector(PIVector<Type> && val): c(std::move(val)) {}
//! \~english Constructor from initializer list
//! \~russian Конструктор из списка инициализации
//! \param init_list The initializer list to copy from
PIMathVector(std::initializer_list<Type> init_list) { c = PIVector<Type>(init_list); } PIMathVector(std::initializer_list<Type> init_list) { c = PIVector<Type>(init_list); }
//! \~english Constructor from fixed-size vector
//! \~russian Конструктор из фиксированного вектора
//! \param val The fixed-size vector to copy from
template<uint Size> template<uint Size>
PIMathVector(const PIMathVectorT<Size, Type> & val) { PIMathVector(const PIMathVectorT<Size, Type> & val) {
c.resize(Size); c.resize(Size);
PIMV_FOR c[i] = val[i]; PIMV_FOR c[i] = val[i];
} }
//! \~english Create vector from two points (st -> fn)
//! \~russian Создать вектор из двух точек (st -> fn)
//! \param st The start point
//! \param fn The finish point
//! \returns Vector from st to fn
static PIMathVector fromTwoPoints(const _CVector & st, const _CVector & fn) { static PIMathVector fromTwoPoints(const _CVector & st, const _CVector & fn) {
assert(st.size() == fn.size()); assert(st.size() == fn.size());
_CVector v(st.size()); _CVector v(st.size());
@@ -387,8 +679,22 @@ public:
v.c[i] = fn[i] - st[i]; v.c[i] = fn[i] - st[i];
} }
//! \~english Create zero vector of specified size
//! \~russian Создать нулевой вектор указанного размера
//! \param size The size of the vector
//! \returns Zero vector
static PIMathVector zeros(const uint size) { return PIMathVector(size, Type()); } static PIMathVector zeros(const uint size) { return PIMathVector(size, Type()); }
//! \~english Create vector with all elements set to 1
//! \~russian Создать вектор со всеми элементами, равными 1
//! \param size The size of the vector
//! \returns Vector filled with ones
static PIMathVector ones(const uint size) { return PIMathVector(size, Type(1)); } static PIMathVector ones(const uint size) { return PIMathVector(size, Type(1)); }
//! \~english Create vector with values in arithmetic progression
//! \~russian Создать вектор со значениями в арифметической прогрессии
//! \param start The start value
//! \param stop The stop value (exclusive)
//! \param step The step between values
//! \returns Vector with arithmetic progression
static PIMathVector arange(const Type start, const Type stop, const Type step = Type(1)) { static PIMathVector arange(const Type start, const Type stop, const Type step = Type(1)) {
PIVector<Type> v; PIVector<Type> v;
for (Type i = start; i < stop; i += step) for (Type i = start; i < stop; i += step)
@@ -396,63 +702,125 @@ public:
return PIMathVector(std::move(v)); return PIMathVector(std::move(v));
} }
//! \~english Get vector size
//! \~russian Получить размер вектора
//! \returns The dynamic size of the vector
uint size() const { return c.size(); } uint size() const { return c.size(); }
//! \~english Resize the vector
//! \~russian Изменить размер вектора
//! \param size The new size
//! \param new_value The value for new elements
//! \returns Reference to this vector
_CVector & resize(uint size, const Type & new_value = Type()) { _CVector & resize(uint size, const Type & new_value = Type()) {
c.resize(size, new_value); c.resize(size, new_value);
return *this; return *this;
} }
//! \~english Get resized copy of the vector
//! \~russian Получить копию вектора с измененным размером
//! \param size The new size
//! \param new_value The value for new elements
//! \returns New vector with new size
_CVector resized(uint size, const Type & new_value = Type()) { _CVector resized(uint size, const Type & new_value = Type()) {
_CVector tv = _CVector(*this); _CVector tv = _CVector(*this);
tv.resize(size, new_value); tv.resize(size, new_value);
return tv; return tv;
} }
//! \~english Fill vector with a single value
//! \~russian Заполнить вектор одним значением
//! \param v The value to fill
//! \returns Reference to this vector
_CVector & fill(const Type & v) { _CVector & fill(const Type & v) {
c.fill(v); c.fill(v);
return *this; return *this;
} }
//! \~english Add value to all elements
//! \~russian Прибавить значение ко всем элементам
//! \param v The value to add
//! \returns Reference to this vector
_CVector & move(const Type & v) { _CVector & move(const Type & v) {
PIMV_FOR c[i] += v; PIMV_FOR c[i] += v;
return *this; return *this;
} }
//! \~english Add vector to this vector
//! \~russian Прибавить вектор к этому вектору
//! \param v The vector to add
//! \returns Reference to this vector
_CVector & move(const _CVector & v) { _CVector & move(const _CVector & v) {
assert(c.size() == v.size()); assert(c.size() == v.size());
PIMV_FOR c[i] += v[i]; PIMV_FOR c[i] += v[i];
return *this; return *this;
} }
//! \~english Swap two elements
//! \~russian Поменять два элемента местами
//! \param f First element index
//! \param s Second element index
//! \returns Reference to this vector
_CVector & swapElements(uint f, uint s) { _CVector & swapElements(uint f, uint s) {
piSwap<Type>(c[f], c[s]); piSwap<Type>(c[f], c[s]);
return *this; return *this;
} }
//! \~english Get squared length of vector
//! \~russian Получить квадрат длины вектора
//! \returns Sum of squares of all elements
Type lengthSqr() const { Type lengthSqr() const {
Type tv(0); Type tv(0);
PIMV_FOR tv += c[i] * c[i]; PIMV_FOR tv += c[i] * c[i];
return tv; return tv;
} }
//! \~english Get length of vector
//! \~russian Получить длину вектора
//! \returns Square root of lengthSqr
Type length() const { return std::sqrt(lengthSqr()); } Type length() const { return std::sqrt(lengthSqr()); }
//! \~english Get Manhattan length (sum of absolute values)
//! \~russian Получить манхэттенскую длину (сумма абсолютных значений)
//! \returns Sum of absolute values of all elements
Type manhattanLength() const { Type manhattanLength() const {
Type tv(0); Type tv(0);
PIMV_FOR tv += piAbs<Type>(c[i]); PIMV_FOR tv += piAbs<Type>(c[i]);
return tv; return tv;
} }
//! \~english Get cosine of angle between two vectors
//! \~russian Получить косинус угла между двумя векторами
//! \param v The other vector
//! \returns cos(angle)
Type angleCos(const _CVector & v) const { Type angleCos(const _CVector & v) const {
assert(c.size() == v.size()); assert(c.size() == v.size());
Type tv = v.length() * length(); Type tv = v.length() * length();
assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP);
return dot(v) / tv; return dot(v) / tv;
} }
//! \~english Get sine of angle between two vectors
//! \~russian Получить синус угла между двумя векторами
//! \param v The other vector
//! \returns sin(angle)
Type angleSin(const _CVector & v) const { Type angleSin(const _CVector & v) const {
assert(c.size() == v.size()); assert(c.size() == v.size());
Type tv = angleCos(v); Type tv = angleCos(v);
return std::sqrt(Type(1) - tv * tv); return std::sqrt(Type(1) - tv * tv);
} }
//! \~english Get angle in radians between two vectors
//! \~russian Получить угол в радианах между двумя векторами
//! \param v The other vector
//! \returns Angle in radians
Type angleRad(const _CVector & v) const { return std::acos(angleCos(v)); } Type angleRad(const _CVector & v) const { return std::acos(angleCos(v)); }
//! \~english Get angle in degrees between two vectors
//! \~russian Получить угол в градусах между двумя векторами
//! \param v The other vector
//! \returns Angle in degrees
Type angleDeg(const _CVector & v) const { return toDeg(angleRad(v)); } Type angleDeg(const _CVector & v) const { return toDeg(angleRad(v)); }
//! \~english Get projection of this vector onto another vector
//! \~russian Получить проекцию этого вектора на другой вектор
//! \param v The vector to project onto
//! \returns Projection vector
_CVector projection(const _CVector & v) { _CVector projection(const _CVector & v) {
assert(c.size() == v.size()); assert(c.size() == v.size());
Type tv = v.length(); Type tv = v.length();
assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP);
return v * (dot(v) / tv); return v * (dot(v) / tv);
} }
//! \~english Normalize vector in place
//! \~russian Нормализовать вектор на месте
//! \returns Reference to this vector
_CVector & normalize() { _CVector & normalize() {
Type tv = length(); Type tv = length();
assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP); assert(std::abs(tv) > PIMATHVECTOR_ZERO_CMP);
@@ -460,71 +828,143 @@ public:
PIMV_FOR c[i] /= tv; PIMV_FOR c[i] /= tv;
return *this; return *this;
} }
//! \~english Get normalized copy of vector
//! \~russian Получить нормализованную копию вектора
//! \returns New normalized vector
_CVector normalized() { _CVector normalized() {
_CVector tv(*this); _CVector tv(*this);
tv.normalize(); tv.normalize();
return tv; return tv;
} }
//! \~english Check if vector is null (all elements zero)
//! \~russian Проверить, является ли вектор нулевым (все элементы нули)
//! \returns true if vector is null
bool isNull() const { bool isNull() const {
PIMV_FOR if (c[i] != Type(0)) return false; PIMV_FOR if (c[i] != Type(0)) return false;
return true; return true;
} }
//! \~english Check if vector is valid (non-empty)
//! \~russian Проверить, валиден ли вектор (не пустой)
//! \returns true if vector is valid
bool isValid() const { return !c.isEmpty(); } bool isValid() const { return !c.isEmpty(); }
//! \~english Check if vectors are orthogonal
//! \~russian Проверить, перпендикулярны ли векторы
//! \param v The other vector
//! \returns true if vectors are orthogonal
bool isOrtho(const _CVector & v) const { return dot(v) == Type(0); } bool isOrtho(const _CVector & v) const { return dot(v) == Type(0); }
//! \~english Get element at index (non-const)
//! \~russian Получить элемент по индексу (non-const)
//! \param index Element index
//! \returns Reference to element
Type & operator[](uint index) { return c[index]; } Type & operator[](uint index) { return c[index]; }
//! \~english Get element at index (const)
//! \~russian Получить элемент по индексу (const)
//! \param index Element index
//! \returns Copy of element
const Type & operator[](uint index) const { return c[index]; } const Type & operator[](uint index) const { return c[index]; }
//! \~english Get element at index (const version)
//! \~russian Получить элемент по индексу (версия const)
//! \param index Element index
//! \returns Copy of element
Type at(uint index) const { return c[index]; } Type at(uint index) const { return c[index]; }
//! \~english Assign value to all elements
//! \~russian Присвоить значение всем элементам
//! \param v The value to assign
//! \returns Reference to this vector
_CVector & operator=(const Type & v) { _CVector & operator=(const Type & v) {
PIMV_FOR c[i] = v; PIMV_FOR c[i] = v;
return *this; return *this;
} }
//! \~english Check equality with another vector
//! \~russian Проверить равенство с другим вектором
//! \param v The vector to compare with
//! \returns true if all elements are equal
bool operator==(const _CVector & v) const { return c == v.c; } bool operator==(const _CVector & v) const { return c == v.c; }
//! \~english Check inequality with another vector
//! \~russian Проверить неравенство с другим вектором
//! \param v The vector to compare with
//! \returns true if any element differs
bool operator!=(const _CVector & v) const { return c != v.c; } bool operator!=(const _CVector & v) const { return c != v.c; }
//! \~english Add vector to this vector
//! \~russian Прибавить вектор к этому вектору
//! \param v The vector to add
void operator+=(const _CVector & v) { void operator+=(const _CVector & v) {
assert(c.size() == v.size()); assert(c.size() == v.size());
PIMV_FOR c[i] += v[i]; PIMV_FOR c[i] += v[i];
} }
//! \~english Subtract vector from this vector
//! \~russian Вычесть вектор из этого вектора
//! \param v The vector to subtract
void operator-=(const _CVector & v) { void operator-=(const _CVector & v) {
assert(c.size() == v.size()); assert(c.size() == v.size());
PIMV_FOR c[i] -= v[i]; PIMV_FOR c[i] -= v[i];
} }
//! \~english Multiply all elements by scalar
//! \~russian Умножить все элементы на скаляр
//! \param v The scalar to multiply by
void operator*=(const Type & v) { PIMV_FOR c[i] *= v; } void operator*=(const Type & v) { PIMV_FOR c[i] *= v; }
//! \~english Divide all elements by scalar
//! \~russian Разделить все элементы на скаляр
//! \param v The scalar to divide by
void operator/=(const Type & v) { void operator/=(const Type & v) {
assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP);
PIMV_FOR c[i] /= v; PIMV_FOR c[i] /= v;
} }
//! \~english Unary minus operator
//! \~russian Унарный оператор минус
//! \returns New vector with negated elements
_CVector operator-() const { _CVector operator-() const {
_CVector tv(c.size()); _CVector tv(c.size());
PIMV_FOR tv[i] = -c[i]; PIMV_FOR tv[i] = -c[i];
return tv; return tv;
} }
//! \~english Add two vectors
//! \~russian Сложить два вектора
//! \param v The vector to add
//! \returns New vector with sum of elements
_CVector operator+(const _CVector & v) const { _CVector operator+(const _CVector & v) const {
assert(c.size() == v.size()); assert(c.size() == v.size());
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] += v[i]; PIMV_FOR tv[i] += v[i];
return tv; return tv;
} }
//! \~english Subtract two vectors
//! \~russian Вычесть два вектора
//! \param v The vector to subtract
//! \returns New vector with difference of elements
_CVector operator-(const _CVector & v) const { _CVector operator-(const _CVector & v) const {
assert(c.size() == v.size()); assert(c.size() == v.size());
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] -= v[i]; PIMV_FOR tv[i] -= v[i];
return tv; return tv;
} }
//! \~english Multiply vector by scalar
//! \~russian Умножить вектор на скаляр
//! \param v The scalar to multiply by
//! \returns New vector with scaled elements
_CVector operator*(const Type & v) const { _CVector operator*(const Type & v) const {
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] *= v; PIMV_FOR tv[i] *= v;
return tv; return tv;
} }
//! \~english Divide vector by scalar
//! \~russian Разделить вектор на скаляр
//! \param v The scalar to divide by
//! \returns New vector with scaled elements
_CVector operator/(const Type & v) const { _CVector operator/(const Type & v) const {
assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP); assert(std::abs(v) > PIMATHVECTOR_ZERO_CMP);
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] /= v; PIMV_FOR tv[i] /= v;
return tv; return tv;
} }
//! \~english Compute cross product with another vector (3D only)
//! \~russian Вычислить векторное произведение с другим вектором (только 3D)
//! \param v The other vector
//! \returns Cross product vector
_CVector cross(const _CVector & v) const { _CVector cross(const _CVector & v) const {
assert(c.size() == 3); assert(c.size() == 3);
assert(v.size() == 3); assert(v.size() == 3);
@@ -534,19 +974,35 @@ public:
tv[2] = c[0] * v[1] - v[0] * c[1]; tv[2] = c[0] * v[1] - v[0] * c[1];
return tv; return tv;
} }
//! \~english Compute dot product with another vector
//! \~russian Вычислить скалярное произведение с другим вектором
//! \param v The other vector
//! \returns Dot product (sum of element-wise products)
Type dot(const _CVector & v) const { Type dot(const _CVector & v) const {
assert(c.size() == v.size()); assert(c.size() == v.size());
Type tv(0); Type tv(0);
PIMV_FOR tv += c[i] * v[i]; PIMV_FOR tv += c[i] * v[i];
return tv; return tv;
} }
//! \~english Element-wise multiplication with another vector
//! \~russian Покомпонентное умножение с другим вектором
//! \param v The other vector
//! \returns New vector with element-wise products
_CVector mul(const _CVector & v) const { _CVector mul(const _CVector & v) const {
assert(c.size() == v.size()); assert(c.size() == v.size());
_CVector tv(*this); _CVector tv(*this);
PIMV_FOR tv[i] *= v[i]; PIMV_FOR tv[i] *= v[i];
return tv; return tv;
} }
//! \~english Element-wise multiplication with scalar
//! \~russian Покомпонентное умножение на скаляр
//! \param v The scalar to multiply by
//! \returns New vector with scaled elements
_CVector mul(const Type & v) const { return (*this) * v; } _CVector mul(const Type & v) const { return (*this) * v; }
//! \~english Element-wise division by another vector
//! \~russian Покомпонентное деление на другой вектор
//! \param v The vector to divide by
//! \returns New vector with element-wise quotients
_CVector div(const _CVector & v) const { _CVector div(const _CVector & v) const {
assert(c.size() == v.size()); assert(c.size() == v.size());
_CVector tv(*this); _CVector tv(*this);
@@ -556,8 +1012,17 @@ public:
} }
return tv; return tv;
} }
//! \~english Element-wise division by scalar
//! \~russian Покомпонентное деление на скаляр
//! \param v The scalar to divide by
//! \returns New vector with scaled elements
_CVector div(const Type & v) const { return (*this) / v; } _CVector div(const Type & v) const { return (*this) / v; }
//! \~english Get distance from this point to line defined by two points
//! \~russian Получить расстояние от этой точки до линии, заданной двумя точками
//! \param lp0 First point on the line
//! \param lp1 Second point on the line
//! \returns Distance from point to line
Type distToLine(const _CVector & lp0, const _CVector & lp1) { Type distToLine(const _CVector & lp0, const _CVector & lp1) {
assert(c.size() == lp0.size()); assert(c.size() == lp0.size());
assert(c.size() == lp1.size()); assert(c.size() == lp1.size());
@@ -568,24 +1033,75 @@ public:
return piAbs<Type>(a[0] * b[1] - a[1] * b[0]) / tv; return piAbs<Type>(a[0] * b[1] - a[1] * b[0]) / tv;
} }
//! \~english Convert to PIVector
//! \~russian Преобразовать в PIVector
//! \returns PIVector with same elements
PIVector<Type> toVector() const { return c; } PIVector<Type> toVector() const { return c; }
//! \~english Apply function to each element (const)
//! \~russian Применить функцию к каждому элементу (const)
//! \param f The function to apply
void forEach(std::function<void(const Type &)> f) const { c.forEach(f); } void forEach(std::function<void(const Type &)> f) const { c.forEach(f); }
//! \~english Apply function to each element
//! \~russian Применить функцию к каждому элементу
//! \param f The function to apply
//! \returns Reference to this vector
_CVector & forEach(std::function<void(Type &)> f) { _CVector & forEach(std::function<void(Type &)> f) {
c.forEach(f); c.forEach(f);
return *this; return *this;
} }
//! \~english Get pointer to underlying data
//! \~russian Получить указатель на внутренние данные
//! \returns Pointer to first element
inline Type * data() { return c.data(); } inline Type * data() { return c.data(); }
//! \~english Get pointer to underlying data (const)
//! \~russian Получить указатель на внутренние данные (const)
//! \returns Pointer to first element
inline const Type * data() const { return c.data(); } inline const Type * data() const { return c.data(); }
//! \~english Static cross product of two vectors
//! \~russian Статическое векторное произведение двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns Cross product vector
static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); } static _CVector cross(const _CVector & v1, const _CVector & v2) { return v1.cross(v2); }
//! \~english Static dot product of two vectors
//! \~russian Статическое скалярное произведение двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns Dot product
static Type dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); } static Type dot(const _CVector & v1, const _CVector & v2) { return v1.dot(v2); }
//! \~english Static element-wise multiplication of two vectors
//! \~russian Статическое покомпонентное умножение двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns New vector with element-wise products
static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); } static _CVector mul(const _CVector & v1, const _CVector & v2) { return v1.mul(v2); }
//! \~english Static scalar multiplication (scalar * vector)
//! \~russian Статическое скалярное умножение (скаляр * вектор)
//! \param v1 Scalar
//! \param v2 Vector
//! \returns Scaled vector
static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; } static _CVector mul(const Type & v1, const _CVector & v2) { return v2 * v1; }
//! \~english Static scalar multiplication (vector * scalar)
//! \~russian Статическое скалярное умножение (вектор * скаляр)
//! \param v1 Vector
//! \param v2 Scalar
//! \returns Scaled vector
static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; } static _CVector mul(const _CVector & v1, const Type & v2) { return v1 * v2; }
//! \~english Static element-wise division of two vectors
//! \~russian Статическое покомпонентное деление двух векторов
//! \param v1 First vector
//! \param v2 Second vector
//! \returns New vector with element-wise quotients
static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); } static _CVector div(const _CVector & v1, const _CVector & v2) { return v1.div(v2); }
//! \~english Static scalar division (vector / scalar)
//! \~russian Статическое скалярное деление (вектор / скаляр)
//! \param v1 Vector
//! \param v2 Scalar
//! \returns Scaled vector
static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; } static _CVector div(const _CVector & v1, const Type & v2) { return v1 / v2; }
private: private:
@@ -600,6 +1116,11 @@ inline PIMathVector<Type> operator*(const Type & x, const PIMathVector<Type> & v
#undef PIMV_FOR #undef PIMV_FOR
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
//! \~english Output vector to stream
//! \~russian Вывести вектор в поток
//! \param s The output stream
//! \param v The vector to output
//! \returns Reference to the stream
template<typename Type> template<typename Type>
inline std::ostream & operator<<(std::ostream & s, const PIMathVector<Type> & v) { inline std::ostream & operator<<(std::ostream & s, const PIMathVector<Type> & v) {
s << "{"; s << "{";
@@ -612,6 +1133,11 @@ inline std::ostream & operator<<(std::ostream & s, const PIMathVector<Type> & v)
} }
#endif #endif
//! \~english Output vector to PIP stream
//! \~russian Вывести вектор в поток PIP
//! \param s The PIP output stream
//! \param v The vector to output
//! \returns Reference to the stream
template<typename Type> template<typename Type>
inline PICout operator<<(PICout s, const PIMathVector<Type> & v) { inline PICout operator<<(PICout s, const PIMathVector<Type> & v) {
s.space(); s.space();
@@ -626,11 +1152,21 @@ inline PICout operator<<(PICout s, const PIMathVector<Type> & v) {
return s; return s;
} }
//! \~english Serialize vector to binary stream
//! \~russian Сериализовать вектор в бинарный поток
//! \param s The binary stream
//! \param v The vector to serialize
//! \returns Reference to the stream
template<typename P, typename T> template<typename P, typename T>
inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMathVector<T> & v) { inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMathVector<T> & v) {
s << v.c; s << v.c;
return s; return s;
} }
//! \~english Deserialize vector from binary stream
//! \~russian Десериализовать вектор из бинарного потока
//! \param s The binary stream
//! \param v The vector to deserialize
//! \returns Reference to the stream
template<typename P, typename T> template<typename P, typename T>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathVector<T> & v) { inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathVector<T> & v) {
s >> v.c; s >> v.c;
@@ -638,7 +1174,11 @@ inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMathVector<T> & v
} }
//! \~english 32-bit integer dynamic vector
//! \~russian Динамический вектор с 32-битными целыми числами
typedef PIMathVector<int> PIMathVectori; typedef PIMathVector<int> PIMathVectori;
//! \~english Double precision dynamic vector
//! \~russian Динамический вектор с числами двойной точности
typedef PIMathVector<double> PIMathVectord; typedef PIMathVector<double> PIMathVectord;
#endif // PIMATHVECTOR_H #endif // PIMATHVECTOR_H

View File

@@ -40,12 +40,15 @@ public:
Type x; Type x;
Type y; Type y;
//! \~english Creates a new point.
//! \~russian Создает новую точку. //! \~russian Создает новую точку.
PIPoint() { x = y = Type(); } PIPoint() { x = y = Type(); }
//! \~english Creates a new point with given coordinates.
//! \~russian Создает новую точку с заданными координатами. //! \~russian Создает новую точку с заданными координатами.
PIPoint(Type x_, Type y_) { set(x_, y_); } PIPoint(Type x_, Type y_) { set(x_, y_); }
//! \~english Set new coordinates for the point.
//! \~russian Задать новые координаты точке. //! \~russian Задать новые координаты точке.
PIPoint<Type> & set(Type x_, Type y_) { PIPoint<Type> & set(Type x_, Type y_) {
x = x_; x = x_;
@@ -53,6 +56,7 @@ public:
return *this; return *this;
} }
//! \~english Set new coordinates from another point.
//! \~russian Задать новые координаты точке. //! \~russian Задать новые координаты точке.
PIPoint<Type> & set(const PIPoint<Type> & p) { PIPoint<Type> & set(const PIPoint<Type> & p) {
x = p.x; x = p.x;
@@ -60,6 +64,7 @@ public:
return *this; return *this;
} }
//! \~english Translate the point by x and y.
//! \~russian Переместить точку. //! \~russian Переместить точку.
PIPoint<Type> & translate(Type x_, Type y_) { PIPoint<Type> & translate(Type x_, Type y_) {
x += x_; x += x_;
@@ -67,6 +72,7 @@ public:
return *this; return *this;
} }
//! \~english Translate the point by another point.
//! \~russian Переместить точку. //! \~russian Переместить точку.
PIPoint<Type> & translate(const PIPoint<Type> & p) { PIPoint<Type> & translate(const PIPoint<Type> & p) {
x += p.x; x += p.x;
@@ -74,6 +80,7 @@ public:
return *this; return *this;
} }
//! \~english Create a copy of the point and translate it.
//! \~russian Создать копию точки и переместить её. //! \~russian Создать копию точки и переместить её.
PIPoint<Type> translated(Type x_, Type y_) const { PIPoint<Type> translated(Type x_, Type y_) const {
PIPoint<Type> rp(*this); PIPoint<Type> rp(*this);
@@ -81,6 +88,7 @@ public:
return rp; return rp;
} }
//! \~english Create a copy of the point and translate it by another point.
//! \~russian Создать копию точки и переместить её. //! \~russian Создать копию точки и переместить её.
PIPoint<Type> translated(const PIPoint<Type> & p) const { PIPoint<Type> translated(const PIPoint<Type> & p) const {
PIPoint<Type> rp(*this); PIPoint<Type> rp(*this);
@@ -88,14 +96,17 @@ public:
return rp; return rp;
} }
//! \~english Translate the point. Alias for \a translate().
//! \~russian Переместить точку. //! \~russian Переместить точку.
//! \details Является копией метода \a translate(). //! \details Является копией метода \a translate().
PIPoint<Type> & move(Type x_, Type y_) { return translate(x_, y_); } PIPoint<Type> & move(Type x_, Type y_) { return translate(x_, y_); }
//! \~english Translate the point by another point. Alias for \a translate().
//! \~russian Переместить точку. //! \~russian Переместить точку.
//! \details Является копией метода \a translate(). //! \details Является копией метода \a translate().
PIPoint<Type> & move(const PIPoint<Type> & p) { return translate(p); } PIPoint<Type> & move(const PIPoint<Type> & p) { return translate(p); }
//! \~english Create a copy of the point and translate it. Alias for \a translated().
//! \~russian Создать копию точки и переместить её. //! \~russian Создать копию точки и переместить её.
//! \details Является копией метода \a translated(). //! \details Является копией метода \a translated().
PIPoint<Type> moved(Type x_, Type y_) const { PIPoint<Type> moved(Type x_, Type y_) const {
@@ -104,6 +115,7 @@ public:
return rp; return rp;
} }
//! \~english Create a copy of the point and translate it by another point. Alias for \a translated().
//! \~russian Создать копию точки и переместить её. //! \~russian Создать копию точки и переместить её.
//! \details Является копией метода \a translated(). //! \details Является копией метода \a translated().
PIPoint<Type> moved(const PIPoint<Type> & p) const { PIPoint<Type> moved(const PIPoint<Type> & p) const {
@@ -112,65 +124,82 @@ public:
return rp; return rp;
} }
//! \~english Calculate angle in radians in polar coordinate system.
//! \~russian Посчитать угол(радианы) в поолярной системе координат. //! \~russian Посчитать угол(радианы) в поолярной системе координат.
double angleRad() const { return atan2(y, x); } double angleRad() const { return atan2(y, x); }
//! \~english Calculate angle in degrees in polar coordinate system.
//! \~russian Посчитать угол(градусы) в поолярной системе координат. //! \~russian Посчитать угол(градусы) в поолярной системе координат.
double angleDeg() const { return toDeg(atan2(y, x)); } double angleDeg() const { return toDeg(atan2(y, x)); }
//! \~english Convert copy of point to polar coordinate system.
//! \~russian Перевести копию точки в полярную систему координат. //! \~russian Перевести копию точки в полярную систему координат.
PIPoint<Type> toPolar(bool isDeg = false) const { return PIPoint<Type>(sqrt(x * x + y * y), isDeg ? angleDeg() : angleRad()); } PIPoint<Type> toPolar(bool isDeg = false) const { return PIPoint<Type>(sqrt(x * x + y * y), isDeg ? angleDeg() : angleRad()); }
//! \~english Convert point from polar to cartesian coordinate system.
//! \~russian Перевести копию точки из полярной системы координат в декартовую. //! \~russian Перевести копию точки из полярной системы координат в декартовую.
static PIPoint<Type> fromPolar(const PIPoint<Type> & p) { return PIPoint<Type>(p.y * cos(p.x), p.y * sin(p.x)); } static PIPoint<Type> fromPolar(const PIPoint<Type> & p) { return PIPoint<Type>(p.y * cos(p.x), p.y * sin(p.x)); }
//! \~russian //! \~english Add second point coordinates and save.
//! Прибавить координаты второй точки и сохранить. //! \~russian Прибавить координаты второй точки и сохранить.
//! \details Является копией метода \a translate(). //! \details Является копией метода \a translate().
PIPoint<Type> & operator+=(const PIPoint<Type> & p) { PIPoint<Type> & operator+=(const PIPoint<Type> & p) {
translate(p); translate(p);
return *this; return *this;
} }
//! \~english Multiply coordinates by value.
PIPoint<Type> & operator*=(Type v) { PIPoint<Type> & operator*=(Type v) {
x *= v; x *= v;
y *= v; y *= v;
return *this; return *this;
} }
//! \~english Divide coordinates by value.
PIPoint<Type> & operator/=(Type v) { PIPoint<Type> & operator/=(Type v) {
x /= v; x /= v;
y /= v; y /= v;
return *this; return *this;
} }
//! \~english Add coordinates of two points.
//! \~russian Сложить координаты двух точек. //! \~russian Сложить координаты двух точек.
PIPoint<Type> operator+(const PIPoint<Type> & p) { return PIPoint<Type>(x + p.x, y + p.y); } PIPoint<Type> operator+(const PIPoint<Type> & p) { return PIPoint<Type>(x + p.x, y + p.y); }
//! \~english Add value to both coordinates.
//! \~russian Прибавить к координатам одинаковое значение. //! \~russian Прибавить к координатам одинаковое значение.
PIPoint<Type> operator+(const Type & p) { return PIPoint<Type>(x + p, y + p); } PIPoint<Type> operator+(const Type & p) { return PIPoint<Type>(x + p, y + p); }
//! \~english Subtract second point coordinates - get offset.
//! \~russian Вычесть из координат координаты второй точки - найти смещение. //! \~russian Вычесть из координат координаты второй точки - найти смещение.
PIPoint<Type> operator-(const PIPoint<Type> & p) { return PIPoint<Type>(x - p.x, y - p.y); } PIPoint<Type> operator-(const PIPoint<Type> & p) { return PIPoint<Type>(x - p.x, y - p.y); }
//! \~english Subtract value from both coordinates.
//! \~russian Вычесть из координат одинаковое значение. //! \~russian Вычесть из координат одинаковое значение.
PIPoint<Type> operator-(const Type & p) { return PIPoint<Type>(x - p, y - p); } PIPoint<Type> operator-(const Type & p) { return PIPoint<Type>(x - p, y - p); }
//! \~english Invert point coordinates.
//! \~russian Инвертировать координаты точки. //! \~russian Инвертировать координаты точки.
PIPoint<Type> operator-() { return PIPoint<Type>(-x, -y); } PIPoint<Type> operator-() { return PIPoint<Type>(-x, -y); }
//! \~english Multiply point coordinates.
//! \~russian Умножить координаты точки. //! \~russian Умножить координаты точки.
PIPoint<Type> operator*(Type v) { return PIPoint<Type>(x * v, y * v); } PIPoint<Type> operator*(Type v) { return PIPoint<Type>(x * v, y * v); }
//! \~english Divide point coordinates.
//! \~russian Делить координаты точки. //! \~russian Делить координаты точки.
PIPoint<Type> operator/(Type v) { return PIPoint<Type>(x / v, y / v); } PIPoint<Type> operator/(Type v) { return PIPoint<Type>(x / v, y / v); }
//! \~english Check equality of two points.
//! \~russian Проверить равенство координат двух точек. //! \~russian Проверить равенство координат двух точек.
bool operator==(const PIPoint<Type> & p) const { return (x == p.x && y == p.y); } bool operator==(const PIPoint<Type> & p) const { return (x == p.x && y == p.y); }
//! \~english Check inequality of two points.
//! \~russian Проверить неравенство координат двух точек. //! \~russian Проверить неравенство координат двух точек.
bool operator!=(const PIPoint<Type> & p) const { return (x != p.x || y != p.y); } bool operator!=(const PIPoint<Type> & p) const { return (x != p.x || y != p.y); }
}; };
//! \~english Stream output operator for PIPoint.
//! \~russian Перегруженный оператор для вывода координат в \a PICout. //! \~russian Перегруженный оператор для вывода координат в \a PICout.
template<typename Type> template<typename Type>
PICout operator<<(PICout & s, const PIPoint<Type> & v) { PICout operator<<(PICout & s, const PIPoint<Type> & v) {

View File

@@ -1,9 +1,13 @@
/*! \file piquaternion.h //! \addtogroup Math
* \ingroup Math //! \{
* \~\brief //! \file piquaternion.h
* \~english Quaternion //! \brief
* \~russian Кватернион //! \~english Quaternion
*/ //! \~russian Кватернион
//! \details
//! \~english Quaternion for 3D rotations and orientations
//! \~russian Кватернион для 3D вращений и ориентаций
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for quaternions Class for quaternions
@@ -28,29 +32,69 @@
#include "pimathmatrix.h" #include "pimathmatrix.h"
//! \~english Quaternion for representing 3D rotations and orientations
//! \~russian Кватернион для представления 3D вращений и ориентаций
class PIP_EXPORT PIQuaternion { class PIP_EXPORT PIQuaternion {
friend PIP_EXPORT PIQuaternion operator*(const PIQuaternion & q0, const PIQuaternion & q1); friend PIP_EXPORT PIQuaternion operator*(const PIQuaternion & q0, const PIQuaternion & q1);
friend PIP_EXPORT PIQuaternion operator*(const double & a, const PIQuaternion & q); friend PIP_EXPORT PIQuaternion operator*(const double & a, const PIQuaternion & q);
public: public:
//! \~english Construct quaternion from rotation axis and angle
//! \~russian Создать кватернион из оси вращения и угла
PIQuaternion(const PIMathVectorT3d & u = PIMathVectorT3d(), double a = 0.); PIQuaternion(const PIMathVectorT3d & u = PIMathVectorT3d(), double a = 0.);
//! \~english Returns conjugate of this quaternion (negated vector part)
//! \~russian Возвращает сопряженный кватернион (с инвертированной векторной частью)
PIQuaternion conjugate() const { return PIQuaternion(-vector(), scalar()); } PIQuaternion conjugate() const { return PIQuaternion(-vector(), scalar()); }
//! \~english Returns new quaternion rotated around axis u by angle a
//! \~russian Возвращает новый кватернион, повернутый вокруг оси u на угол a
PIQuaternion rotated(const PIMathVectorT3d & u, double a) const; PIQuaternion rotated(const PIMathVectorT3d & u, double a) const;
//! \~english Rotate this quaternion around axis u by angle a
//! \~russian Повернуть этот кватернион вокруг оси u на угол a
void rotate(const PIMathVectorT3d & u, double a); void rotate(const PIMathVectorT3d & u, double a);
//! \~english Normalize quaternion to unit length
//! \~russian Нормализовать кватернион к единичной длине
void normalize(); void normalize();
//! Get/Set scalar component
double & scalar() { return q[0]; } double & scalar() { return q[0]; }
//! Get scalar component
double scalar() const { return q[0]; } double scalar() const { return q[0]; }
//! \~english Returns vector part of quaternion
//! \~russian Возвращает векторную часть кватерниона
PIMathVectorT3d vector() const { return PIMathVectorT3d({q[1], q[2], q[3]}); } PIMathVectorT3d vector() const { return PIMathVectorT3d({q[1], q[2], q[3]}); }
//! \~english Returns Euler angles from quaternion
//! \~russian Возвращает углы Эйлера из кватерниона
PIMathVectorT3d eyler() const; PIMathVectorT3d eyler() const;
//! \~english Returns 3x3 rotation matrix from quaternion
//! \~russian Возвращает матрицу вращения 3x3 из кватерниона
PIMathMatrixT33d rotationMatrix() const; PIMathMatrixT33d rotationMatrix() const;
//! \~english Extracts rotation axis from quaternion
//! \~russian Извлекает ось вращения из кватерниона
void axis(PIMathVectorT3d * ret) const; void axis(PIMathVectorT3d * ret) const;
//! \~english Create quaternion from Euler angles (roll, pitch, yaw)
//! \~russian Создать кватернион из углов Эйлера (крен, тангаж, рыскание)
static PIQuaternion fromEyler(double ax, double ay, double az); static PIQuaternion fromEyler(double ax, double ay, double az);
//! \~english Create quaternion from 3x3 rotation matrix
//! \~russian Создать кватернион из матрицы вращения 3x3
static PIQuaternion fromRotationMatrix(const PIMathMatrixT33d & m); static PIQuaternion fromRotationMatrix(const PIMathMatrixT33d & m);
//! \~english Create quaternion from rotation angles
//! \~russian Создать кватернион из углов поворота
static PIQuaternion fromAngles(double ax, double ay, double az); static PIQuaternion fromAngles(double ax, double ay, double az);
//! \~english Create quaternion from rotation angles (alternative method)
//! \~russian Создать кватернион из углов поворота (альтернативный метод)
static PIQuaternion fromAngles2(double ax, double ay, double az); static PIQuaternion fromAngles2(double ax, double ay, double az);
protected: protected:

View File

@@ -1,8 +1,11 @@
//! \file pirect.h //! \file pirect.h
//! \ingroup Math //! \ingroup Math
//! \brief //! \brief
//! \~english Rect class //! \~english Rect class for 2D geometry
//! \~russian Класс прямоугольника //! \~russian Класс прямоугольника для 2D геометрии
//! \details
//! \~english The PIRect class provides a two-dimensional rectangle class for 2D geometry.
//! \~russian Класс PIRect предоставляет двумерный класс прямоугольника для 2D геометрии.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Rect class Rect class
@@ -30,25 +33,26 @@
//! \brief //! \brief
//! \~english Rect class //! \~english Rect class
//! \~russian Класс прямоугольника //! \~russian Класс прямоугольника
//! \~\details //! \details
//! \~russian //! \~english The PIRect class provides a two-dimensional rectangle class for 2D geometry.
//! Этот класс описывает прямоугольник на плоскости в прямоугольной системе координат //! \~russian Класс PIRect предоставляет двумерный класс прямоугольника для 2D геометрии.
template<typename Type> template<typename Type>
class PIP_EXPORT PIRect { class PIP_EXPORT PIRect {
static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic"); static_assert(std::is_arithmetic<Type>::value, "Type must be arithmetic");
public: public:
//! //! \~english Default constructor.
//! \~russian Конструктор по умолчанию.
PIRect() {} PIRect() {}
//! \brief //! \~english Constructor from bottom-left corner coordinates and width/height.
//! \~russian Конструктор прямоугольника из координат левого нижнего угла и размеров ширины и высоты //! \~russian Конструктор прямоугольника из координат левого нижнего угла и размеров ширины и высоты
PIRect(Type left_, Type bottom_, Type width_, Type height_) { PIRect(Type left_, Type bottom_, Type width_, Type height_) {
set(left_, bottom_, width_, height_); set(left_, bottom_, width_, height_);
normalize(); normalize();
} }
//! \brief //! \~english Constructor from bottom-left and top-right points.
//! \~russian Конструктор прямоугольника из координат левого нижнего угла и правого верхнего угла //! \~russian Конструктор прямоугольника из координат левого нижнего угла и правого верхнего угла
PIRect(const PIPoint<Type> & bottom_left, const PIPoint<Type> & top_right) { PIRect(const PIPoint<Type> & bottom_left, const PIPoint<Type> & top_right) {
bl = bottom_left; bl = bottom_left;
@@ -61,128 +65,128 @@ public:
// piMax<Type>(p0.x, p1.x, p2.x), piMax<Type>(p0.y, p1.y, p2.y)); // piMax<Type>(p0.x, p1.x, p2.x), piMax<Type>(p0.y, p1.y, p2.y));
// } // }
//! //! \~english Set rectangle from coordinates and dimensions.
PIRect<Type> & set(Type left_, Type bottom_, Type width_, Type height_) { PIRect<Type> & set(Type left_, Type bottom_, Type width_, Type height_) {
bl = PIPoint<Type>(left_, bottom_); bl = PIPoint<Type>(left_, bottom_);
tr = PIPoint<Type>(left_ + width_, bottom_ + height_); tr = PIPoint<Type>(left_ + width_, bottom_ + height_);
return normalize(); return normalize();
} }
//! //! \~english Set rectangle from two points.
PIRect<Type> & set(const PIPoint<Type> & top_left, const PIPoint<Type> & bottom_right) { PIRect<Type> & set(const PIPoint<Type> & top_left, const PIPoint<Type> & bottom_right) {
bl = top_left; bl = top_left;
tr = bottom_right; tr = bottom_right;
return normalize(); return normalize();
} }
//! \brief //! \~english Check if point with given coordinates is inside the rectangle.
//! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику //! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику
bool pointIn(Type x, Type y) const { return (x <= bl.x && x >= tr.x && y <= bl.y && y >= tr.y); } bool pointIn(Type x, Type y) const { return (x <= bl.x && x >= tr.x && y <= bl.y && y >= tr.y); }
//! \brief //! \~english Check if point is inside the rectangle.
//! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику //! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику
bool pointIn(const PIPoint<Type> & p) const { return pointIn(p.x, p.y); } bool pointIn(const PIPoint<Type> & p) const { return pointIn(p.x, p.y); }
//! //! \~english Check if rectangle is empty.
bool isEmpty() const { return (width() == 0 && height() == 0); } bool isEmpty() const { return (width() == 0 && height() == 0); }
//! //! \~english Translate rectangle by x and y.
PIRect<Type> & translate(Type x, Type y) { PIRect<Type> & translate(Type x, Type y) {
bl.translate(x, y); bl.translate(x, y);
tr.translate(x, y); tr.translate(x, y);
return *this; return *this;
} }
//! //! \~english Translate rectangle by point.
PIRect<Type> & translate(const PIPoint<Type> & p) { PIRect<Type> & translate(const PIPoint<Type> & p) {
bl.translate(p); bl.translate(p);
tr.translate(p); tr.translate(p);
return *this; return *this;
} }
//! //! \~english Create a copy of rectangle and translate it by x and y.
PIRect<Type> translated(Type x, Type y) const { PIRect<Type> translated(Type x, Type y) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.translate(x, y); r.translate(x, y);
return r; return r;
} }
//! //! \~english Create a copy of rectangle and translate it by point.
PIRect<Type> translated(const PIPoint<Type> & p) const { PIRect<Type> translated(const PIPoint<Type> & p) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.translate(p); r.translate(p);
return r; return r;
} }
//! //! \~english Translate rectangle by x and y. Alias for \a translate().
PIRect<Type> & move(Type x, Type y) { return translate(x, y); } PIRect<Type> & move(Type x, Type y) { return translate(x, y); }
//! //! \~english Translate rectangle by point. Alias for \a translate().
PIRect<Type> & move(const PIPoint<Type> & p) { return translate(p); } PIRect<Type> & move(const PIPoint<Type> & p) { return translate(p); }
//! //! \~english Create a copy of rectangle and translate it by x and y. Alias for \a translated().
PIRect<Type> moved(Type x, Type y) const { PIRect<Type> moved(Type x, Type y) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.translate(x, y); r.translate(x, y);
return r; return r;
} }
//! //! \~english Create a copy of rectangle and translate it by point. Alias for \a translated().
PIRect<Type> moved(const PIPoint<Type> & p) const { PIRect<Type> moved(const PIPoint<Type> & p) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.translate(p); r.translate(p);
return r; return r;
} }
//! //! \~english Scale rectangle by x and y factors.
PIRect<Type> & scale(Type x, Type y) { PIRect<Type> & scale(Type x, Type y) {
setWidth(width() * x); setWidth(width() * x);
setHeight(height() * y); setHeight(height() * y);
return normalize(); return normalize();
} }
//! //! \~english Scale rectangle uniformly.
PIRect<Type> & scale(Type s) { return scale(s, s); } PIRect<Type> & scale(Type s) { return scale(s, s); }
//! //! \~english Scale rectangle by point factors.
PIRect<Type> & scale(const PIPoint<Type> & p) { return scale(p.x, p.y); } PIRect<Type> & scale(const PIPoint<Type> & p) { return scale(p.x, p.y); }
//! //! \~english Create a copy of rectangle and scale it by x and y factors.
PIRect<Type> scaled(Type x, Type y) const { PIRect<Type> scaled(Type x, Type y) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.scale(x, y); r.scale(x, y);
return r; return r;
} }
//! //! \~english Create a copy of rectangle and scale it uniformly.
PIRect<Type> scaled(Type s) const { PIRect<Type> scaled(Type s) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.scale(s); r.scale(s);
return r; return r;
} }
//! //! \~english Create a copy of rectangle and scale it by point factors.
PIRect<Type> scaled(const PIPoint<Type> & p) const { PIRect<Type> scaled(const PIPoint<Type> & p) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.scale(p); r.scale(p);
return r; return r;
} }
//! //! \~english Normalize rectangle so that left <= right and bottom <= top.
PIRect<Type> & normalize() { PIRect<Type> & normalize() {
if (bl.x > tr.x) piSwap<Type>(bl.x, tr.x); if (bl.x > tr.x) piSwap<Type>(bl.x, tr.x);
if (bl.y > tr.y) piSwap<Type>(bl.y, tr.y); if (bl.y > tr.y) piSwap<Type>(bl.y, tr.y);
return *this; return *this;
} }
//! //! \~english Create normalized copy of rectangle.
PIRect<Type> normalized() const { PIRect<Type> normalized() const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.normalize(); r.normalize();
return r; return r;
} }
//! //! \~english Unite rectangle with another rectangle.
PIRect<Type> & unite(const PIRect<Type> & r) { PIRect<Type> & unite(const PIRect<Type> & r) {
bl.x = piMax<Type>(bl.x, r.left()); bl.x = piMax<Type>(bl.x, r.left());
bl.y = piMax<Type>(bl.y, r.bottom()); bl.y = piMax<Type>(bl.y, r.bottom());
@@ -191,14 +195,14 @@ public:
return normalize(); return normalize();
} }
//! //! \~english Create united copy of rectangle with another rectangle.
PIRect<Type> united(const PIRect<Type> & rect) const { PIRect<Type> united(const PIRect<Type> & rect) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.unite(rect); r.unite(rect);
return r; return r;
} }
//! //! \~english Intersect rectangle with another rectangle.
PIRect<Type> & intersect(const PIRect<Type> & r) { PIRect<Type> & intersect(const PIRect<Type> & r) {
bl.x = piMax<Type>(bl.x, r.left()); bl.x = piMax<Type>(bl.x, r.left());
bl.y = piMax<Type>(bl.y, r.bottom()); bl.y = piMax<Type>(bl.y, r.bottom());
@@ -208,101 +212,101 @@ public:
return *this; return *this;
} }
//! //! \~english Create intersected copy of rectangle with another rectangle.
PIRect<Type> intersected(const PIRect<Type> & rect) const { PIRect<Type> intersected(const PIRect<Type> & rect) const {
PIRect<Type> r(*this); PIRect<Type> r(*this);
r.intersect(rect); r.intersect(rect);
return r; return r;
} }
//! //! \~english Get top coordinate.
Type top() const { return tr.y; } Type top() const { return tr.y; }
//! //! \~english Get left coordinate.
Type left() const { return bl.x; } Type left() const { return bl.x; }
//! //! \~english Get right coordinate.
Type right() const { return tr.x; } Type right() const { return tr.x; }
//! //! \~english Get bottom coordinate.
Type bottom() const { return bl.y; } Type bottom() const { return bl.y; }
//! //! \~english Get rectangle width.
Type width() const { return tr.x - bl.x; } Type width() const { return tr.x - bl.x; }
//! //! \~english Get rectangle height.
Type height() const { return tr.y - bl.y; } Type height() const { return tr.y - bl.y; }
//! //! \~english Get top-left corner point.
PIPoint<Type> topLeft() const { return PIPoint<Type>(bl.x, tr.y); } PIPoint<Type> topLeft() const { return PIPoint<Type>(bl.x, tr.y); }
//! //! \~english Get top-right corner point.
PIPoint<Type> topRigth() const { return tr; } PIPoint<Type> topRigth() const { return tr; }
//! //! \~english Get bottom-left corner point.
PIPoint<Type> bottomLeft() const { return bl; } PIPoint<Type> bottomLeft() const { return bl; }
//! //! \~english Get bottom-right corner point.
PIPoint<Type> bottomRight() const { return PIPoint<Type>(tr.x, bl.y); } PIPoint<Type> bottomRight() const { return PIPoint<Type>(tr.x, bl.y); }
//! //! \~english Get center point of rectangle.
PIPoint<Type> center() const { return bl.moved(width() / 2, height() / 2); } PIPoint<Type> center() const { return bl.moved(width() / 2, height() / 2); }
//! //! \~english Set top coordinate.
void setTop(Type v) { void setTop(Type v) {
tr.y = v; tr.y = v;
normalize(); normalize();
} }
//! //! \~english Set left coordinate.
void setLeft(Type v) { void setLeft(Type v) {
bl.x = v; bl.x = v;
normalize(); normalize();
} }
//! //! \~english Set right coordinate.
void setRigth(Type v) { void setRigth(Type v) {
tr.x = v; tr.x = v;
normalize(); normalize();
} }
//! //! \~english Set bottom coordinate.
void setBottom(Type v) { void setBottom(Type v) {
bl.y = v; bl.y = v;
normalize(); normalize();
} }
//! //! \~english Set rectangle width.
void setWidth(Type v) { setTop(bl.x + v); } void setWidth(Type v) { setTop(bl.x + v); }
//! //! \~english Set rectangle height.
void setHeight(Type v) { setRigth(bl.y + v); } void setHeight(Type v) { setRigth(bl.y + v); }
//! //! \~english Set top-left corner point.
void setTopLeft(const PIPoint<Type> & p) { void setTopLeft(const PIPoint<Type> & p) {
setLeft(p.x); setLeft(p.x);
setTop(p.y); setTop(p.y);
} }
//! //! \~english Set bottom-right corner point.
void setBottomRight(const PIPoint<Type> & p) { void setBottomRight(const PIPoint<Type> & p) {
setRigth(p.x); setRigth(p.x);
setBottom(p.y); setBottom(p.y);
} }
//! //! \~english Set bottom-left corner point.
void setBottomLeft(const PIPoint<Type> & p) { void setBottomLeft(const PIPoint<Type> & p) {
bl = p; bl = p;
normalize(); normalize();
} }
//! //! \~english Set top-right corner point.
void setTopRigth(const PIPoint<Type> & p) { void setTopRigth(const PIPoint<Type> & p) {
tr = p; tr = p;
normalize(); normalize();
} }
//! //! \~english Set center point.
void setCenter(const PIPoint<Type> & p) { void setCenter(const PIPoint<Type> & p) {
Type w = width(); Type w = width();
Type h = height(); Type h = height();
@@ -310,46 +314,46 @@ public:
tr = PIPoint<Type>(bl.x + w, bl.y + h); tr = PIPoint<Type>(bl.x + w, bl.y + h);
} }
//! //! \~english Set rectangle size.
void setSize(Type w, Type h) { void setSize(Type w, Type h) {
tr = PIPoint<Type>(bl.x + w, bl.y + h); tr = PIPoint<Type>(bl.x + w, bl.y + h);
normalize(); normalize();
} }
//! //! \~english Translate rectangle by x on both coordinates.
void operator+=(Type x) { translate(x, x); } void operator+=(Type x) { translate(x, x); }
//! //! \~english Translate rectangle by point.
void operator+=(const PIPoint<Type> & p) { translate(p); } void operator+=(const PIPoint<Type> & p) { translate(p); }
//! //! \~english Translate rectangle by negative x on both coordinates.
void operator-=(Type x) { translate(-x, -x); } void operator-=(Type x) { translate(-x, -x); }
//! //! \~english Translate rectangle by negative point.
void operator-=(const PIPoint<Type> & p) { translate(-p); } void operator-=(const PIPoint<Type> & p) { translate(-p); }
//! //! \~english Unite rectangle with another.
void operator|=(const PIRect<Type> & r) { unite(r); } void operator|=(const PIRect<Type> & r) { unite(r); }
//! //! \~english Intersect rectangle with another.
void operator&=(const PIRect<Type> & r) { intersect(r); } void operator&=(const PIRect<Type> & r) { intersect(r); }
//! //! \~english Translate rectangle by point.
PIRect<Type> operator+(const PIPoint<Type> & p) { return translated(p); } PIRect<Type> operator+(const PIPoint<Type> & p) { return translated(p); }
//! //! \~english Translate rectangle by negative point.
PIRect<Type> operator-(const PIPoint<Type> & p) { return translated(-p); } PIRect<Type> operator-(const PIPoint<Type> & p) { return translated(-p); }
//! //! \~english Unite rectangle with another.
PIRect<Type> operator|(const PIRect<Type> & r) { return united(r); } PIRect<Type> operator|(const PIRect<Type> & r) { return united(r); }
//! //! \~english Intersect rectangle with another.
PIRect<Type> operator&(const PIRect<Type> & r) { return intersected(r); } PIRect<Type> operator&(const PIRect<Type> & r) { return intersected(r); }
//! //! \~english Check equality of two rectangles.
bool operator==(const PIRect<Type> & r) const { return (bl == r.bl && tr == r.tr); } bool operator==(const PIRect<Type> & r) const { return (bl == r.bl && tr == r.tr); }
//! //! \~english Check inequality of two rectangles.
bool operator!=(const PIRect<Type> & r) const { return (bl != r.bl || tr != r.tr); } bool operator!=(const PIRect<Type> & r) const { return (bl != r.bl || tr != r.tr); }
private: private:
@@ -357,7 +361,11 @@ private:
PIPoint<Type> tr; PIPoint<Type> tr;
}; };
//! \~english Stream output operator for PIRect.
//! \~russian Перегруженный оператор для вывода прямоугольника в \a PICout.
//! \details
//! \~english The operator outputs rectangle information in format: Rect{bottomLeft:widthxheight}
//! \~russian Оператор выводит информацию о прямоугольнике в формате: Rect{bottomLeft:widthxheight}
template<typename Type> template<typename Type>
PICout operator<<(PICout & s, const PIRect<Type> & v) { PICout operator<<(PICout & s, const PIRect<Type> & v) {
s.space(); s.space();

View File

@@ -1,9 +1,13 @@
/*! \file pistatistic.h //! \addtogroup Math
* \ingroup Math //! \{
* \~\brief //! \file pistatistic.h
* \~english Calculating math statistic of values array //! \brief
* \~russian Вычисление математической статистики у массива чисел //! \~english Calculating math statistic of values array
*/ //! \~russian Вычисление математической статистики у массива чисел
//! \details
//! \~english Template class for calculating statistical measures of a data set
//! \~russian Шаблонный класс для вычисления статистических характеристик набора данных
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for calculacing math statistic in values array Class for calculacing math statistic in values array
@@ -28,13 +32,20 @@
#include "pimathbase.h" #include "pimathbase.h"
//! Statistical calculator template class
//! \~english Template class for calculating statistical measures (mean, variance, skewness, kurtosis)
//! \~russian Шаблонный класс для вычисления статистических показателей (среднее, дисперсия, асимметрия, эксцесс)
template<typename T> template<typename T>
class PIStatistic { class PIStatistic {
static_assert(std::is_arithmetic<T>::value, "Type must be arithmetic"); static_assert(std::is_arithmetic<T>::value, "Type must be arithmetic");
public: public:
//! Construct empty statistic calculator
PIStatistic() { mean = variance = skewness = kurtosis = T(); } PIStatistic() { mean = variance = skewness = kurtosis = T(); }
//! Calculate arithmetic mean
//! \~english Calculate arithmetic mean of values
//! \~russian Вычислить среднее арифметическое значение
static T calculateMean(const PIVector<T> & val) { static T calculateMean(const PIVector<T> & val) {
T ret = T(); T ret = T();
int n = val.size(); int n = val.size();
@@ -43,11 +54,14 @@ public:
ret += val[i]; ret += val[i];
return ret / n; return ret / n;
} }
//! Calculate all statistics with given mean
//! \~english Calculate variance, skewness and kurtosis using provided mean value
//! \~russian Вычислить дисперсию, асимметрию и эксцесс с использованием заданного среднего значения
bool calculate(const PIVector<T> & val, const T & given_mean) { bool calculate(const PIVector<T> & val, const T & given_mean) {
T v = T(), v1 = T(), v2 = T(), stddev = T(), var = T(); T v = T(), v1 = T(), v2 = T(), stddev = T(), var = T();
int i, n = val.size(); int i, n = val.size();
mean = given_mean;
if (n < 2) return false; if (n < 2) return false;
mean = given_mean;
variance = skewness = kurtosis = T(); variance = skewness = kurtosis = T();
// Variance (using corrected two-pass algorithm) // Variance (using corrected two-pass algorithm)
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
@@ -72,11 +86,18 @@ public:
} }
return true; return true;
} }
//! Calculate all statistics
//! \~english Calculate mean, variance, skewness and kurtosis
//! \~russian Вычислить среднее, дисперсию, асимметрию и эксцесс
bool calculate(const PIVector<T> & val) { return calculate(val, calculateMean(val)); } bool calculate(const PIVector<T> & val) { return calculate(val, calculateMean(val)); }
//! Arithmetic mean
T mean; T mean;
//! Variance
T variance; T variance;
//! Skewness (third standardized moment)
T skewness; T skewness;
//! Kurtosis (fourth standardized moment)
T kurtosis; T kurtosis;
}; };

View File

@@ -21,7 +21,10 @@
You should have received a copy of the GNU Lesser General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//! \~english OpenCL module
//! \~russian Модуль OpenCL
//! \defgroup OpenCL OpenCL //! \defgroup OpenCL OpenCL
//! \~\brief //! \~\brief
//! \~english OpenCL support //! \~english OpenCL support
@@ -61,19 +64,45 @@
#include "pivariant.h" #include "pivariant.h"
//! \~english Main OpenCL wrapper class
//! \~russian Главный класс-обёртка OpenCL
class PIP_OPENCL_EXPORT PIOpenCL { class PIP_OPENCL_EXPORT PIOpenCL {
public: public:
//! \~english Kernel argument structure
//! \~russian Структура аргумента ядра
struct KernelArg; struct KernelArg;
//! \~english Device structure
//! \~russian Структура устройства
struct Device; struct Device;
//! \~english Platform structure
//! \~russian Структура платформы
struct Platform; struct Platform;
//! \~english OpenCL context class
//! \~russian Класс контекста OpenCL
class Context; class Context;
//! \~english OpenCL buffer class
//! \~russian Класс буфера OpenCL
class Buffer; class Buffer;
//! \~english OpenCL program class
//! \~russian Класс программы OpenCL
class Program; class Program;
//! \~english OpenCL kernel class
//! \~russian Класс ядра OpenCL
class Kernel; class Kernel;
//! \~english List of devices
//! \~russian Список устройств
typedef PIVector<Device> DeviceList; typedef PIVector<Device> DeviceList;
//! \~english Address space qualifiers
//! \~russian Квалификаторы адресного пространства
enum AddressQualifier { enum AddressQualifier {
AddressGlobal, AddressGlobal,
AddressLocal, AddressLocal,
@@ -81,6 +110,8 @@ public:
AddressPrivate, AddressPrivate,
}; };
//! \~english Access qualifiers
//! \~russian Квалификаторы доступа
enum AccessQualifier { enum AccessQualifier {
AccessReadOnly, AccessReadOnly,
AccessWriteOnly, AccessWriteOnly,
@@ -88,12 +119,16 @@ public:
AccessNone, AccessNone,
}; };
//! \~english Buffer direction
//! \~russian Направление буфера
enum Direction { enum Direction {
Input = 0x01, Input = 0x01,
Output = 0x02, Output = 0x02,
InputOutput = Input | Output, InputOutput = Input | Output,
}; };
//! \~english Type qualifiers
//! \~russian Квалификаторы типа
enum TypeQualifier { enum TypeQualifier {
TypeConst, TypeConst,
TypeRestrict, TypeRestrict,
@@ -101,6 +136,8 @@ public:
TypeNone, TypeNone,
}; };
//! \~english Argument types
//! \~russian Типы аргументов
enum ArgType { enum ArgType {
Char = 1, Char = 1,
UChar, UChar,
@@ -115,17 +152,51 @@ public:
}; };
//! \~english Kernel argument information
//! \~russian Информация об аргументе ядра
struct PIP_OPENCL_EXPORT KernelArg { struct PIP_OPENCL_EXPORT KernelArg {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
KernelArg(); KernelArg();
//! \~english Address qualifier
//! \~russian Квалификатор адреса
AddressQualifier address_qualifier; AddressQualifier address_qualifier;
//! \~english Access qualifier
//! \~russian Квалификатор доступа
AccessQualifier access_qualifier; AccessQualifier access_qualifier;
//! \~english Buffer direction
//! \~russian Направление буфера
Direction direction; Direction direction;
//! \~english Type qualifier
//! \~russian Квалификатор типа
TypeQualifier type_qualifier; TypeQualifier type_qualifier;
//! \~english Argument name
//! \~russian Имя аргумента
PIString arg_name; PIString arg_name;
//! \~english Type name
//! \~russian Имя типа
PIString type_name; PIString type_name;
//! \~english Base type name
//! \~russian Имя базового типа
PIString base_type_name; PIString base_type_name;
//! \~english Is pointer
//! \~russian Является указателем
bool is_pointer; bool is_pointer;
//! \~english Argument type
//! \~russian Тип аргумента
ArgType arg_type; ArgType arg_type;
//! \~english Dimensions
//! \~russian Размерности
int dims; int dims;
private: private:
@@ -134,68 +205,180 @@ public:
}; };
//! \~english OpenCL device information
//! \~russian Информация об устройстве OpenCL
struct PIP_OPENCL_EXPORT Device { struct PIP_OPENCL_EXPORT Device {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
Device() { Device() {
id = platform_id = 0; id = platform_id = 0;
max_compute_units = max_clock_frequency = 0; max_compute_units = max_clock_frequency = 0;
max_memory_size = 0; max_memory_size = 0;
} }
//! \~english Check if device is valid
//! \~russian Проверить устройство на корректность
bool isValid() const { return id != 0; } bool isValid() const { return id != 0; }
//! \~english Get display text
//! \~russian Получить текст для отображения
PIString displayText() const { return name.trimmed() + " (" + device_version.trimmed() + ")"; } PIString displayText() const { return name.trimmed() + " (" + device_version.trimmed() + ")"; }
//! \~english Device handle
//! \~russian Дескриптор устройства
void * id; void * id;
//! \~english Platform ID
//! \~russian ID платформы
void * platform_id; void * platform_id;
//! \~english Device name
//! \~russian Имя устройства
PIString name; PIString name;
//! \~english Vendor name
//! \~russian Имя производителя
PIString vendor; PIString vendor;
//! \~english Device version
//! \~russian Версия устройства
PIString device_version; PIString device_version;
//! \~english Driver version
//! \~russian Версия драйвера
PIString driver_version; PIString driver_version;
//! \~english Maximum compute units
//! \~russian Максимум вычислительных блоков
int max_compute_units; int max_compute_units;
//! \~english Maximum clock frequency
//! \~russian Максимальная тактовая частота
int max_clock_frequency; int max_clock_frequency;
//! \~english Maximum memory size
//! \~russian Максимальный размер памяти
ullong max_memory_size; ullong max_memory_size;
}; };
//! \~english OpenCL platform information
//! \~russian Информация о платформе OpenCL
struct PIP_OPENCL_EXPORT Platform { struct PIP_OPENCL_EXPORT Platform {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
Platform() { id = 0; } Platform() { id = 0; }
//! \~english Check if platform is valid
//! \~russian Проверить платформу на корректность
bool isValid() const { return id != 0; } bool isValid() const { return id != 0; }
//! \~english Get display text
//! \~russian Получить текст для отображения
PIString displayText() const { return name.trimmed() + " (" + version.trimmed() + ", " + profile.trimmed() + ")"; } PIString displayText() const { return name.trimmed() + " (" + version.trimmed() + ", " + profile.trimmed() + ")"; }
//! \~english Platform handle
//! \~russian Дескриптор платформы
void * id; void * id;
//! \~english Platform name
//! \~russian Имя платформы
PIString name; PIString name;
//! \~english Vendor name
//! \~russian Имя производителя
PIString vendor; PIString vendor;
//! \~english Profile
//! \~russian Профиль
PIString profile; PIString profile;
//! \~english Version
//! \~russian Версия
PIString version; PIString version;
//! \~english Extensions
//! \~russian Расширения
PIStringList extensions; PIStringList extensions;
//! \~english Available devices
//! \~russian Доступные устройства
PIVector<Device> devices; PIVector<Device> devices;
}; };
//! \~english OpenCL context for managing devices and resources
//! \~russian Контекст OpenCL для управления устройствами и ресурсами
class PIP_OPENCL_EXPORT Context { class PIP_OPENCL_EXPORT Context {
friend class Buffer; friend class Buffer;
friend class Program; friend class Program;
friend class Kernel; friend class Kernel;
public: public:
//! \~english Destructor
//! \~russian Деструктор
~Context(); ~Context();
//! \~english Get context handle
//! \~russian Получить дескриптор контекста
void * handle(); void * handle();
//! \~english Get command queue
//! \~russian Получить очередь команд
void * queue(); void * queue();
//! \~english Create context for device list
//! \~russian Создать контекст для списка устройств
//! \param dl List of devices
//! \return New context or nullptr
static Context * create(const DeviceList & dl); static Context * create(const DeviceList & dl);
//! \~english Create context for single device
//! \~russian Создать контекст для одного устройства
//! \param d Device
//! \return New context or nullptr
static Context * create(const Device & d) { return create(DeviceList() << d); } static Context * create(const Device & d) { return create(DeviceList() << d); }
//! \~english Create context by platform name
//! \~russian Создать контекст по имени платформы
//! \param part_name Platform name pattern
//! \return New context or nullptr
static Context * create(const PIString & part_name); static Context * create(const PIString & part_name);
//! \~english Create program from source
//! \~russian Создать программу из исходного кода
//! \param source OpenCL source code
//! \param args Build arguments
//! \param error Error message output
//! \return New program or nullptr
Program * createProgram(const PIString & source, const PIStringList & args = PIStringList(), PIString * error = 0); Program * createProgram(const PIString & source, const PIStringList & args = PIStringList(), PIString * error = 0);
//! \~english Create buffer from vector
//! \~russian Создать буфер из вектора
template<typename T> template<typename T>
Buffer * createBuffer(PIOpenCL::Direction dir, PIVector<T> & container) { Buffer * createBuffer(PIOpenCL::Direction dir, PIVector<T> & container) {
T def = T(); T def = T();
return createBuffer(dir, &container, Buffer::cVector, PIByteArray(&def, sizeof(T)), container.size()); return createBuffer(dir, &container, Buffer::cVector, PIByteArray(&def, sizeof(T)), container.size());
} }
//! \~english Create buffer from deque
//! \~russian Создать буфер из deque
template<typename T> template<typename T>
Buffer * createBuffer(PIOpenCL::Direction dir, PIDeque<T> & container) { Buffer * createBuffer(PIOpenCL::Direction dir, PIDeque<T> & container) {
T def = T(); T def = T();
return createBuffer(dir, &container, Buffer::cDeque, PIByteArray(&def, sizeof(T)), container.size()); return createBuffer(dir, &container, Buffer::cDeque, PIByteArray(&def, sizeof(T)), container.size());
} }
//! \~english Create buffer from 2D vector
//! \~russian Создать буфер из 2D вектора
template<typename T> template<typename T>
Buffer * createBuffer(PIOpenCL::Direction dir, PIVector2D<T> & container) { Buffer * createBuffer(PIOpenCL::Direction dir, PIVector2D<T> & container) {
T def = T(); T def = T();
return createBuffer(dir, &container, Buffer::cVector2D, PIByteArray(&def, sizeof(T)), container.size()); return createBuffer(dir, &container, Buffer::cVector2D, PIByteArray(&def, sizeof(T)), container.size());
} }
//! \~english Create buffer for elements
//! \~russian Создать буфер для элементов
template<typename T> template<typename T>
Buffer * createBuffer(PIOpenCL::Direction dir, uint elements) { Buffer * createBuffer(PIOpenCL::Direction dir, uint elements) {
T def = T(); T def = T();
@@ -216,26 +399,70 @@ public:
}; };
//! \~english OpenCL buffer for data storage
//! \~russian Буфер OpenCL для хранения данных
class PIP_OPENCL_EXPORT Buffer { class PIP_OPENCL_EXPORT Buffer {
friend class Context; friend class Context;
friend class Kernel; friend class Kernel;
public: public:
//! \~english Destructor
//! \~russian Деструктор
~Buffer(); ~Buffer();
//! \~english Get buffer handle
//! \~russian Получить дескриптор буфера
void * handle(); void * handle();
//! \~english Resize buffer
//! \~russian Изменить размер буфера
//! \param new_elements New number of elements
//! \return true if successful
bool resize(uint new_elements); bool resize(uint new_elements);
//! \~english Clear buffer
//! \~russian Очистить буфер
void clear(); void clear();
//! \~english Copy to container
//! \~russian Копировать в контейнер
void copyToContainer(); void copyToContainer();
//! \~english Copy to memory
//! \~russian Копировать в память
void copyTo(void * data); void copyTo(void * data);
//! \~english Copy to memory with offset
//! \~russian Копировать в память со смещением
void copyTo(void * data, int elements_count, int elements_offset = 0); void copyTo(void * data, int elements_count, int elements_offset = 0);
//! \~english Copy to another buffer
//! \~russian Копировать в другой буфер
void copyTo(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0); void copyTo(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0);
//! \~english Copy from container
//! \~russian Копировать из контейнера
void copyFromContainer(); void copyFromContainer();
//! \~english Copy from memory
//! \~russian Копировать из памяти
void copyFrom(void * data); void copyFrom(void * data);
//! \~english Copy from memory with offset
//! \~russian Копировать из памяти со смещением
void copyFrom(void * data, int elements_count, int elements_offset = 0); void copyFrom(void * data, int elements_count, int elements_offset = 0);
//! \~english Copy from another buffer
//! \~russian Копировать из другого буфера
void copyFrom(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0); void copyFrom(Buffer * buffer, int elements_count = -1, int elements_from_offset = 0, int elements_to_offset = 0);
//! \~english Get elements count
//! \~russian Получить количество элементов
uint elementsCount() const { return elements; } uint elementsCount() const { return elements; }
private: private:
//! \~english Container types
//! \~russian Типы контейнеров
enum Container { enum Container {
cNone, cNone,
cVector, cVector,
@@ -257,16 +484,32 @@ public:
}; };
//! \~english OpenCL program containing kernels
//! \~russian Программа OpenCL содержащая ядра
class PIP_OPENCL_EXPORT Program { class PIP_OPENCL_EXPORT Program {
friend class Context; friend class Context;
friend class Kernel; friend class Kernel;
friend class Buffer; friend class Buffer;
public: public:
//! \~english Destructor
//! \~russian Деструктор
~Program(); ~Program();
//! \~english Get context
//! \~russian Получить контекст
Context * context() const { return context_; } Context * context() const { return context_; }
//! \~english Get source code
//! \~russian Получить исходный код
const PIString & sourceCode() const { return source_; } const PIString & sourceCode() const { return source_; }
//! \~english Get kernel by index
//! \~russian Получить ядро по индексу
Kernel * kernel(int index = 0) const { return kernels_[index]; } Kernel * kernel(int index = 0) const { return kernels_[index]; }
//! \~english Get all kernels
//! \~russian Получить все ядра
const PIVector<Kernel *> & kernels() const { return kernels_; } const PIVector<Kernel *> & kernels() const { return kernels_; }
private: private:
@@ -280,28 +523,68 @@ public:
}; };
//! \~english OpenCL kernel for execution
//! \~russian Ядро OpenCL для выполнения
class PIP_OPENCL_EXPORT Kernel { class PIP_OPENCL_EXPORT Kernel {
friend class Program; friend class Program;
friend class Buffer; friend class Buffer;
public: public:
//! \~english Get parent program
//! \~russian Получить родительскую программу
Program * program() const { return program_; } Program * program() const { return program_; }
//! \~english Execute kernel
//! \~russian Выполнить ядро
//! \return true if successful
bool execute(); bool execute();
//! \~english Wait for execution to finish
//! \~russian Ждать завершения выполнения
void waitForFinish(); void waitForFinish();
//! \~english Set execution range (1D)
//! \~russian Установить диапазон выполнения (1D)
//! \param size Number of work items
void setExecuteRange(int size) { setExecuteRanges(PIVector<int>() << size); } void setExecuteRange(int size) { setExecuteRanges(PIVector<int>() << size); }
//! \~english Set execution ranges (ND)
//! \~russian Установить диапазоны выполнения (ND)
//! \param ranges Array of sizes per dimension
void setExecuteRanges(const PIVector<int> & ranges); void setExecuteRanges(const PIVector<int> & ranges);
//! \~english Get kernel name
//! \~russian Получить имя ядра
const PIString & name() const { return name_; } const PIString & name() const { return name_; }
//! \~english Get kernel arguments
//! \~russian Получить аргументы ядра
const PIVector<KernelArg> & args() const { return args_; } const PIVector<KernelArg> & args() const { return args_; }
//! \~english Set argument value by index
//! \~russian Установить значение аргумента по индексу
template<typename T> template<typename T>
bool setArgValue(int index, const T & value) { bool setArgValue(int index, const T & value) {
return setArgValueS(index, PIVariant::fromValue(value)); return setArgValueS(index, PIVariant::fromValue(value));
} }
//! \~english Set argument value by name
//! \~russian Установить значение аргумента по имени
template<typename T> template<typename T>
bool setArgValue(const PIString & arg, const T & value) { bool setArgValue(const PIString & arg, const T & value) {
return setArgValue(argIndex(arg), value); return setArgValue(argIndex(arg), value);
} }
//! \~english Set variant argument value
//! \~russian Установить значение аргумента variant
bool setArgValue(const PIString & arg, const PIVariant & value) { return setArgValueS(argIndex(arg), value); } bool setArgValue(const PIString & arg, const PIVariant & value) { return setArgValueS(argIndex(arg), value); }
//! \~english Bind buffer to argument
//! \~russian Привязать буфер к аргументу
bool bindArgValue(int index, Buffer * buffer); bool bindArgValue(int index, Buffer * buffer);
//! \~english Bind buffer to argument by name
//! \~russian Привязать буфер к аргументу по имени
bool bindArgValue(const PIString & arg, Buffer * buffer) { return bindArgValue(argIndex(arg), buffer); } bool bindArgValue(const PIString & arg, Buffer * buffer) { return bindArgValue(argIndex(arg), buffer); }
private: private:
@@ -321,15 +604,37 @@ public:
}; };
//! \~english Initialize OpenCL
//! \~russian Инициализировать OpenCL
static void init(); static void init();
//! \~english Get available platforms
//! \~russian Получить доступные платформы
//! \return Vector of platforms
static const PIVector<Platform> & platforms(); static const PIVector<Platform> & platforms();
//! \~english Get all available devices
//! \~russian Получить все доступные устройства
//! \return Vector of devices
static const PIVector<Device> devices(); static const PIVector<Device> devices();
//! \~english Get device by ID
//! \~russian Получить устройство по ID
//! \param id Device handle
//! \return Device info
static Device deviceByID(void * id); static Device deviceByID(void * id);
//! \~english Prepare program source
//! \~russian Подготовить исходный код программы
//! \param prog Program source
//! \return Prepared source
static PIString prepareProgram(const PIString & prog); static PIString prepareProgram(const PIString & prog);
private: private:
static PIString prog_header; static PIString prog_header;
PIOpenCL() { ; } PIOpenCL() { ; }
//! \~english Initialization helper
//! \~russian Помощник инициализации
class PIP_OPENCL_EXPORT Initializer { class PIP_OPENCL_EXPORT Initializer {
public: public:
Initializer(); Initializer();
@@ -341,6 +646,8 @@ private:
}; };
//! \~english Output stream operator for KernelArg
//! \~russian Оператор вывода в поток для KernelArg
PIP_OPENCL_EXPORT PICout operator<<(PICout s, const PIOpenCL::KernelArg & v); PIP_OPENCL_EXPORT PICout operator<<(PICout s, const PIOpenCL::KernelArg & v);

View File

@@ -17,6 +17,40 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//! \~english PIP - Platform Independent Primitives
//! \~russian PIP - Кроссплатформенные примитивы
//! \mainpage
//!
//! \~\brief
//! \~english Main include file for PIP library
//! \~russian Главный включаемый файл библиотеки PIP
//!
//! \~\details
//! \~english \section overview Overview
//! \~russian \section overview Обзор
//!
//! \~english
//! PIP is a C++ cross-platform library providing platform-independent abstractions for:
//! * Core/Types: Strings, variants, containers, datetime, networks
//! * Threading: Mutexes, semaphores, thread pools, timers
//! * I/O: Files, serial, CAN, GPIO, SPI, Ethernet
//! * Math: Vectors, matrices, FFT, quaternions
//! * Crypto: MD5, SHA, BLAKE2, SipHash
//! * Compression: zlib support
//! * HTTP: Client and server support
//! * Serialization: JSON, binary, XML
//!
//! \~russian
//! PIP - это кроссплатформенная C++ библиотека, предоставляющая платформонезависимые абстракции для:
//! * Ядро/Типы: Строки, варианты, контейнеры, дата/время, сети
//! * Потоки: Мьютексы, семафоры, пулы потоков, таймеры
//! * Ввод/Вывод: Файлы, последовательные порты, CAN, GPIO, SPI, Ethernet
//! * Математика: Векторы, матрицы, FFT, кватернионы
//! * Криптография: MD5, SHA, BLAKE2, SipHash
//! * Сжатие: Поддержка zlib
//! * HTTP: Клиент и сервер
//! * Сериализация: JSON, бинарная, XML
#ifndef PIP_H #ifndef PIP_H
#define PIP_H #define PIP_H

View File

@@ -22,12 +22,15 @@
You should have received a copy of the GNU Lesser General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//! \~english Resources subsystem
//! \~russian Подсистема ресурсов
//! \defgroup Resources Resources //! \defgroup Resources Resources
//! \~\brief //! \~\brief
//! \~english Resources subsystem //! \~english Resources subsystem
//! \~russian Подсистема ресурсов //! \~russian Подсистема ресурсов
//! //!
//! \~\details //! \~\details
//! \~
//! \~english \section cmake_module_Resources Building with CMake //! \~english \section cmake_module_Resources Building with CMake
//! \~russian \section cmake_module_Resources Сборка с использованием CMake //! \~russian \section cmake_module_Resources Сборка с использованием CMake
//! //!
@@ -59,18 +62,31 @@
#include "pistring.h" #include "pistring.h"
#define INIT_RESOURCE(name) \ //! \~english Macro for initializing compiled-in resources
{ \ //! \~russian Макрос для инициализации вкомпиленных ресурсов
extern void _pirc_##name##_init_(); \ #define INIT_RESOURCE(name) \
_pirc_##name##_init_(); \ { \
} extern void _pirc_##name##_init_(); \
_pirc_##name##_init_(); \
}
//! \~english Class for accessing compiled-in resources
//! \~russian Класс для доступа к вкомпиленным ресурсам
class PIP_EXPORT PIResources { class PIP_EXPORT PIResources {
public: public:
//! //! \~english Get resource by section and name
//! \~russian Получить ресурс по секции и имени
//! \details
//! \~english Searches for resource in specified section
//! \~russian Ищет ресурс в указанной секции
static PIByteArray get(const PIString & section, const PIString & name); static PIByteArray get(const PIString & section, const PIString & name);
//! \~english Get resource by name (searches all sections)
//! \~russian Получить ресурс по имени (ищет во всех секциях)
static PIByteArray get(const PIString & name); static PIByteArray get(const PIString & name);
//! \~english Dump all resources to console
//! \~russian Вывести все ресурсы в консоль
static void dump(); static void dump();
private: private:

View File

@@ -17,6 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//! \~english Resources storage subsystem
//! \~russian Подсистема хранения ресурсов
//! \defgroup Resources Resources
//! \~\brief
//! \~english Resources storage subsystem
//! \~russian Подсистема хранения ресурсов
#ifndef PIRESOURCES_P_H #ifndef PIRESOURCES_P_H
#define PIRESOURCES_P_H #define PIRESOURCES_P_H
@@ -26,20 +33,41 @@
class PIResources; class PIResources;
//! \~english Storage for compiled-in resources
//! \~russian Хранилище вкомпиленных ресурсов
class PIP_EXPORT PIResourcesStorage { class PIP_EXPORT PIResourcesStorage {
friend class PIResources; friend class PIResources;
public: public:
//! \~english Get singleton instance
//! \~russian Получить синглтон
static PIResourcesStorage * instance(); static PIResourcesStorage * instance();
//! \~english Section containing resource entries
//! \~russian Секция, содержащая записи ресурсов
struct PIP_EXPORT Section { struct PIP_EXPORT Section {
//! \~english Constructor
//! \~russian Конструктор
Section(); Section();
//! \~english Destructor
//! \~russian Деструктор
~Section(); ~Section();
//! \~english Add another section to this one
//! \~russian Добавить другую секцию к этой
void add(const Section & s); void add(const Section & s);
//! \~english Clear all entries
//! \~russian Очистить все записи
void purge(); void purge();
//! \~english Map of resource names to data
//! \~russian Карта имен ресурсов к данным
PIMap<PIString, PIByteArray *> entries; PIMap<PIString, PIByteArray *> entries;
}; };
//! \~english Resource entry constructor
//! \~russian Конструктор записи ресурса
struct PIP_EXPORT __RCEntry { struct PIP_EXPORT __RCEntry {
__RCEntry(const PIString & s = PIString(), __RCEntry(const PIString & s = PIString(),
const PIString & n = PIString(), const PIString & n = PIString(),
@@ -56,21 +84,65 @@ public:
size = si; size = si;
flags = fl; flags = fl;
} }
//! \~english Section name
//! \~russian Имя секции
PIString section; PIString section;
//! \~english Resource name
//! \~russian Имя ресурса
PIString name; PIString name;
//! \~english Alias
//! \~russian Псевдоним
PIString alias; PIString alias;
//! \~english Source file
//! \~russian Исходный файл
PIString file; PIString file;
//! \~english Offset in file
//! \~russian Смещение в файле
llong offset; llong offset;
//! \~english Size
//! \~russian Размер
llong size; llong size;
//! \~english Flags
//! \~russian Флаги
int flags; int flags;
}; };
//! \~english Register a section with data
//! \~russian Зарегистрировать секцию с данными
//! \param section_name Name of the section
//! \param data Section data
void registerSection(const PIString & section_name, const Section & data); void registerSection(const PIString & section_name, const Section & data);
//! \~english Register from raw data
//! \~russian Зарегистрировать из сырых данных
//! \param rc_data Resource data
//! \param rc_desc Resource description
//! \param rc_desc_size Description size
void registerSection(const uchar * rc_data, const uchar * rc_desc, int rc_desc_size); void registerSection(const uchar * rc_data, const uchar * rc_desc, int rc_desc_size);
//! \~english Get section by name
//! \~russian Получить секцию по имени
//! \param section_name Name of section
//! \return Pointer to section or nullptr
Section * section(const PIString & section_name) const; Section * section(const PIString & section_name) const;
//! \~english Get resource by section and name
//! \~russian Получить ресурс по секции и имени
PIByteArray get(const PIString & section_name, const PIString & entry_name) const; PIByteArray get(const PIString & section_name, const PIString & entry_name) const;
//! \~english Get resource by name (searches all sections)
//! \~russian Получить ресурс по имени (ищет во всех секциях)
PIByteArray get(const PIString & entry_name) const; PIByteArray get(const PIString & entry_name) const;
//! \~english Clear all sections
//! \~russian Очистить все секции
void clear(); void clear();
private: private:

View File

@@ -34,17 +34,17 @@
#define PIP_BINARY_STREAM #define PIP_BINARY_STREAM
#define BINARY_STREAM_FRIEND(T) \ #define BINARY_STREAM_FRIEND(T) \
template<typename P> \ template<typename P> \
friend PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const T & v); \ friend PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const T & v); \
template<typename P> \ template<typename P> \
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, T & v); friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, T & v);
#define BINARY_STREAM_WRITE(T) \ #define BINARY_STREAM_WRITE(T) \
template<typename P> \ template<typename P> \
inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const T & v) inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const T & v)
#define BINARY_STREAM_READ(T) \ #define BINARY_STREAM_READ(T) \
template<typename P> \ template<typename P> \
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, T & v) inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, T & v)
//! \ingroup Serialization //! \ingroup Serialization

View File

@@ -106,7 +106,12 @@ public:
return true; return true;
} }
//! \~english Set source buffer for read from "data"
//! \~russian Устанавливает исходный буфер для чтения из "data"
void setSource(const PIByteArray & data); void setSource(const PIByteArray & data);
//! \~english Set source buffer for read or write to/from "data", or empty stream for write if "data" = 0
//! \~russian Устанавливает исходный буфер для чтения или записи из/в "data", или пустой поток на запись если "data" = 0
void setSource(PIByteArray * data); void setSource(PIByteArray * data);
//! \~english Returns internal buffer with written data //! \~english Returns internal buffer with written data

View File

@@ -1,8 +1,13 @@
/*! \file pijson.h /*! \file pijsonserialization.h
* \ingroup Serialization * \addtogroup Serialization
* \brief * \brief
* \~english JSON serialization * \~english JSON serialization and deserialization template functions
* \~russian Сериализация JSON * \~russian Шаблонные функции сериализации и десериализации JSON
* \details
* \~english This file provides template functions for serializing and deserializing
* various types to and from PIJSON format.
* \~russian Этот файл предоставляет шаблонные функции для сериализации и десериализации
* различных типов в формат PIJSON и из него.
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -38,14 +43,14 @@
template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0> template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline PIJSON piSerializeJSON(const T & v) { inline PIJSON piSerializeJSON(const T & v) {
return PIJSON() = (int)v; return PIJSON() = (int)v;
} }
template<typename T, template<typename T,
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0, typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
inline PIJSON piSerializeJSON(const T & v) { inline PIJSON piSerializeJSON(const T & v) {
return PIJSON() = v; return PIJSON() = v;
} }
template<typename T, template<typename T,
@@ -53,7 +58,7 @@ template<typename T,
typename std::enable_if<!std::is_arithmetic<T>::value, int>::type = 0> typename std::enable_if<!std::is_arithmetic<T>::value, int>::type = 0>
inline PIJSON piSerializeJSON(const T & v) { inline PIJSON piSerializeJSON(const T & v) {
static_assert(std::is_enum<T>::value || std::is_arithmetic<T>::value, static_assert(std::is_enum<T>::value || std::is_arithmetic<T>::value,
"[piSerializeJSON] Error: using undeclared piSerializeJSON() for complex type!"); "[piSerializeJSON] Error: using undeclared piSerializeJSON() for complex type!");
return {}; return {};
} }
@@ -229,14 +234,14 @@ inline PIJSON piSerializeJSON(const PIMap<K, T> & v) {
template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0> template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline void piDeserializeJSON(T & v, const PIJSON & js) { inline void piDeserializeJSON(T & v, const PIJSON & js) {
v = (T)js.toInt(); v = (T)js.toInt();
} }
template<typename T, template<typename T,
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0, typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
inline void piDeserializeJSON(T & v, const PIJSON & js) { inline void piDeserializeJSON(T & v, const PIJSON & js) {
v = js.value().value<T>(); v = js.value().value<T>();
} }
template<typename T, template<typename T,
@@ -244,7 +249,7 @@ template<typename T,
typename std::enable_if<!std::is_arithmetic<T>::value, int>::type = 0> typename std::enable_if<!std::is_arithmetic<T>::value, int>::type = 0>
inline void piDeserializeJSON(T & v, const PIJSON & js) { inline void piDeserializeJSON(T & v, const PIJSON & js) {
static_assert(std::is_enum<T>::value || std::is_arithmetic<T>::value, static_assert(std::is_enum<T>::value || std::is_arithmetic<T>::value,
"[piDeserializeJSON] Error: using undeclared piDeserializeJSON() for complex type!"); "[piDeserializeJSON] Error: using undeclared piDeserializeJSON() for complex type!");
v = {}; v = {};
} }

View File

@@ -1,8 +1,13 @@
/*! \file pivaluetree_conversions.h /*! \file pivaluetree_conversions.h
* \ingroup Serialization * \addtogroup Serialization
* \brief * \brief
* \~english PIValueTree conversions * \~english PIValueTree conversion functions
* \~russian Преобразования PIValueTree * \~russian Функции преобразования PIValueTree
* \details
* \~english This file provides functions for converting PIValueTree to and from
* various formats (JSON, text, property storage).
* \~russian Этот файл предоставляет функции для преобразования PIValueTree в различные
* форматы (JSON, текст, хранилище свойств) и из них.
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -32,31 +37,65 @@ class PIPropertyStorage;
class PIJSON; class PIJSON;
class PIIODevice; class PIIODevice;
//! \~english PIValueTree conversion namespace.
//! \~russian Пространство имён преобразований PIValueTree.
namespace PIValueTreeConversions { namespace PIValueTreeConversions {
//! \~english Conversion options. \~russian Параметры преобразования.
enum Option { enum Option {
WithAttributes = 0x1, WithAttributes = 0x1, //!< \~english Include attributes \~russian Включить атрибуты
WithComment = 0x2, WithComment = 0x2, //!< \~english Include comments \~russian Включить комментарии
WithType = 0x4, WithType = 0x4, //!< \~english Include type information \~russian Включить информацию о типе
WithAll = 0xFFF, WithAll = 0xFFF, //!< \~english Include everything \~russian Включить всё
IncludeRoot = 0x1000, IncludeRoot = 0x1000, //!< \~english Include root node \~russian Включить корневой узел
Default = WithAll Default = WithAll //!< \~english Default options \~russian Параметры по умолчанию
}; };
//! \~english Options flags type.
//! \~russian Тип флагов параметров.
typedef PIFlags<Option> Options; typedef PIFlags<Option> Options;
//! \~english Convert PIPropertyStorage to PIValueTree.
//! \~russian Преобразование PIPropertyStorage в PIValueTree.
PIP_EXPORT PIValueTree fromPropertyStorage(const PIPropertyStorage & ps); PIP_EXPORT PIValueTree fromPropertyStorage(const PIPropertyStorage & ps);
//! \~english Convert PIVariantMap to PIValueTree.
//! \~russian Преобразование PIVariantMap в PIValueTree.
PIP_EXPORT PIValueTree fromVariantMap(const PIVariantMap & vm); PIP_EXPORT PIValueTree fromVariantMap(const PIVariantMap & vm);
//! \~english Convert PIJSON to PIValueTree.
//! \~russian Преобразование PIJSON в PIValueTree.
PIP_EXPORT PIValueTree fromJSON(const PIJSON & json); PIP_EXPORT PIValueTree fromJSON(const PIJSON & json);
//! \~english Read PIValueTree from IODevice as text.
//! \~russian Чтение PIValueTree из IODevice как текст.
PIP_EXPORT PIValueTree fromText(PIIODevice * device); PIP_EXPORT PIValueTree fromText(PIIODevice * device);
//! \~english Parse PIValueTree from text string.
//! \~russian Разбор PIValueTree из текстовой строки.
PIP_EXPORT PIValueTree fromText(const PIString & str); PIP_EXPORT PIValueTree fromText(const PIString & str);
//! \~english Load PIValueTree from JSON file.
//! \~russian Загрузка PIValueTree из JSON файла.
PIP_EXPORT PIValueTree fromJSONFile(const PIString & path); PIP_EXPORT PIValueTree fromJSONFile(const PIString & path);
//! \~english Load PIValueTree from text file.
//! \~russian Загрузка PIValueTree из текстового файла.
PIP_EXPORT PIValueTree fromTextFile(const PIString & path); PIP_EXPORT PIValueTree fromTextFile(const PIString & path);
//! \~english Convert PIValueTree to JSON.
//! \~russian Преобразование PIValueTree в JSON.
PIP_EXPORT PIJSON toJSON(const PIValueTree & root, Options options = Default); PIP_EXPORT PIJSON toJSON(const PIValueTree & root, Options options = Default);
//! \~english Convert PIValueTree to text.
//! \~russian Преобразование PIValueTree в текст.
PIP_EXPORT PIString toText(const PIValueTree & root, Options options = Default); PIP_EXPORT PIString toText(const PIValueTree & root, Options options = Default);
//! \~english Save PIValueTree to JSON file.
//! \~russian Сохранение PIValueTree в JSON файл.
PIP_EXPORT bool toJSONFile(const PIString & path, const PIValueTree & root, Options options = Default); PIP_EXPORT bool toJSONFile(const PIString & path, const PIValueTree & root, Options options = Default);
//! \~english Save PIValueTree to text file.
//! \~russian Сохранение PIValueTree в текстовый файл.
PIP_EXPORT bool toTextFile(const PIString & path, const PIValueTree & root, Options options = Default); PIP_EXPORT bool toTextFile(const PIString & path, const PIValueTree & root, Options options = Default);
} // namespace PIValueTreeConversions } // namespace PIValueTreeConversions

View File

@@ -1,12 +1,16 @@
/*! \file pistatemachine.h //! \addtogroup StateMachine
* \ingroup StateMachine //! \{
* \~\brief //! \file pistatemachine.h
* \~english State machine. //! \brief
* \~russian Машина состояний. //! \~english State machine.
*/ //! \~russian Машина состояний.
//! \details
//! \~english Main state machine class that manages states and transitions
//! \~russian Основной класс машины состояний, управляющий состояниями и переходами
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
State machine State machine
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -31,17 +35,36 @@
//! \ingroup StateMachine //! \ingroup StateMachine
//! \~\brief //! \~english Main state machine class
//! \~english //! \~russian Основной класс машины состояний
//! \~russian
class PIP_EXPORT PIStateMachine: public PIStateBase { class PIP_EXPORT PIStateMachine: public PIStateBase {
public: public:
//! \~english Creates state machine with optional name
//! \~russian Создает машину состояний с опциональным именем
//! \param n Machine name
PIStateMachine(const PIString & n = {}); PIStateMachine(const PIString & n = {});
//! \~english Starts state machine execution
//! \~russian Запускает выполнение машины состояний
//! \return true if started successfully
bool start(); bool start();
//! \~english Checks if state machine is running
//! \~russian Проверяет, запущена ли машина состояний
//! \return true if running
bool isRunning() const { return is_running; } bool isRunning() const { return is_running; }
//! \~english Sets finish callback
//! \~russian Устанавливает коллбэк завершения
//! \param f Callback function to call when machine finishes
void setOnFinish(std::function<void()> f) { on_finish = f; } void setOnFinish(std::function<void()> f) { on_finish = f; }
//! \~english Posts event to state machine
//! \~russian Отправляет событие в машину состояний
//! \tparam Args Event arguments types
//! \param event_id Event identifier
//! \param args Event arguments
//! \return true if transition was triggered
template<typename... Args> template<typename... Args>
bool postEvent(int event_id, Args... args) { bool postEvent(int event_id, Args... args) {
if (!is_running) return false; if (!is_running) return false;

View File

@@ -1,12 +1,16 @@
/*! \file pistatemachine_base.h //! \addtogroup StateMachine
* \ingroup StateMachine //! \{
* \~\brief //! \file pistatemachine_base.h
* \~english Some template helpers for PIStateMachine //! \brief
* \~russian Несколько шаблонов для PIStateMachine //! \~english Some template helpers for PIStateMachine
*/ //! \~russian Несколько шаблонов для PIStateMachine
//! \details
//! \~english Contains helper classes and functions for state machine implementation
//! \~russian Содержит вспомогательные классы и функции для реализации машины состояний
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Some template helpers for PIStateMachine Some template helpers for PIStateMachine
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -31,22 +35,45 @@
namespace PIStateMachineHelpers { namespace PIStateMachineHelpers {
//! \~english Helper namespace for state machine implementation
//! \~russian Вспомогательное пространство имён для реализации машины состояний
//! \~english Base class for function wrappers
//! \~russian Базовый класс для обёрток функций
class FunctionBase { class FunctionBase {
public: public:
//! \~english Virtual destructor
//! \~russian Виртуальный деструктор
virtual ~FunctionBase() {} virtual ~FunctionBase() {}
//! \~english Returns format hash for type checking
//! \~russian Возвращает хеш формата для проверки типов
virtual uint formatHash() = 0; virtual uint formatHash() = 0;
}; };
//! \~english Template class for function wrappers
//! \~russian Шаблонный класс для обёрток функций
template<typename... Args> template<typename... Args>
class Function: public FunctionBase { class Function: public FunctionBase {
public: public:
//! \~english Returns format hash for type checking
//! \~russian Возвращает хеш формата для проверки типов
uint formatHash() override { uint formatHash() override {
static uint ret = PIConstChars(typeid(std::function<void(Args...)>).name()).hash(); static uint ret = PIConstChars(typeid(std::function<void(Args...)>).name()).hash();
return ret; return ret;
} }
//! \~english Stored function
//! \~russian Сохранённая функция
std::function<bool(Args...)> func; std::function<bool(Args...)> func;
}; };
//! \~english Creates function wrapper from std::function
//! \~russian Создает обёртку функции из std::function
//! \tparam Ret Return type of the function
//! \tparam Args Argument types of the function
//! \param func Function to wrap
//! \return Pointer to function wrapper
template<typename Ret, typename... Args> template<typename Ret, typename... Args>
FunctionBase * makeFunction(std::function<Ret(Args...)> func) { FunctionBase * makeFunction(std::function<Ret(Args...)> func) {
auto * ret = new Function<Args...>(); auto * ret = new Function<Args...>();

View File

@@ -1,12 +1,16 @@
/*! \file pistatemachine_state.h //! \addtogroup StateMachine
* \ingroup StateMachine //! \{
* \~\brief //! \file pistatemachine_state.h
* \~english State machine node //! \brief
* \~russian Узел машины состояний //! \~english State machine node
*/ //! \~russian Узел машины состояний
//! \details
//! \~english Contains state classes for building state machines
//! \~russian Содержит классы состояний для построения машин состояний
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
State machine node State machine node
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -31,50 +35,117 @@
#include "pisystemtime.h" #include "pisystemtime.h"
//! \ingroup StateMachine //! \~english Base class for state machine states
//! \~\brief //! \~russian Базовый класс для состояний машины состояний
//! \~english
//! \~russian
class PIP_EXPORT PIStateBase { class PIP_EXPORT PIStateBase {
friend class PIStateMachine; friend class PIStateMachine;
friend class PITransitionBase; friend class PITransitionBase;
friend class PIStateFinal; friend class PIStateFinal;
public: public:
//! \~english Creates state with name
//! \~russian Создает состояние с именем
PIStateBase(const PIString & n = {}): name_(n) { ; } PIStateBase(const PIString & n = {}): name_(n) { ; }
virtual ~PIStateBase(); virtual ~PIStateBase();
//! \~english Called when state is \~russian Вы entered
//! зывается при входе в состояние
virtual void onEnter() {} virtual void onEnter() {}
//! \~english Called when state is exited
//! \~russian Вызывается при выходе из состояния
virtual void onExit() {} virtual void onExit() {}
//! \~english Called when state machine finishes (for final states)
//! \~russian Вызывается при завершении машины состояний (для финальных состояний)
virtual void onFinish() {} virtual void onFinish() {}
//! \~english Returns state machine this state belongs to
//! \~russian Возвращает машину состояний, которой принадлежит это состояние
PIStateMachine * machine() const { return root; } PIStateMachine * machine() const { return root; }
//! \~english Returns parent state
//! \~russian Возвращает родительское состояние
PIStateBase * parent() const { return parent_state; } PIStateBase * parent() const { return parent_state; }
//! \~english Returns active child state
//! \~russian Возвращает активное дочернее состояние
PIStateBase * activeChild() const { return active_state; } PIStateBase * activeChild() const { return active_state; }
//! \~english Returns all active child states
//! \~russian Возвращает все активные дочерние состояния
PIVector<PIStateBase *> activeChildren() const; PIVector<PIStateBase *> activeChildren() const;
//! \~english Returns all active atomic states
//! \~russian Возвращает все активные атомарные состояния
PIVector<PIStateBase *> activeAtomics() const; PIVector<PIStateBase *> activeAtomics() const;
//! \~english Adds child state
//! \~russian Добавляет дочернее состояние
void addState(PIStateBase * s); void addState(PIStateBase * s);
//! \~english Adds multiple child states
//! \~russian Добавляет несколько дочерних состояний
void addStates(PIVector<PIStateBase *> s); void addStates(PIVector<PIStateBase *> s);
//! \~english Sets initial state for compound state
//! \~russian Устанавливает начальное состояние для составного состояния
void setInitialState(PIStateBase * s); void setInitialState(PIStateBase * s);
//! \~english Adds transition to target state on event
//! \~russian Добавляет переход к целевому состоянию по событию
PITransitionBase * addTransition(PIStateBase * target, int event_id); PITransitionBase * addTransition(PIStateBase * target, int event_id);
//! \~english Adds timeout transition to target state
//! \~russian Добавляет переход по таймауту к целевому состоянию
PITransitionTimeout * addTimeoutTransition(PIStateBase * target, PISystemTime timeout); PITransitionTimeout * addTimeoutTransition(PIStateBase * target, PISystemTime timeout);
//! \~english Sets parallel mode for state
//! \~russian Устанавливает параллельный режим для состояния
void setParallel(bool yes) { is_parallel = yes; } void setParallel(bool yes) { is_parallel = yes; }
//! \~english Returns state name
//! \~russian Возвращает имя состояния
const PIString & getName() const { return name_; } const PIString & getName() const { return name_; }
//! \~english Checks if this is root state machine
//! \~russian Проверяет является ли это корневой машиной состояний
bool isStateMachine() const { return is_root; } bool isStateMachine() const { return is_root; }
//! \~english Checks if state is active
//! \~russian Проверяет активно ли состояние
bool isActive() const { return is_active; } bool isActive() const { return is_active; }
//! \~english Checks if state is in parallel mode
//! \~russian Проверяет находится ли состояние в параллельном режиме
bool isParallel() const { return is_parallel; } bool isParallel() const { return is_parallel; }
//! \~english Checks if state is final
//! \~russian Проверяет является ли состояние финальным
bool isFinal() const { return is_final; } bool isFinal() const { return is_final; }
//! \~english Checks if state is atomic (no children)
//! \~russian Проверяет является ли состояние атомарным (нет потомков)
bool isAtomic() const { return children.isEmpty(); } bool isAtomic() const { return children.isEmpty(); }
//! \~english Checks if state is compound (has children)
//! \~russian Проверяет является ли состояние составным (есть потомки)
bool isCompound() const { return children.isNotEmpty(); } bool isCompound() const { return children.isNotEmpty(); }
//! \~english Returns child states
//! \~russian Возвращает дочерние состояния
const PIVector<PIStateBase *> & getChildren() const { return children; } const PIVector<PIStateBase *> & getChildren() const { return children; }
//! \~english Returns transitions from this state
//! \~russian Возвращает переходы из этого состояния
const PIVector<PITransitionBase *> & getTransitions() const { return transitions; } const PIVector<PITransitionBase *> & getTransitions() const { return transitions; }
//! \~english Prints state tree to string
//! \~russian Выводит дерево состояний в строку
void print(PIString prefix = {}); void print(PIString prefix = {});
//! \~english Returns all states in machine
//! \~russian Возвращает все состояния в машине
PIVector<PIStateBase *> gatherStates(); PIVector<PIStateBase *> gatherStates();
private: private:
@@ -100,8 +171,12 @@ private:
}; };
//! \~english State with lambda callbacks
//! \~russian Состояние с lambda коллбэками
class PIP_EXPORT PIStateLambda: public PIStateBase { class PIP_EXPORT PIStateLambda: public PIStateBase {
public: public:
//! \~english Creates lambda state with callbacks
//! \~russian Создает lambda состояние с коллбэками
PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString & n = {}): PIStateBase(n) { PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString & n = {}): PIStateBase(n) {
enter = on_enter; enter = on_enter;
exit = on_exit; exit = on_exit;
@@ -118,8 +193,12 @@ private:
}; };
//! \~english Final state of state machine
//! \~russian Финальное состояние машины состояний
class PIP_EXPORT PIStateFinal: public PIStateBase { class PIP_EXPORT PIStateFinal: public PIStateBase {
public: public:
//! \~english Creates final state with finish callback
//! \~russian Создает финальное состояние с коллбэком завершения
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n) { PIStateFinal(std::function<void()> on_finish = nullptr, const PIString & n = {}): PIStateBase(n) {
is_final = true; is_final = true;
enter = on_finish; enter = on_finish;
@@ -133,6 +212,11 @@ private:
}; };
//! \~english Output stream operator for PIStateBase
//! \~russian Оператор вывода потока для PIStateBase
//! \param c Output stream
//! \param s State to output
//! \return Reference to output stream
inline PICout operator<<(PICout c, PIStateBase * s) { inline PICout operator<<(PICout c, PIStateBase * s) {
if (!s) if (!s)
c << "state(nullptr)"; c << "state(nullptr)";

View File

@@ -1,12 +1,16 @@
/*! \file pistatemachine_transition.h //! \addtogroup StateMachine
* \ingroup StateMachine //! \{
* \~\brief //! \file pistatemachine_transition.h
* \~english State machine transition //! \brief
* \~russian Переход машины состояний //! \~english State machine transition
*/ //! \~russian Переход машины состояний
//! \details
//! \~english Contains transition classes for state machine
//! \~russian Содержит классы переходов для машины состояний
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
State machine transition State machine transition
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -30,22 +34,38 @@
#include "pitimer.h" #include "pitimer.h"
//! \ingroup StateMachine //! \~english Base class for state machine transitions
//! \~\brief //! \~russian Базовый класс для переходов машины состояний
//! \~english
//! \~russian
class PIP_EXPORT PITransitionBase { class PIP_EXPORT PITransitionBase {
friend class PIStateMachine; friend class PIStateMachine;
friend class PIStateBase; friend class PIStateBase;
public: public:
//! \~english Creates transition from source to target on event
//! \~russian Создает переход от source к target по событию
//! \param source Source state
//! \param target Target state
//! \param event_id Event identifier that triggers this transition
PITransitionBase(PIStateBase * source, PIStateBase * target, int event_id); PITransitionBase(PIStateBase * source, PIStateBase * target, int event_id);
//! \~english Virtual destructor
//! \~russian Виртуальный деструктор
virtual ~PITransitionBase(); virtual ~PITransitionBase();
//! \~english Returns state machine this transition belongs to
//! \~russian Возвращает машину состояний, которой принадлежит этот переход
PIStateMachine * machine() const { return root; } PIStateMachine * machine() const { return root; }
//! \~english Returns source state
//! \~russian Возвращает исходное состояние
PIStateBase * source() const { return source_state; } PIStateBase * source() const { return source_state; }
//! \~english Returns target state
//! \~russian Возвращает целевое состояние
PIStateBase * target() const { return target_state; } PIStateBase * target() const { return target_state; }
//! \~english Adds guard function to transition
//! \~russian Добавляет сторожевую функцию к переходу
template<typename R, typename... Args> template<typename R, typename... Args>
PITransitionBase * addGuard(std::function<R(Args...)> f) { PITransitionBase * addGuard(std::function<R(Args...)> f) {
static_assert(std::is_same<R, bool>::value, "guard function should return bool!"); static_assert(std::is_same<R, bool>::value, "guard function should return bool!");
@@ -54,11 +74,15 @@ public:
return this; return this;
} }
//! \~english Adds guard function to transition (callable)
//! \~russian Добавляет сторожевую функцию к переходу (callable)
template<typename L> template<typename L>
PITransitionBase * addGuard(L f) { PITransitionBase * addGuard(L f) {
return addGuard(toStdFunction(f)); return addGuard(toStdFunction(f));
} }
//! \~english Tests guard function with arguments
//! \~russian Тестирует сторожевую функцию с аргументами
template<typename... Args> template<typename... Args>
bool testGuard(Args... args) { bool testGuard(Args... args) {
if (!guard) return true; if (!guard) return true;
@@ -69,13 +93,25 @@ public:
return reinterpret_cast<PIStateMachineHelpers::Function<Args...> *>(guard)->func(args...); return reinterpret_cast<PIStateMachineHelpers::Function<Args...> *>(guard)->func(args...);
} }
//! \~english Adds action to transition
//! \~russian Добавляет действие к переходу
PITransitionBase * addAction(std::function<void()> a); PITransitionBase * addAction(std::function<void()> a);
//! \~english Executes transition action
//! \~russian Выполняет действие перехода
void makeAction(); void makeAction();
//! \~english Triggers transition
//! \~russian Запускает переход
void trigger(); void trigger();
protected: protected:
//! \~english Called when transition becomes enabled
//! \~russian Вызывается когда переход становится доступным
virtual void enabled() {} virtual void enabled() {}
//! \~english Called when transition becomes disabled
//! \~russian Вызывается когда переход становится недоступным
virtual void disabled() {} virtual void disabled() {}
int eventID = 0; int eventID = 0;
@@ -86,9 +122,22 @@ protected:
}; };
//! \~english Timeout transition
//! \~russian Переход по таймауту
//! \details
//! \~english Transition that triggers after specified timeout
//! \~russian Переход, который срабатывает после указанного таймаута
class PIP_EXPORT PITransitionTimeout: public PITransitionBase { class PIP_EXPORT PITransitionTimeout: public PITransitionBase {
public: public:
//! \~english Creates timeout transition
//! \~russian Создает переход по таймауту
//! \param source Source state
//! \param target Target state
//! \param timeout Timeout duration
PITransitionTimeout(PIStateBase * source, PIStateBase * target, PISystemTime timeout); PITransitionTimeout(PIStateBase * source, PIStateBase * target, PISystemTime timeout);
//! \~english Destructor
//! \~russian Деструктор
~PITransitionTimeout(); ~PITransitionTimeout();
private: private:
@@ -98,4 +147,6 @@ private:
PITimer timer; PITimer timer;
}; };
//! \}
#endif #endif

View File

@@ -122,6 +122,10 @@ bool PIHIDevice::open(const PIHIDeviceInfo & device) {
return false; return false;
} }
HidD_GetPreparsedData(PRIVATE->deviceHandle, &PRIVATE->preparsed); HidD_GetPreparsedData(PRIVATE->deviceHandle, &PRIVATE->preparsed);
if (!PRIVATE->preparsed) {
close();
return false;
}
return true; return true;
#endif #endif
} }
@@ -338,12 +342,12 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PIDir hid_dir("/sys/bus/hid/devices"_a); PIDir hid_dir("/sys/bus/hid/devices"_a);
auto hid_devs = hid_dir.entries(); auto hid_devs = hid_dir.entries();
for (auto hd: hid_devs) { for (const auto & hd: hid_devs) {
// piCout << d.path; // piCout << d.path;
if (!isDir(hd)) continue; if (!isDir(hd)) continue;
PIDir dir_input(hd.path + "/input"_a); PIDir dir_input(hd.path + "/input"_a);
auto hid_inputs = dir_input.entries(); auto hid_inputs = dir_input.entries();
for (auto hd_i: hid_inputs) { for (const auto & hd_i: hid_inputs) {
if (!isDir(hd_i)) continue; if (!isDir(hd_i)) continue;
// now in /sys/bus/hid/devices/<dev>/input/input<N> // now in /sys/bus/hid/devices/<dev>/input/input<N>
// piCout << hd_i.path; // piCout << hd_i.path;
@@ -360,7 +364,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PIDir dir_e(hd_i.path); PIDir dir_e(hd_i.path);
PIStringList devs; PIStringList devs;
auto dl_e = dir_e.entries(); auto dl_e = dir_e.entries();
for (auto d_e: dl_e) { for (const auto & d_e: dl_e) {
if (!d_e.isDir() || d_e.flags[PIFile::FileInfo::Dot] || d_e.flags[PIFile::FileInfo::DotDot]) continue; if (!d_e.isDir() || d_e.flags[PIFile::FileInfo::Dot] || d_e.flags[PIFile::FileInfo::DotDot]) continue;
devs << d_e.name(); devs << d_e.name();
} }
@@ -388,7 +392,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
if (test_f.isClosed()) continue; if (test_f.isClosed()) continue;
} }
ullong ev = readFile(hd_i.path + "/capabilities/ev"_a).toULLong(16); // ullong ev = readFile(hd_i.path + "/capabilities/ev"_a).toULLong(16);
auto readAxes = [readFile, checkBit, &hd_i, &dev](const PIString & file, bool is_relative) { auto readAxes = [readFile, checkBit, &hd_i, &dev](const PIString & file, bool is_relative) {
PIVector<PIHIDeviceInfo::AxisInfo> ret; PIVector<PIHIDeviceInfo::AxisInfo> ret;
@@ -524,6 +528,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PHIDP_PREPARSED_DATA preparsed = nullptr; PHIDP_PREPARSED_DATA preparsed = nullptr;
if (HidD_GetPreparsedData(deviceHandle, &preparsed) == FALSE) { if (HidD_GetPreparsedData(deviceHandle, &preparsed) == FALSE) {
piCout << "HidD_GetPreparsedData error:" << errorString(); piCout << "HidD_GetPreparsedData error:" << errorString();
CloseHandle(deviceHandle);
continue; continue;
} }
// auto pp = PIByteArray(preparsed, 64); // auto pp = PIByteArray(preparsed, 64);

View File

@@ -29,37 +29,98 @@
#include "pithread.h" #include "pithread.h"
//! \~english HID device information
//! \~russian Информация об HID устройстве
struct PIP_EXPORT PIHIDeviceInfo { struct PIP_EXPORT PIHIDeviceInfo {
friend class PIHIDevice; friend class PIHIDevice;
//! \~english Base class for value info
//! \~russian Базовый класс для информации о значении
struct PIP_EXPORT ValueInfoBase { struct PIP_EXPORT ValueInfoBase {
//! \~english Checks if info is valid
//! \~russian Проверяет валидна ли информация
bool isValid() const { return index >= 0; } bool isValid() const { return index >= 0; }
int index = -1; int index = -1;
int data_index = -1; int data_index = -1;
}; };
//! \~english Axis information
//! \~russian Информация об оси
struct PIP_EXPORT AxisInfo: public ValueInfoBase { struct PIP_EXPORT AxisInfo: public ValueInfoBase {
int bits = 0; int bits = 0;
int min = 0; int min = 0;
int max = 1; int max = 1;
bool is_relative = false; bool is_relative = false;
}; };
//! \~english Button information
//! \~russian Информация о кнопке
struct PIP_EXPORT ButtonInfo: public ValueInfoBase { struct PIP_EXPORT ButtonInfo: public ValueInfoBase {
int code = 0; int code = 0;
}; };
//! \~english Device path
//! \~russian Путь к устройству
PIString path; PIString path;
//! \~english Manufacturer name
//! \~russian Имя производителя
PIString manufacturer; PIString manufacturer;
//! \~english Product name
//! \~russian Название продукта
PIString product; PIString product;
//! \~english Serial number
//! \~russian Серийный номер
PIString serial; PIString serial;
//! \~english Version
//! \~russian Версия
PIString version; PIString version;
//! \~english Vendor ID
//! \~russian Идентификатор производителя
PIString VID; PIString VID;
//! \~english Product ID
//! \~russian Идентификатор продукта
PIString PID; PIString PID;
//! \~english List of axes
//! \~russian Список осей
PIVector<AxisInfo> axes; PIVector<AxisInfo> axes;
//! \~english List of buttons
//! \~russian Список кнопок
PIVector<ButtonInfo> buttons; PIVector<ButtonInfo> buttons;
//! \~english Checks if info is null
//! \~russian Проверяет является ли информация пустой
bool isNull() const { return path.isEmpty(); } bool isNull() const { return path.isEmpty(); }
//! \~english Checks if info is not null
//! \~russian Проверяет является ли информация не пустой
bool isNotNull() const { return !isNull(); } bool isNotNull() const { return !isNull(); }
//! \~english Matches device by string
//! \~russian Сопоставляет устройство по строке
bool match(const PIString & str) const; bool match(const PIString & str) const;
//! \~english Returns axes count
//! \~russian Возвращает количество осей
int axesCount() const { return axes.size_s(); } int axesCount() const { return axes.size_s(); }
//! \~english Returns absolute axes count
//! \~russian Возвращает количество абсолютных осей
int axesAbsoluteCount() const; int axesAbsoluteCount() const;
//! \~english Returns relative axes count
//! \~russian Возвращает количество относительных осей
int axesRelativeCount() const; int axesRelativeCount() const;
//! \~english Returns buttons count
//! \~russian Возвращает количество кнопок
int buttonsCount() const { return buttons.size_s(); } int buttonsCount() const { return buttons.size_s(); }
private: private:
@@ -74,13 +135,19 @@ private:
PIP_EXPORT PICout operator<<(PICout s, const PIHIDeviceInfo & v); PIP_EXPORT PICout operator<<(PICout s, const PIHIDeviceInfo & v);
//! \~english HID device
//! \~russian HID устройство
class PIP_EXPORT PIHIDevice: public PIThread { class PIP_EXPORT PIHIDevice: public PIThread {
PIOBJECT_SUBCLASS(PIHIDevice, PIThread) PIOBJECT_SUBCLASS(PIHIDevice, PIThread)
public: public:
~PIHIDevice(); ~PIHIDevice();
//! \~english HID event
//! \~russian Событие HID
struct PIP_EXPORT Event { struct PIP_EXPORT Event {
//! \~english Event type
//! \~russian Тип события
enum Type { enum Type {
tNone, tNone,
tButton, tButton,
@@ -92,19 +159,48 @@ public:
float value = 0.; float value = 0.;
}; };
//! \~english Checks if device is opened
//! \~russian Проверяет открыто ли устройство
bool isOpened() const; bool isOpened() const;
//! \~english Opens device by info
//! \~russian Открывает устройство по информации
bool open(const PIHIDeviceInfo & device); bool open(const PIHIDeviceInfo & device);
//! \~english Opens device
//! \~russian Открывает устройство
bool open(); bool open();
//! \~english Closes device
//! \~russian Закрывает устройство
void close(); void close();
//! \~english Starts reading device
//! \~russian Начинает чтение устройства
void start(); void start();
//! \~english Stops reading device
//! \~russian Останавливает чтение устройства
void stop(); void stop();
//! \~english Sets dead zone for axes
//! \~russian Устанавливает мёртвую зону для осей
void setDeadZone(float v) { dead_zone = v; } void setDeadZone(float v) { dead_zone = v; }
//! \~english Returns dead zone
//! \~russian Возвращает мёртвую зону
float deadZone() const { return dead_zone; } float deadZone() const { return dead_zone; }
//! \~english Event fired on device event
//! \~russian Событие при событии устройства
EVENT1(event, PIHIDevice::Event, e); EVENT1(event, PIHIDevice::Event, e);
//! \~english Returns all available HID devices
//! \~russian Возвращает все доступные HID устройства
static PIVector<PIHIDeviceInfo> allDevices(bool try_open = true); static PIVector<PIHIDeviceInfo> allDevices(bool try_open = true);
//! \~english Finds device by name
//! \~russian Находит устройство по имени
static PIHIDeviceInfo findDevice(const PIString & name); static PIHIDeviceInfo findDevice(const PIString & name);
private: private:

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