3 Commits

Author SHA1 Message Date
c60a682279 missing include 2026-01-02 20:48:37 +03:00
cf89d77981 pip micro disable piintrospection piwaitevent
PIP_NO_SOCET
2025-10-18 11:20:18 +03:00
4885623492 Add pico sdk define 2025-10-18 08:53:47 +03:00
259 changed files with 7038 additions and 18589 deletions

4
.gitignore vendored
View File

@@ -1,10 +1,8 @@
/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

@@ -97,10 +97,8 @@ public:
{ {
int code = lua_pcall (L, nargs, nresults, msgh); int code = lua_pcall (L, nargs, nresults, msgh);
if (code != LUABRIDGE_LUA_OK) { if (code != LUABRIDGE_LUA_OK)
// Throw (LuaException (L, code)); Throw (LuaException (L, code));
assert(true);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -130,8 +128,7 @@ protected:
private: private:
static int throwAtPanic (lua_State* L) static int throwAtPanic (lua_State* L)
{ {
// throw LuaException (L, -1); throw LuaException (L, -1);
return -1;
} }
}; };

View File

@@ -101,8 +101,7 @@ protected:
{ {
if (m_stackSize == 0) if (m_stackSize == 0)
{ {
std::cerr << ("Unable to continue registration"); throw std::logic_error ("Unable to continue registration");
assert(true);
} }
} }
}; };
@@ -1055,8 +1054,7 @@ public:
{ {
if (m_stackSize == 1) if (m_stackSize == 1)
{ {
std::cerr << ("endNamespace () called on global namespace"); throw std::logic_error ("endNamespace () called on global namespace");
assert(true);
} }
assert (m_stackSize > 1); assert (m_stackSize > 1);
@@ -1152,8 +1150,7 @@ public:
{ {
if (m_stackSize == 1) if (m_stackSize == 1)
{ {
std::cerr << ("addProperty () called on global namespace"); throw std::logic_error ("addProperty () called on global namespace");
assert(true);
} }
assert (lua_istable (L, -1)); // Stack: namespace table (ns) assert (lua_istable (L, -1)); // Stack: namespace table (ns)

View File

@@ -33,7 +33,6 @@
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
#include <iostream>
namespace luabridge { namespace luabridge {
@@ -321,8 +320,7 @@ public:
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
if (!lua_istable (L, -1)) if (!lua_istable (L, -1))
{ {
std::cerr << ("The class is not registered in LuaBridge"); throw std::logic_error ("The class is not registered in LuaBridge");
assert(true);
} }
lua_setmetatable (L, -2); lua_setmetatable (L, -2);
return ud; return ud;
@@ -377,8 +375,7 @@ private:
lua_rawgetp (L, LUA_REGISTRYINDEX, key); lua_rawgetp (L, LUA_REGISTRYINDEX, key);
if (!lua_istable (L, -1)) if (!lua_istable (L, -1))
{ {
std::cerr << ("The class is not registered in LuaBridge"); throw std::logic_error ("The class is not registered in LuaBridge");
assert(true);
} }
lua_setmetatable (L, -2); lua_setmetatable (L, -2);
} }

View File

@@ -5,9 +5,9 @@ if (POLICY CMP0177)
endif() endif()
project(PIP) project(PIP)
set(PIP_MAJOR 5) set(PIP_MAJOR 5)
set(PIP_MINOR 7) set(PIP_MINOR 5)
set(PIP_REVISION 0) set(PIP_REVISION 2)
set(PIP_SUFFIX _alpha) set(PIP_SUFFIX )
set(PIP_COMPANY SHS) set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS) set(PIP_DOMAIN org.SHS)
@@ -67,13 +67,11 @@ set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE STRING "")
option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT}) option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT})
option(STD_IOSTREAM "Building with std iostream operators support" OFF) option(STD_IOSTREAM "Building with std iostream operators support" OFF)
option(INTROSPECTION "Build with introspection" OFF) option(INTROSPECTION "Build with introspection" OFF)
option(TESTS "Build tests" OFF) option(TESTS "Build tests and perform their before install step" OFF)
option(TESTS_RUN "Run tests before install step" OFF)
option(COVERAGE "Build project with coverage info" OFF) 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)
option(PIP_MANUAL_TEST "Build dev test (main.cpp)" 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)
@@ -223,11 +221,18 @@ if (TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()
if(PIP_FREERTOS) if(PIP_MICRO)
add_definitions(-DPIP_FREERTOS) add_definitions(-DMICRO_PIP)
set(ICU OFF) set(ICU OFF)
set(LOCAL ON) set(LOCAL ON)
endif() endif()
if(PIP_FREERTOS)
add_definitions(-DPIP_FREERTOS)
endif()
if(DEFINED PICO_BOARD)
add_definitions(-DPICO_SDK)
message(STATUS "Building PIP for Pi Pico SDK ${PICO_SDK_VERSION_STRING}")
endif()
# Check Bessel functions # Check Bessel functions
set(CMAKE_REQUIRED_INCLUDES math.h) set(CMAKE_REQUIRED_INCLUDES math.h)
@@ -331,7 +336,7 @@ if ((NOT DEFINED SHSTKPROJECT) AND (DEFINED ANDROID_PLATFORM))
#message("${ANDROID_NDK}/sysroot/usr/include") #message("${ANDROID_NDK}/sysroot/usr/include")
endif() endif()
if(NOT PIP_FREERTOS) if(NOT PIP_MICRO)
if(WIN32) if(WIN32)
if(${C_COMPILER} STREQUAL "cl.exe") if(${C_COMPILER} STREQUAL "cl.exe")
else() else()
@@ -352,7 +357,7 @@ if(NOT PIP_FREERTOS)
endif() endif()
endif() endif()
set(PIP_LIBS) set(PIP_LIBS)
if(PIP_FREERTOS) if(PIP_MICRO)
set(PIP_LIBS ${LIBS_MAIN}) set(PIP_LIBS ${LIBS_MAIN})
else() else()
foreach(LIB_ ${LIBS_MAIN}) foreach(LIB_ ${LIBS_MAIN})
@@ -362,18 +367,15 @@ endif()
if(WIN32) if(WIN32)
add_definitions(-DPSAPI_VERSION=1) add_definitions(-DPSAPI_VERSION=1)
if(${C_COMPILER} STREQUAL "cl.exe") if(${C_COMPILER} STREQUAL "cl.exe")
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0 /EH-") set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0")
endif() endif()
else() else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
if (NOT DEFINED ANDROID_PLATFORM)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
endif()
if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
endif()
endif() endif()
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}")
if(DEFINED ENV{QNX_HOST} OR PIP_MICRO)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
endif()
set(PCRE2_BUILD_PCRE2_8 OFF) set(PCRE2_BUILD_PCRE2_8 OFF)
set(PCRE2_BUILD_PCRE2_16 ON ) set(PCRE2_BUILD_PCRE2_16 ON )
@@ -411,7 +413,7 @@ endif()
if (NOT CROSSTOOLS) if (NOT CROSSTOOLS)
if (NOT PIP_FREERTOS) if (NOT PIP_MICRO)
if (PIP_BUILD_CONSOLE) if (PIP_BUILD_CONSOLE)
pip_module(console "" "PIP console support" "" "" "") pip_module(console "" "PIP console support" "" "" "")
@@ -597,7 +599,6 @@ if (NOT CROSSTOOLS)
#target_link_libraries(pip_plugin pip) #target_link_libraries(pip_plugin pip)
if (NOT DEFINED ANDROID_PLATFORM) if (NOT DEFINED ANDROID_PLATFORM)
if (PIP_MANUAL_TEST)
if(microhttpd_FOUND AND curl_FOUND) if(microhttpd_FOUND AND curl_FOUND)
add_executable(pip_test "main.cpp") add_executable(pip_test "main.cpp")
target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server pip_http_client) target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server pip_http_client)
@@ -608,7 +609,6 @@ if (NOT CROSSTOOLS)
endif() endif()
endif() endif()
endif() endif()
endif()
else() else()
@@ -631,7 +631,7 @@ string(REPLACE ";" "," PIP_EXPORTS_STR "${PIP_EXPORTS}")
target_compile_definitions(pip PRIVATE "PICODE_DEFINES=\"${PIP_EXPORTS_STR}\"") target_compile_definitions(pip PRIVATE "PICODE_DEFINES=\"${PIP_EXPORTS_STR}\"")
if(NOT PIP_FREERTOS) if(NOT PIP_MICRO)
# Auxiliary # Auxiliary
if (NOT CROSSTOOLS) if (NOT CROSSTOOLS)
@@ -708,7 +708,7 @@ if(NOT LOCAL)
install(TARGETS ${PIP_MODULES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install(TARGETS ${PIP_MODULES} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif() endif()
else() else()
if(NOT PIP_FREERTOS) if(NOT PIP_MICRO)
if(WIN32) if(WIN32)
install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION bin) install(TARGETS ${PIP_MODULES} RUNTIME DESTINATION bin)
install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION lib) install(TARGETS ${PIP_MODULES} ARCHIVE DESTINATION lib)
@@ -736,7 +736,7 @@ endif()
# #
# Build Documentation # Build Documentation
# #
if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS)) if ((NOT PIP_MICRO) AND (NOT CROSSTOOLS))
include(PIPDocumentation) include(PIPDocumentation)
find_package(Doxygen) find_package(Doxygen)
if(DOXYGEN_FOUND) if(DOXYGEN_FOUND)
@@ -805,7 +805,7 @@ message(" Type : ${CMAKE_BUILD_TYPE}")
if (NOT LOCAL) if (NOT LOCAL)
message(" Install: \"${CMAKE_INSTALL_PREFIX}\"") message(" Install: \"${CMAKE_INSTALL_PREFIX}\"")
else() else()
if(NOT PIP_FREERTOS) if(NOT PIP_MICRO)
message(" Install: local \"bin\", \"lib\" and \"include\"") message(" Install: local \"bin\", \"lib\" and \"include\"")
endif() endif()
endif() endif()
@@ -830,9 +830,6 @@ if (PIP_TESTS_LIST)
foreach(_test ${PIP_TESTS_LIST}) foreach(_test ${PIP_TESTS_LIST})
message(" * ${_test}") message(" * ${_test}")
endforeach() endforeach()
if (TESTS_RUN)
message("TESTS_RUN ON -> Run tests before install step")
endif()
else() else()
message(" Tests: skip (tests off)") message(" Tests: skip (tests off)")
endif() endif()
@@ -841,7 +838,7 @@ message(" Utilites:")
foreach(_util ${PIP_UTILS_LIST}) foreach(_util ${PIP_UTILS_LIST})
message(" * ${_util}") message(" * ${_util}")
endforeach() endforeach()
if(NOT PIP_FREERTOS) if(NOT PIP_MICRO)
message("") message("")
message(" Using libraries:") message(" Using libraries:")
foreach(LIB_ ${LIBS_STATUS}) foreach(LIB_ ${LIBS_STATUS})

115
README.md
View File

@@ -40,118 +40,3 @@ 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

@@ -71,7 +71,7 @@ if (NOT BUILDING_PIP)
find_library(PTHREAD_LIBRARY pthread) find_library(PTHREAD_LIBRARY pthread)
find_library(UTIL_LIBRARY util) find_library(UTIL_LIBRARY util)
set(_PIP_ADD_LIBS_ ${PTHREAD_LIBRARY} ${UTIL_LIBRARY}) set(_PIP_ADD_LIBS_ ${PTHREAD_LIBRARY} ${UTIL_LIBRARY})
if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT PIP_FREERTOS)) if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT PIP_MICRO))
find_library(RT_LIBRARY rt) find_library(RT_LIBRARY rt)
list(APPEND _PIP_ADD_LIBS_ ${RT_LIBRARY}) list(APPEND _PIP_ADD_LIBS_ ${RT_LIBRARY})
endif() endif()

View File

@@ -1,26 +0,0 @@
\~english \page application Application-level tools
\~russian \page application Инструменты уровня приложения
\~english
The Application module provides classes commonly needed at program startup and runtime:
* **PICLI** — command-line argument parser. Add named arguments (e.g. \c addArgument("debug") for \c -d / \c --debug), check presence with \a hasArgument(), optionally read values. Used in \ref using_basic for console and debug flags.
* **PILog** — high-level logging with categories and levels. Configure sinks and severity; write log lines from anywhere in the process.
* **PISystemMonitor** — snapshot of system resources (CPU, memory, etc.). Query current stats or subscribe to periodic updates.
* **PISingleApplication** — ensure only one instance of the application runs; optional inter-process messaging when a second instance is started.
* **PITranslator** — translation support: load catalogs, select language, translate strings at runtime.
All are included via the main PIP library or the Application umbrella (\a piapplicationmodule.h). For CLI and logging, see \ref using_basic; for full API details see the headers \a picli.h, \a pilog.h, \a pisystemmonitor.h, \a pisingleapplication.h, \a pitranslator.h.
\~russian
Модуль Application предоставляет классы, часто нужные при запуске и работе приложения:
* **PICLI** — разбор аргументов командной строки. Добавление именованных аргументов (\c addArgument("debug") для \c -d / \c --debug), проверка наличия \a hasArgument(), при необходимости чтение значений. Используется в \ref using_basic для флагов консоли и отладки.
* **PILog** — логирование с категориями и уровнями. Настройка приёмников и уровня детализации; запись строк лога из любой части процесса.
* **PISystemMonitor** — снимок ресурсов системы (CPU, память и т.д.). Запрос текущей статистики или подписка на периодические обновления.
* **PISingleApplication** — гарантия единственного экземпляра приложения; при необходимости обмен сообщениями между процессами при запуске второго экземпляра.
* **PITranslator** — поддержка перевода: загрузка каталогов, выбор языка, перевод строк в runtime.
Всё подключается через основную библиотеку PIP или зонтичный заголовок (\a piapplicationmodule.h). Для CLI и лога см. \ref using_basic; детали API — в заголовках \a picli.h, \a pilog.h, \a pisystemmonitor.h, \a pisingleapplication.h, \a pitranslator.h.

View File

@@ -1,56 +0,0 @@
\~english \page chunk_stream Chunk stream and versioned serialization
\~russian \page chunk_stream Поток чанков и версионная сериализация
\~english
\a PIChunkStream is a binary stream where data is stored as **chunks**: each chunk has an integer \e id and a value. Reading is id-based, so you can add or reorder fields over time and stay backward compatible: old readers ignore unknown ids, new readers can skip optional ids.
Two format versions exist (\a PIChunkStream::Version_1 and \a Version_2); the writer chooses the version, the reader detects it automatically. By default new data is written in Version_2.
# When to use
Use chunk streams when:
* You need to extend structures without breaking existing stored data (add new fields with new ids).
* You want optional or reordered fields in a single stream.
* You use \ref code_model to generate serialization: with default (chunk) mode, \c pip_cmg emits operators that read/write via \a PIChunkStream and field ids (see \ref code_model "code_model" for PIMETA \c id and \c simple-stream / \c no-stream).
For fixed, non-extensible layouts, plain \a PIBinaryStream operators (see \ref iostream) are enough.
# Usage
Build a \a PIChunkStream from a \a PIByteArray (read or read-write). Write with \c cs << cs.chunk(id, value) or \c add(id, value); read with \c read() to get the next id, then \c get(value). Call \c data() to get the byte buffer for storing or sending. Example (conceptually as in code_model output):
\code{.cpp}
PIByteArray buf;
PIChunkStream cs(&buf);
cs << cs.chunk(1, i) << cs.chunk(2, s);
// later:
PIChunkStream reader(buf);
while (!reader.atEnd()) {
switch (reader.read()) {
case 1: reader.get(i); break;
case 2: reader.get(s); break;
}
}
\endcode
Generated operators for structs use the same pattern; see \ref code_model.
\~russian
\a PIChunkStream — бинарный поток, в котором данные хранятся **чанками**: у каждого чанка целочисленный \e id и значение. Чтение идёт по id, поэтому можно добавлять или менять порядок полей с сохранением обратной совместимости: старые читатели игнорируют неизвестные id, новые могут пропускать необязательные.
Есть две версии формата (\a PIChunkStream::Version_1 и \a Version_2); версию выбирает запись, при чтении она определяется автоматически. По умолчанию запись идёт в Version_2.
# Когда использовать
Имеет смысл использовать поток чанков, когда:
* Нужно расширять структуры без поломки уже сохранённых данных (новые поля — новые id).
* Нужны необязательные или переставляемые поля в одном потоке.
* Используется \ref code_model для генерации сериализации: в режиме по умолчанию (chunk) \c pip_cmg выдаёт операторы через \a PIChunkStream и id полей (см. \ref code_model по PIMETA \c id и \c simple-stream / \c no-stream).
Для фиксированных неизменяемых форматов достаточно обычных операторов \a PIBinaryStream (см. \ref iostream).
# Использование
Создают \a PIChunkStream из \a PIByteArray (чтение или чтение/запись). Запись: \c cs << cs.chunk(id, value) или \c add(id, value); чтение: \c read() — следующий id, затем \c get(value). \c data() возвращает буфер для сохранения или передачи. Примеры генерации операторов — в \ref code_model.

View File

@@ -1,46 +0,0 @@
\~english \page client_server TCP client-server
\~russian \page client_server TCP клиент-сервер
\~english
The ClientServer module provides a TCP server that accepts connections and manages per-client objects, and an active client that connects to a server. All in the \a PIClientServer namespace.
# Server
\a PIClientServer::Server listens on an address (e.g. \a listenAll(port) for all interfaces). For each accepted connection the server creates a \a PIClientServer::ServerClient. You can override the client type and handle client lifecycle (e.g. data received, disconnected). Use \a getMaxClients() / \a setMaxClients() to limit simultaneous connections. \a listen(addr) starts listening, \a stopServer() stops the server, \a closeAll() closes all current clients.
# ServerClient
\a PIClientServer::ServerClient is the server-side representation of one connected client. The server creates and owns these objects. Override \a aboutDelete() if you need cleanup before the client is removed. Use the base API (\a ClientBase) to send and receive data on the connection.
# Client
\a PIClientServer::Client is the active client: it connects to a remote server (address/port). After connecting you use the same send/receive API as on the server side. Connect, exchange data, then disconnect when done.
# Typical flow
Server: construct \a Server, optionally set max clients and callbacks, call \a listen() or \a listenAll(port). Handle client events (new client, data, disconnect) in your overrides or via the provided hooks. Client: construct \a Client, connect to server address, send/receive, disconnect.
See \a piclientserver_server.h, \a piclientserver_client.h, \a piclientserver_client_base.h for the full API.
\~russian
Модуль ClientServer предоставляет TCP-сервер, принимающий соединения и управляющий объектами клиентов, и активный клиент, подключающийся к серверу. Всё в пространстве имён \a PIClientServer.
# Сервер
\a PIClientServer::Server слушает адрес (например \a listenAll(port) на всех интерфейсах). Для каждого принятого соединения создаётся \a PIClientServer::ServerClient. Можно подменить тип клиента и обрабатывать жизненный цикл (данные, отключение). \a getMaxClients() / \a setMaxClients() ограничивают число одновременных соединений. \a listen(addr) — запуск, \a stopServer() — остановка, \a closeAll() — закрытие всех клиентов.
# Серверный клиент
\a PIClientServer::ServerClient — серверное представление одного подключённого клиента. Объекты создаёт и владеет сервер. Переопределите \a aboutDelete() при необходимости очистки перед удалением. Отправка и приём данных — через базовый API (\a ClientBase).
# Клиент
\a PIClientServer::Client — активный клиент: подключается к удалённому серверу (адрес/порт). После подключения используется тот же API отправки/приёма. Подключение, обмен, отключение.
# Типичный сценарий
Сервер: создать \a Server, при необходимости задать лимит клиентов и обработчики, вызвать \a listen() или \a listenAll(port). Обрабатывать события клиентов в переопределениях или через хуки. Клиент: создать \a Client, подключиться к адресу сервера, обмен данными, отключиться.
Полный API: \a piclientserver_server.h, \a piclientserver_client.h, \a piclientserver_client_base.h.

View File

@@ -3,26 +3,6 @@
\~english \~english
# Introduction
Code generation helps when you need string representation of entities (classes, enums, etc.) or automated serialization/deserialization of structures and classes. For example, you may need a list of "name" = "value" pairs from an enumeration for a UI, or to traverse nested structures with metadata. You can describe a structure of any complexity, assign field IDs, and get ready-made operators for \a PIBinaryStream with versioning and backward compatibility.
# pip_cmg
PIP provides the \c pip_cmg utility: it takes source files, include paths, and options, and produces a .h/.cpp pair. Depending on options, the output may include: entity metadata; serialization operators; and the ability to get a \a PIVariant for any member by name.
Processing options: \c -s (do not follow #include); \c -I<include_dir> (add include path); \c -D<define> (add macro; \c PICODE is always defined).
Creation options: \c -A (create all); \c -M (metadata); \c -E (enums); \c -S (serialization operators); \c -G (get value by name); \c -o <output_file> (output base name without extension).
# CMake
The \c pip_code_model CMake macro invokes \c pip_cmg and keeps the model up to date. Call format: \c pip_code_model(<out_var> file0 [file1 ...] [OPTIONS ...] [NAME name]). Parameters: \c out_var receives generated file paths; \c file... are sources; \c OPTIONS are passed to \c pip_cmg (e.g. \c "-Es"); \c NAME sets the model file base (default \c "ccm_${PROJECT_NAME}"). The macro adds PIP include paths. Run \c pip_cmg -v for current options.
# Details
Metadata: attach \c PIMETA(...) to types, members or enums; read at runtime via \a PICODEINFO::classes() and \a PICODEINFO::enums(). Serialization: struct-level \c PIMETA(simple-stream) or \c PIMETA(no-stream), or per-member chunk ids (default); see \ref chunk_stream. Add the generated .h/.cpp to your target and \c #include the generated header; metadata loads before \c main().
\~russian \~russian
# Введение # Введение

View File

@@ -1,14 +0,0 @@
\~english \page config Configuration from file
\~russian \page config Конфигурация из файла
\~english
\a PIConfig parses and writes configuration from files, strings, or any \a PIIODevice. The internal model is a tree of entries; each node is \a PIConfig::Entry, and a list of entries is \a PIConfig::Branch. Use dotted paths to get values, e.g. \c getValue("section.key.subkey"). Supports INI-style \c [section] prefixes, multiline values, and \c include directives resolved at parse time.
Typical use: open a file or device, then call \c getValue(name) or \c getValue(name, default) on the root or on a \a PIConfig::Branch. Overloads exist for string, numeric, and bool defaults. To configure an I/O device from config, pass \a PIConfig::Entry pointers to \a PIIODevice::configure(); see \a PIIODevice and device-specific headers.
\~russian
\a PIConfig разбирает и записывает конфигурацию из файлов, строк или любого \a PIIODevice. Внутренняя модель — дерево записей; узел — \a PIConfig::Entry, список узлов — \a PIConfig::Branch. Доступ по точечным путям, например \c getValue("section.key.subkey"). Поддерживаются префиксы секций в стиле INI (\c [section]), многострочные значения и директивы \c include, разрешаемые при разборе.
Типичное использование: открыть файл или устройство, затем вызывать \c getValue(name) или \c getValue(name, default) от корня или от \a PIConfig::Branch. Есть перегрузки для строковых, числовых и булевых значений по умолчанию. Для настройки устройства ввода-вывода из конфига в \a PIIODevice::configure() передают указатели на \a PIConfig::Entry; см. \a PIIODevice и заголовки конкретных устройств.

View File

@@ -1,50 +0,0 @@
\~english \page connection Complex I/O (PIConnection)
\~russian \page connection Сложный ввод-вывод (PIConnection)
\~english
\a PIConnection is an abstract layer over physical I/O devices: it manages a **device pool**, **filters** (packet extraction), **senders** (timed output), and **diagnostics**. Several connections can share one physical device through the pool; each device has an associated read thread that you start/stop with \a startThreadedRead() and \a stopThreadedRead().
# Device pool
The device pool is a single per-application container of unique devices. Each \a PIConnection talks to real hardware through this pool, so one serial port or socket can feed multiple logical connections.
# Filters
A filter is a \a PIPacketExtractor plus a set of bound devices or other filters. When the read thread gets data from a device, that data can be passed to one or more filters. Filters have unique names; use \a filter(name) to get the \a PIPacketExtractor*, and \a filterBoundedDevices() for the list of bound devices/filters. One filter can receive from several sources and be bound to several others.
# Senders
Senders are named timers that periodically send data to bound devices. Create a sender or add a device to a sender with \a addSender(). Each sender runs a timer and calls the virtual \a senderData(); the returned value is sent to bound devices. Alternatively use \a setSenderFixedData() to send fixed data without calling \a senderData().
# Diagnostics
\a PIConnection creates a \a PIDiagnostics for each device or filter. Access them with \a diagnostic().
# Configuration
You can build a \a PIConnection from a config file section or configure it later with \a configureFromConfig() (see \ref config). Devices are described by full paths (see \a PIIODevice documentation). \a makeConfig() produces a string you can insert into a config file.
\~russian
\a PIConnection — абстрактный слой над физическими устройствами ввода-вывода: **пул устройств**, **фильтры** (извлечение пакетов), **отправители** (периодическая отправка) и **диагностика**. Несколько соединений могут использовать одно физическое устройство через пул; у каждого устройства есть поток чтения, запуск и остановка — \a startThreadedRead() и \a stopThreadedRead().
# Пул устройств
Пул устройств — единственный на приложение набор уникальных устройств. \a PIConnection обращается к железу через этот пул, поэтому один порт или сокет может обслуживать несколько логических соединений.
# Фильтры
Фильтр — это \a PIPacketExtractor и набор привязанных устройств или других фильтров. Когда поток чтения получает данные с устройства, они могут передаваться в один или несколько фильтров. У фильтров уникальные имена; \a filter(name) возвращает \a PIPacketExtractor*, \a filterBoundedDevices() — список привязанных устройств и фильтров. Один фильтр может получать данные из нескольких источников и быть привязан к нескольким.
# Отправители (senders)
Отправители — именованные таймеры, периодически отправляющие данные на привязанные устройства. Создание или добавление устройства — \a addSender(). У каждого отправителя свой таймер и вызов виртуального \a senderData(); возвращённое значение отправляется на устройства. Либо \a setSenderFixedData() — отправка фиксированных данных без вызова \a senderData().
# Диагностика
Для каждого устройства или фильтра создаётся \a PIDiagnostics. Доступ — \a diagnostic().
# Конфигурация
\a PIConnection можно собрать из секции конфига или настроить позже через \a configureFromConfig() (см. \ref config). Устройства задаются полными путями (см. документацию \a PIIODevice). \a makeConfig() формирует строку для вставки в конфиг.

View File

@@ -1,42 +0,0 @@
\~english \page console Tiling console (PIScreen)
\~russian \page console Тайлинговая консоль (PIScreen)
\~english
\a PIScreen is the console screen manager: it runs a drawing thread, hosts **tiles** (layout regions), and routes keyboard and optionally mouse input to the focused tile. Tiles can contain widgets: text rows, scroll bars, lists, buttons, button groups, check boxes, progress bars, \a PICout output, text input, etc.
# Basic use
Create a \a PIScreen (optionally with \c startNow = false and a key callback). Call \a enableExitCapture() so that a key (e.g. 'Q') triggers \a waitForFinish(). Add tiles and attach widgets to them; set focus and layout as needed. \a PIScreen inherits \a PIThread and runs the redraw loop; start it before \a waitForFinish() if you did not use \c startNow.
# Tiles and layout
Tiles (\a PIScreenTile) are attached to the screen and arranged in a layout. Each tile can hold widgets. Focus determines which tile receives keyboard input. See \a piscreentile.h, \a piscreentiles.h for composed tile widgets and layout types.
# Widgets
Widget types are declared in the console headers: list, button, buttons group, check box, progress bar, text input, terminal (PICout output), etc. Add them to a tile; they draw and react to input within the tile. Details and behavior per widget: \a piscreenconsole.h, \a piscreentiles.h, \a piterminal.h, \a piscreendrawer.h.
# Notes
Some widget options or behaviors may be refined in the implementation; when in doubt, check the header and example usage.
\~russian
\a PIScreen — менеджер консольного экрана: поток отрисовки, **тайлы** (области раскладки), маршрутизация клавиатуры и при необходимости мыши в активный тайл. В тайлах размещают виджеты: строки текста, скроллбары, списки, кнопки, группы кнопок, галочки, прогрессбары, вывод \a PICout, текстовый ввод и др.
# Базовое использование
Создать \a PIScreen (при необходимости \c startNow = false и callback клавиш). Вызвать \a enableExitCapture(), чтобы клавиша (например 'Q') вызывала \a waitForFinish(). Добавлять тайлы и виджеты, настраивать фокус и раскладку. \a PIScreen наследует \a PIThread и выполняет цикл перерисовки; запустить до \a waitForFinish(), если не использовали \c startNow.
# Тайлы и раскладка
Тайлы (\a PIScreenTile) присоединяются к экрану и располагаются в раскладке. В каждом тайле — виджеты. Фокус определяет получателя ввода с клавиатуры. Составные виджеты и типы раскладки: \a piscreentile.h, \a piscreentiles.h.
# Виджеты
Типы виджетов объявлены в заголовках консоли: список, кнопка, группа кнопок, галочка, прогрессбар, текстовый ввод, терминал (вывод PICout) и др. Их добавляют в тайл; отрисовка и реакция на ввод — внутри тайла. Подробности по виджетам: \a piscreenconsole.h, \a piscreentiles.h, \a piterminal.h, \a piscreendrawer.h.
# Замечания
Часть опций или поведения виджетов может уточняться в реализации; при сомнениях смотрите заголовки и примеры.

View File

@@ -1,52 +0,0 @@
\~english \page examples Examples
\~russian \page examples Примеры
\~english
The \c doc/examples directory contains sample code that can be built and run. Below, each file is listed with a short description and a pointer to related documentation where applicable.
| File | Description | See also |
|------|-------------|----------|
| pibytearray.cpp | \a PIByteArray and binary stream usage | \ref iostream |
| pichunkstream.cpp | \a PIChunkStream read/write | \ref chunk_stream |
| picollection.cpp | Collection helpers | — |
| picontainers.cpp | Containers (\a PIVector, \a PIMap, etc.) | \ref summary |
| piconfig.cpp | \a PIConfig, \a PIConfig::Entry, dotted paths | \ref config |
| picli.cpp | \a PICLI (stub) | \ref application |
| picout.cpp | \a PICout, console output | \ref using_basic |
| pievaluator.cpp | \a PIEvaluator, expression evaluation | \ref summary (Mathematics) |
| piincludes.cpp | Include paths and module discovery | — |
| piiodevice.cpp | \a PIIODevice, custom device and \a PIConfig | \ref config, \ref connection |
| pikbdlistener.cpp | \a PIKbdListener, keyboard input | \ref console |
| pimutex.cpp | \a PIMutex (minimal) | \ref threading |
| piobject.cpp | \a PIObject, events and handlers | \ref PIObject_sec0 |
| piparsehelper.cpp | Parse utilities | — |
| pistatemachine.cpp | \a PIStateMachine, states and transitions | \ref state_machine |
| pitimer.cpp | \a PITimer, periodic callbacks | \ref threading |
Examples are referenced from the main PIP build when documentation is enabled; paths and build integration may vary by project configuration.
\~russian
В каталоге \c doc/examples находятся примеры кода, которые можно собирать и запускать. Ниже перечислены файлы с кратким описанием и ссылкой на связанную документацию.
| Файл | Описание | См. также |
|------|----------|-----------|
| pibytearray.cpp | \a PIByteArray и бинарный поток | \ref iostream |
| pichunkstream.cpp | Чтение/запись \a PIChunkStream | \ref chunk_stream |
| picollection.cpp | Вспомогательные типы коллекций | — |
| picontainers.cpp | Контейнеры (\a PIVector, \a PIMap и др.) | \ref summary |
| piconfig.cpp | \a PIConfig, \a PIConfig::Entry, точечные пути | \ref config |
| picli.cpp | \a PICLI (заглушка) | \ref application |
| picout.cpp | \a PICout, вывод в консоль | \ref using_basic |
| pievaluator.cpp | \a PIEvaluator, вычисление выражений | \ref summary (Математика) |
| piincludes.cpp | Пути включения и поиск модулей | — |
| piiodevice.cpp | \a PIIODevice, своё устройство и \a PIConfig | \ref config, \ref connection |
| pikbdlistener.cpp | \a PIKbdListener, ввод с клавиатуры | \ref console |
| pimutex.cpp | \a PIMutex (минимальный пример) | \ref threading |
| piobject.cpp | \a PIObject, события и обработчики | \ref PIObject_sec0 |
| piparsehelper.cpp | Утилиты разбора | — |
| pistatemachine.cpp | \a PIStateMachine, состояния и переходы | \ref state_machine |
| pitimer.cpp | \a PITimer, периодические вызовы | \ref threading |
Примеры подключаются к сборке PIP при включённой документации; пути и способ интеграции зависят от конфигурации проекта.

View File

@@ -3,10 +3,8 @@
\~english \~english
\a PIBinaryStream is the binary serialization interface. For versioned, extensible formats with chunk ids see \ref chunk_stream. It is not used standalone; only as a mixin or via concrete classes such as \a PIByteArray and \a PIIOBinaryStream. Use it to save or load any data. Trivial types are read/written as memory blocks unless custom operators are defined; non-trivial types must have stream operators or the code will not compile. Containers are supported under the same rules. Enums are treated as int, bool as one byte. Write operators append to the stream; read operators consume from the beginning. Macros: \c BINARY_STREAM_FRIEND(T), \c BINARY_STREAM_WRITE(T), \c BINARY_STREAM_READ(T) (inside them \c s is the stream, \c v is the value).
\~russian \~russian
%PIBinaryStream представляет собой интерфейс бинарной сериализации. Для версионных расширяемых форматов с id чанков см. \ref chunk_stream. %PIBinaryStream представляет собой интерфейс бинарной сериализации.
Не может быть использован в чистом виде, только в виде миксина или Не может быть использован в чистом виде, только в виде миксина или
готовых классов: PIByteArray и PIIOBinaryStream. готовых классов: PIByteArray и PIIOBinaryStream.
@@ -30,7 +28,7 @@
* BINARY_STREAM_READ(T) - чтение из потока, "s" - объект потока, "v" - объект типа T. * BINARY_STREAM_READ(T) - чтение из потока, "s" - объект потока, "v" - объект типа T.
Пример: Пример:
\code{.cpp} \~\code{.cpp}
#include <pibytearray.h> #include <pibytearray.h>
class MyType { class MyType {
@@ -71,7 +69,7 @@ int main(int argc, char * argv[]) {
\~english Result: \~english Result:
\~russian Результат: \~russian Результат:
\code{.cpp} \~\code{.cpp}
0a000000040000007400650078007400 0a000000040000007400650078007400
10 text 10 text
@@ -86,7 +84,7 @@ operators of this class simply store/restore data block to/from stream:
Для сохранения/извлечения блоков произвольных данных используется класс PIMemoryBlock. Для сохранения/извлечения блоков произвольных данных используется класс PIMemoryBlock.
Потоковые операторы для него просто сохраняют/извлекают блоки байтов в/из потока: Потоковые операторы для него просто сохраняют/извлекают блоки байтов в/из потока:
\code{.cpp} \~\code{.cpp}
float a_read[10], a_write[10]; float a_read[10], a_write[10];
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
a_read [i] = 0.f; a_read [i] = 0.f;
@@ -105,7 +103,7 @@ for (int i = 0; i < 10; ++i)
\~english Result: \~english Result:
\~russian Результат: \~russian Результат:
\code{.cpp} \~\code{.cpp}
00000000cdcccc3dcdcc4c3e9a99993ecdcccc3e0000003f9a99193f3333333fcdcc4c3f6666663f 00000000cdcccc3dcdcc4c3e9a99993ecdcccc3e0000003f9a99193f3333333fcdcc4c3f6666663f
0 0
0.1 0.1
@@ -121,9 +119,7 @@ for (int i = 0; i < 10; ++i)
\~english \~english
If a read runs out of data (e.g. end of array or file), the stream's \c wasReadError() returns \c true. Check it after reads to handle errors correctly.
\~russian \~russian
Если при чтении из потока не хватило данных (например, закончился массив или файл), то проверка Если при чтении из потока не хватило данных (например, закончился массив или файл), то проверка
объекта потока на \c wasReadError() вернёт \c true. Рекомендуется делать эту проверку после чтения объекта потока на wasReadError() вернёт true. Рекомендуется делать эту проверку после чтения
данных для корректной обработки ошибки. данных для корректной обработки ошибки.

View File

@@ -8,19 +8,19 @@ PIP - Platform-Independent Primitives - is crossplatform library for C++ develop
This library can help developers write non-GUI projects much more quickly, efficiently This library can help developers write non-GUI projects much more quickly, efficiently
and customizable than on pure C++. and customizable than on pure C++.
Applications written on PIP work the same on any system. One can read and write Application written on PIP works the same on any system. One can read and write
any data types, serialize any types to device channels between any systems. any data types, serialize any types to device channels between any systems.
Many common data types, system primitives and devices implemented in this library. Many common data types, system primitives and devices implemented in this library.
PIP also tightly integrates with [CMake](https://cmake.org/) build system, providing handy search for the PIP also tightly integrates with [CMake](https://cmake.org/) build system, providing handly search
main library, additional modules of PIP and several utilities. With main library, additional modules of PIP and several utilites. With
CMake and PIP one can easily generate and use code metainformation or CMake with PIP one can easily generate and use code metainformation or
serialize custom types with version back-compatibility. serialize custom types with it versions back-compatability.
Summary one can find at \ref summary page. Summary one can find at \ref summary page.
Basic using — \ref using_basic. Further topics — \ref using_advanced. Configuration — \ref config. Code generation — \ref code_model. Streams: \ref iostream, \ref chunk_stream. State machine — \ref state_machine. Complex I/O — \ref connection. TCP client-server — \ref client_server. Tiling console — \ref console. Application tools — \ref application. Threading — \ref threading. Examples — \ref examples. Basic using of PIP described at \ref using_basic page.
\~russian \~russian
@@ -41,4 +41,4 @@ PIP также тесно интегрируется с системой сбо
Сводку можно найти на странице \ref summary. Сводку можно найти на странице \ref summary.
Базовое использование — \ref using_basic. Дополнительные темы — \ref using_advanced. Конфигурация — \ref config. Кодогенерация — \ref code_model. Потоки: \ref iostream, \ref chunk_stream. Машина состояний — \ref state_machine. Сложный ввод-вывод — \ref connection. TCP клиент-сервер — \ref client_server. Тайлинговая консоль — \ref console. Инструменты приложения — \ref application. Многопоточность — \ref threading. Примеры — \ref examples. Базовое использование PIP описано на странице \ref using_basic.

View File

@@ -1,714 +0,0 @@
\~english \page state_machine State machine
\~russian \page state_machine Машина состояний
\~english
# State Machine
## State Machine Description
State machine is a behavioral design pattern that allows an object to change its behavior when its internal state changes.
Implementation in PIP is based on the **SCXML** (State Chart XML) standard.
### SCXML Concepts
- **State** — a node in the state tree, can be atomic or compound
- **Transition** — a connection between states that triggers on an event
- **Event** — a trigger that causes a transition
- **Guard** — a condition that must be true for a transition to execute
- **Action** — an operation executed during a transition
- **Parallel** — a state where all substates are activated simultaneously
### PIP State Machine Features
- **Cannot create state, event, transition on stack** — all objects are created via `new` and managed via pointers
- **State machine is the root state** — `PIStateMachine` inherits from `PIStateBase`
- **All transitions and states are automatically deleted** — when the parent object is destroyed
### State Types
- **Atomic state** — a state without nested substates
- **Compound state** — a state containing nested substates
- **Final state** — a terminating state indicating the end of machine execution
- **Parallel state** — a state where all substates are activated simultaneously
### Transition Types
- **Normal transition** — triggers on receiving a specific event
- **Timeout transition** — triggers automatically after a specified time interval
- **Guarded transition** — triggers only when a specific condition is met
## State Machine API
### Main Classes
#### PIStateMachine
Main state machine class.
**Key methods:**
- `bool start()` — starts state machine execution
- `bool isRunning()` — checks if state machine is running
- `void setOnFinish(std::function<void()> f)` — sets finish callback
- `bool postEvent(int event_id, Args... args)` — posts event to state machine
#### PIStateBase
Base class for all states.
**Key methods:**
- `virtual void onEnter()` — called when state is entered
- `virtual void onExit()` — called when state is exited
- `void addState(PIStateBase *s)` — adds child state
- `PITransitionBase *addTransition(PIStateBase *target, int event_id)` — adds transition
- `PITransitionTimeout *addTimeoutTransition(PIStateBase *target, PISystemTime timeout)` — adds timeout transition
- `void setParallel(bool yes)` — sets parallel mode
#### PIStateLambda
State with lambda callbacks.
\code{.cpp}
PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString &n = {})
\endcode
#### PIStateFinal
Final state of state machine.
\code{.cpp}
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString &n = {})
\endcode
#### PITransitionBase
Base class for transitions.
**Key methods:**
- `PITransitionBase *addGuard(std::function<R(Args...)> f)` — adds guard function
- `PITransitionBase *addAction(std::function<void()> a)` — adds action
- `void trigger()` — triggers transition
#### PITransitionTimeout
Transition that triggers after a specified timeout.
## Usage Examples
### Simple State Machine
\code{.cpp}
#include "pistatemachine.h"
#include "pisystemtime.h"
// Create state machine
PIStateMachine *machine = new PIStateMachine("Main");
// Create states
PIStateLambda *idle = new PIStateLambda(
[]() { piCout << "Entering Idle state\n"; },
[]() { piCout << "Exiting Idle state\n"; },
"Idle"
);
PIStateLambda *running = new PIStateLambda(
[]() { piCout << "Entering Running state\n"; },
[]() { piCout << "Exiting Running state\n"; },
"Running"
);
PIStateFinal *finish = new PIStateFinal(
[]() { piCout << "Machine finished\n"; },
"Finish"
);
// Add states
machine->addState(idle);
machine->addState(running);
machine->addState(finish);
// Set initial state
idle->setInitialState(idle);
running->setInitialState(running);
machine->setInitialState(idle);
// Add transitions
idle->addTransition(running, 1);
running->addTransition(finish, 2);
// Set finish callback
machine->setOnFinish([]() { piCout << "Machine execution completed\n"; });
// Start machine
machine->start();
// Post events
machine->postEvent(1); // Transition to Running
machine->postEvent(2); // Transition to Finish
\endcode
### Guarded Transitions
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("With Guards");
PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
PIStateLambda *stateC = new PIStateLambda([]() { piCout << "State C\n"; }, nullptr, "C");
machine->addState(stateA);
machine->addState(stateB);
machine->addState(stateC);
stateA->setInitialState(stateA);
machine->setInitialState(stateA);
// Transition with guard function
auto *t1 = stateA->addTransition(stateB, 1);
t1->addGuard([](int value) -> bool {
return value > 10;
});
// Transition with another guard function
auto *t2 = stateB->addTransition(stateC, 2);
t2->addGuard([](const PIString &msg) -> bool {
return msg == "allowed";
});
machine->start();
// First call will not execute (value <= 10)
machine->postEvent(1, 5);
// Second call will execute (value > 10)
machine->postEvent(1, 15);
// First call will not execute (msg != "allowed")
machine->postEvent(2, "test");
// Second call will execute (msg == "allowed")
machine->postEvent(2, "allowed");
\endcode
### Timeout Transitions
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("With Timeout");
PIStateLambda *working = new PIStateLambda(
[]() { piCout << "Working...\n"; },
[]() { piCout << "Stop working\n"; },
"Working"
);
PIStateLambda *timeoutState = new PIStateLambda([]() { piCout << "Timeout occurred\n"; }, nullptr, "Timeout");
PIStateFinal *finish = new PIStateFinal([]() { piCout << "Done\n"; }, "Finish");
machine->addState(working);
machine->addState(timeoutState);
machine->addState(finish);
working->setInitialState(working);
machine->setInitialState(working);
// Add timeout transition (after 5 seconds)
working->addTimeoutTransition(timeoutState, PISystemTime::fromSeconds(5));
// Add transition from timeoutState to finish
timeoutState->addTransition(finish, 1);
machine->start();
\endcode
### Compound States
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("Compound States");
// Root state (machine)
PIStateLambda *root = new PIStateLambda([]() { piCout << "Root state\n"; }, nullptr, "Root");
// Compound state with substates
PIStateLambda *parent = new PIStateLambda([]() { piCout << "Parent state\n"; }, nullptr, "Parent");
PIStateLambda *child1 = new PIStateLambda([]() { piCout << "Child 1\n"; }, nullptr, "Child1");
PIStateLambda *child2 = new PIStateLambda([]() { piCout << "Child 2\n"; }, nullptr, "Child2");
parent->setInitialState(child1);
parent->addState(child1);
parent->addState(child2);
root->addState(parent);
machine->addState(root);
machine->setInitialState(root);
// Add transitions
root->addTransition(parent, 1);
parent->addTransition(root, 2);
machine->start();
// Transition to parent
machine->postEvent(1);
// Transition back
machine->postEvent(2);
\endcode
### Parallel States
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("Parallel States");
PIStateLambda *root = new PIStateLambda([]() { piCout << "Root\n"; }, nullptr, "Root");
PIStateLambda *parallel = new PIStateLambda([]() { piCout << "Parallel\n"; }, nullptr, "Parallel");
PIStateLambda *sub1 = new PIStateLambda([]() { piCout << "Substate 1\n"; }, nullptr, "Sub1");
PIStateLambda *sub2 = new PIStateLambda([]() { piCout << "Substate 2\n"; }, nullptr, "Sub2");
// Enable parallel mode
parallel->setParallel(true);
parallel->addState(sub1);
parallel->addState(sub2);
parallel->setInitialState(sub1);
root->addState(parallel);
machine->addState(root);
machine->setInitialState(root);
machine->start();
// When entering parallel, both substates are activated simultaneously
\endcode
### Transitions with Actions
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("With Actions");
PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
machine->addState(stateA);
machine->addState(stateB);
machine->setInitialState(stateA);
// Add transition with action
auto *t = stateA->addTransition(stateB, 1);
t->addAction([]() { piCout << "Action during transition\n"; });
machine->start();
machine->postEvent(1);
\endcode
## Thread Safety
State machine is thread-safe. The `postEvent` method uses a queue to handle nested calls, allowing safe event posting from
different threads.
## Usage Rules
### Cannot Create on Stack
\code{.cpp}
// ❌ WRONG
PIStateLambda state([]() {}, nullptr, "State");
// ✅ CORRECT
PIStateLambda *state = new PIStateLambda([]() {}, nullptr, "State");
\endcode
### Proper Object Hierarchy
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("Main");
// States are created via new and added to machine or another state
PIStateLambda *state1 = new PIStateLambda([]() {}, nullptr, "State1");
PIStateLambda *state2 = new PIStateLambda([]() {}, nullptr, "State2");
machine->addState(state1);
machine->addState(state2);
// Transitions are added to states via addTransition
state1->addTransition(state2, 1);
// Machine is started
machine->start();
\endcode
### Memory Cleanup
All objects (states, transitions) are automatically deleted when the parent object is destroyed:
- When `PIStateMachine` is destroyed, all states and transitions are deleted
- When `PIStateBase` is destroyed, all child states and transitions are deleted
## Debugging
For debugging, you can use the `print()` method to output the state tree:
\code{.cpp}
machine->print();
\endcode
Also, you can use `activeAtomics()` to get a list of active states.
## Related Modules
- \ref DateTime module for `PISystemTime` used in timeout transitions
\~russian
# Машина состояний
## Описание машины состояний
Машина состояний — это поведенческий паттерн проектирования, который позволяет объекту изменять свое поведение при изменении
внутреннего состояния. Реализация в PIP основана на стандарте **SCXML** (State Chart XML).
### Основные концепции SCXML
- **State (Состояние)** — узел в дереве состояний, может быть атомарным или составным
- **Transition (Переход)** — связь между состояниями, срабатывает при событии
- **Event (Событие)** — триггер, вызывающий переход
- **Guard (Сторожевая функция)** — условие, которое должно быть истинным для выполнения перехода
- **Action (Действие)** — операция, выполняемая при переходе
- **Parallel (Параллельное состояние)** — состояние, в котором все подсостояния активируются одновременно
### Особенности реализации PIP
- **Нельзя создавать state, event, transition в стеке** — все объекты создаются через `new` и управляются через указатели
- **Машина состояний — это корневой state** — `PIStateMachine` наследуется от `PIStateBase`
- **Все переходы и состояния удаляются автоматически** — при уничтожении родительского объекта
### Основные типы состояний
- **Атомарное состояние** — состояние без вложенных подсостояний
- **Составное состояние** — состояние, содержащее вложенные подсостояния
- **Финальное состояние** — завершающее состояние, указывающее на окончание работы машины
- **Параллельное состояние** — состояние, в котором все подсостояния активируются одновременно
### Виды переходов
- **Обычный переход** — срабатывает при получении определенного события
- **Переход по таймауту** — срабатывает автоматически через заданный промежуток времени
- **Переход с guard** — срабатывает только при выполнении определенного условия
## PIP State Machine API
### Основные классы
#### PIStateMachine
Основной класс машины состояний.
**Ключевые методы:**
- `bool start()` — запускает выполнение машины состояний
- `bool isRunning()` — проверяет, запущена ли машина
- `void setOnFinish(std::function<void()> f)` — устанавливает коллбэк завершения
- `bool postEvent(int event_id, Args... args)` — отправляет событие в машину состояний
#### PIStateBase
Базовый класс для всех состояний.
**Ключевые методы:**
- `virtual void onEnter()` — вызывается при входе в состояние
- `virtual void onExit()` — вызывается при выходе из состояния
- `void addState(PIStateBase *s)` — добавляет дочернее состояние
- `PITransitionBase *addTransition(PIStateBase *target, int event_id)` — добавляет переход
- `PITransitionTimeout *addTimeoutTransition(PIStateBase *target, PISystemTime timeout)` — добавляет переход по таймауту
- `void setParallel(bool yes)` — устанавливает параллельный режим
#### PIStateLambda
Состояние с lambda-коллбэками.
\code{.cpp}
PIStateLambda(std::function<void()> on_enter, std::function<void()> on_exit = nullptr, const PIString &n = {})
\endcode
#### PIStateFinal
Финальное состояние машины состояний.
\code{.cpp}
PIStateFinal(std::function<void()> on_finish = nullptr, const PIString &n = {})
\endcode
#### PITransitionBase
Базовый класс для переходов.
**Ключевые методы:**
- `PITransitionBase *addGuard(std::function<R(Args...)> f)` — добавляет сторожевую функцию
- `PITransitionBase *addAction(std::function<void()> a)` — добавляет действие
- `void trigger()` — запускает переход
#### PITransitionTimeout
Переход, срабатывающий через заданный промежуток времени.
## Примеры использования
### Простая машина состояний
\code{.cpp}
#include "pistatemachine.h"
#include "pisystemtime.h"
// Создаем машину состояний
PIStateMachine *machine = new PIStateMachine("Main");
// Создаем состояния
PIStateLambda *idle = new PIStateLambda(
[]() { piCout << "Entering Idle state\n"; },
[]() { piCout << "Exiting Idle state\n"; },
"Idle"
);
PIStateLambda *running = new PIStateLambda(
[]() { piCout << "Entering Running state\n"; },
[]() { piCout << "Exiting Running state\n"; },
"Running"
);
PIStateFinal *finish = new PIStateFinal(
[]() { piCout << "Machine finished\n"; },
"Finish"
);
// Добавляем состояния
machine->addState(idle);
machine->addState(running);
machine->addState(finish);
// Устанавливаем начальное состояние
idle->setInitialState(idle);
running->setInitialState(running);
machine->setInitialState(idle);
// Добавляем переходы
idle->addTransition(running, 1);
running->addTransition(finish, 2);
// Устанавливаем коллбэк завершения
machine->setOnFinish([]() { piCout << "Machine execution completed\n"; });
// Запускаем машину
machine->start();
// Отправляем события
machine->postEvent(1); // Перейти в Running
machine->postEvent(2); // Перейти в Finish
\endcode
### Машина состояний с guard-функциями
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("With Guards");
PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
PIStateLambda *stateC = new PIStateLambda([]() { piCout << "State C\n"; }, nullptr, "C");
machine->addState(stateA);
machine->addState(stateB);
machine->addState(stateC);
stateA->setInitialState(stateA);
machine->setInitialState(stateA);
// Переход с guard-функцией
auto *t1 = stateA->addTransition(stateB, 1);
t1->addGuard([](int value) -> bool {
return value > 10;
});
// Переход с другой guard-функцией
auto *t2 = stateB->addTransition(stateC, 2);
t2->addGuard([](const PIString &msg) -> bool {
return msg == "allowed";
});
machine->start();
// Первый вызов не выполнится (value <= 10)
machine->postEvent(1, 5);
// Второй вызов выполнится (value > 10)
machine->postEvent(1, 15);
// Первый вызов не выполнится (msg != "allowed")
machine->postEvent(2, "test");
// Второй вызов выполнится (msg == "allowed")
machine->postEvent(2, "allowed");
\endcode
### Машина состояний с таймаутами
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("With Timeout");
PIStateLambda *working = new PIStateLambda(
[]() { piCout << "Working...\n"; },
[]() { piCout << "Stop working\n"; },
"Working"
);
PIStateLambda *timeoutState = new PIStateLambda([]() { piCout << "Timeout occurred\n"; }, nullptr, "Timeout");
PIStateFinal *finish = new PIStateFinal([]() { piCout << "Done\n"; }, "Finish");
machine->addState(working);
machine->addState(timeoutState);
machine->addState(finish);
working->setInitialState(working);
machine->setInitialState(working);
// Добавляем переход по таймауту (через 5 секунд)
working->addTimeoutTransition(timeoutState, PISystemTime::fromSeconds(5));
// Добавляем переход из timeoutState в finish
timeoutState->addTransition(finish, 1);
machine->start();
\endcode
### Составные состояния
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("Compound States");
// Корневое состояние (машина)
PIStateLambda *root = new PIStateLambda([]() { piCout << "Root state\n"; }, nullptr, "Root");
// Составное состояние с подсостояниями
PIStateLambda *parent = new PIStateLambda([]() { piCout << "Parent state\n"; }, nullptr, "Parent");
PIStateLambda *child1 = new PIStateLambda([]() { piCout << "Child 1\n"; }, nullptr, "Child1");
PIStateLambda *child2 = new PIStateLambda([]() { piCout << "Child 2\n"; }, nullptr, "Child2");
parent->setInitialState(child1);
parent->addState(child1);
parent->addState(child2);
root->addState(parent);
machine->addState(root);
machine->setInitialState(root);
// Добавляем переходы
root->addTransition(parent, 1);
parent->addTransition(root, 2);
machine->start();
// Переход в parent
machine->postEvent(1);
// Переход обратно
machine->postEvent(2);
\endcode
### Параллельные состояния
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("Parallel States");
PIStateLambda *root = new PIStateLambda([]() { piCout << "Root\n"; }, nullptr, "Root");
PIStateLambda *parallel = new PIStateLambda([]() { piCout << "Parallel\n"; }, nullptr, "Parallel");
PIStateLambda *sub1 = new PIStateLambda([]() { piCout << "Substate 1\n"; }, nullptr, "Sub1");
PIStateLambda *sub2 = new PIStateLambda([]() { piCout << "Substate 2\n"; }, nullptr, "Sub2");
// Включаем параллельный режим
parallel->setParallel(true);
parallel->addState(sub1);
parallel->addState(sub2);
parallel->setInitialState(sub1);
root->addState(parallel);
machine->addState(root);
machine->setInitialState(root);
machine->start();
// При входе в parallel оба подсостояния активируются одновременно
\endcode
### Машина состояний с действиями
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("With Actions");
PIStateLambda *stateA = new PIStateLambda([]() { piCout << "State A\n"; }, nullptr, "A");
PIStateLambda *stateB = new PIStateLambda([]() { piCout << "State B\n"; }, nullptr, "B");
machine->addState(stateA);
machine->addState(stateB);
machine->setInitialState(stateA);
// Добавляем переход с действием
auto *t = stateA->addTransition(stateB, 1);
t->addAction([]() { piCout << "Action during transition\n"; });
machine->start();
machine->postEvent(1);
\endcode
## Потокобезопасность
Машина состояний PIP потокобезопасна. Метод `postEvent` использует очередь для обработки вложенных вызовов, что позволяет
безопасно отправлять события из разных потоков.
## Правила использования
### Нельзя создавать в стеке
\code{.cpp}
// ❌ НЕЛЬЗЯ
PIStateLambda state([]() {}, nullptr, "State");
// ✅ ПРАВИЛЬНО
PIStateLambda *state = new PIStateLambda([]() {}, nullptr, "State");
\endcode
### Правильная иерархия объектов
\code{.cpp}
PIStateMachine *machine = new PIStateMachine("Main");
// Состояния создаются через new и добавляются в машину или другое состояние
PIStateLambda *state1 = new PIStateLambda([]() {}, nullptr, "State1");
PIStateLambda *state2 = new PIStateLambda([]() {}, nullptr, "State2");
machine->addState(state1);
machine->addState(state2);
// Переходы добавляются к состояниям через addTransition
state1->addTransition(state2, 1);
// Машина запускается
machine->start();
\endcode
### Очистка памяти
Все объекты (состояния, переходы) автоматически удаляются при уничтожении родительского объекта:
- При уничтожении `PIStateMachine` удаляются все состояния и переходы
- При уничтожении `PIStateBase` удаляются все дочерние состояния и переходы
## Отладка
Для отладки можно использовать метод `print()` для вывода дерева состояний:
\code{.cpp}
machine->print();
\endcode
Также можно использовать `activeAtomics()` для получения списка активных состояний.
## Связанные модули
- \ref DateTime модуль для `PISystemTime`, используемого в переходах по таймауту

View File

@@ -35,7 +35,7 @@
* binary log (\a PIBinaryLog) * binary log (\a PIBinaryLog)
* complex I/O point (\a PIConnection) * complex I/O point (\a PIConnection)
* peering net node (\a PIPeer) * peering net node (\a PIPeer)
* connection quality diagnostic (\a PIDiagnostics) * connection quality diagnotic (\a PIDiagnostics)
* Run-time libraries * Run-time libraries
* external process (\a PIProcess) * external process (\a PIProcess)
* external library (\a PILibrary) * external library (\a PILibrary)
@@ -56,13 +56,11 @@
* single-instance application control (\a PISingleApplication) * single-instance application control (\a PISingleApplication)
* high-level log (\a PILog) * high-level log (\a PILog)
* translation support (\a PITranslator) * translation support (\a PITranslator)
* State machine ([By standard](https://www.w3.org/TR/scxml/)) (\a PIStateMachine) * State machine ([By stantard](https://www.w3.org/TR/scxml/)) (\a PIStateMachine)
* High-level TCP client-server * High-level TCP client-server
* server (\a PIClientServer::Server, \a PIClientServer::ServerClient) * server (\a PIClientServer::Server, \a PIClientServer::ServerClient)
* client (\a PIClientServer::Client) * client (\a PIClientServer::Client)
* Crypt support (\a PICrypt, \a PIAuth) * Crypt support (\a PICrypt, \a PIAuth)
* Cloud (\a PICloudClient, \a PICloudServer) — named endpoints over ethernet
* HTTP client and server (\a PIHTTPClient, \a PIHTTPServer, \a MicrohttpdServer)
\~russian \~russian
@@ -124,5 +122,3 @@
* сервер (\a PIClientServer::Server, \a PIClientServer::ServerClient) * сервер (\a PIClientServer::Server, \a PIClientServer::ServerClient)
* клиент (\a PIClientServer::Client) * клиент (\a PIClientServer::Client)
* Поддержка шифрования (\a PICrypt, \a PIAuth) * Поддержка шифрования (\a PICrypt, \a PIAuth)
* Облако (\a PICloudClient, \a PICloudServer) — именованные конечные точки поверх Ethernet
* HTTP-клиент и сервер (\a PIHTTPClient, \a PIHTTPServer, \a MicrohttpdServer)

View File

@@ -1,28 +0,0 @@
\~english \page threading Multithreading
\~russian \page threading Многопоточность
\~english
The Thread module provides threads, timers, synchronization primitives and task execution:
* **PIThread** — run a loop or one-off work in a separate thread. Override \a run() or use the default loop; start/stop with \a start() and \a stop(). Can act as the event performer for \a PIObject (see \ref using_advanced "Threading and events").
* **PITimer** — periodic callbacks at a given frequency (e.g. Hz). Connect to a handler; start/stop the timer. Used in \ref using_basic and in state machine examples.
* **Synchronization** — \a PIMutex, \a PISpinlock, \a PIConditionVariable, \a PISemaphore, \a PIReadWriteLock for protecting shared data and coordinating threads.
* **PIThreadPoolExecutor** — submit tasks to a fixed pool of worker threads; wait for completion or shutdown.
* **PIThreadPoolLoop** — run a function over a range in parallel (parallel-for style).
* **PIBlockingDequeue** — blocking producer-consumer queue for passing work between threads.
Use \a PIMutexLocker (and similar guards) for exception-safe locking. Events from other threads can be queued and processed in the object's thread via \a callQueuedEvents() (see \ref PIObject_sec0). Full API: \a pithread.h, \a pitimer.h, \a pimutex.h, \a pithreadpoolexecutor.h, \a piblockingqueue.h, \a pithreadmodule.h.
\~russian
Модуль Thread предоставляет потоки, таймеры, примитивы синхронизации и выполнение задач:
* **PIThread** — выполнение цикла или разовой работы в отдельном потоке. Переопределение \a run() или использование цикла по умолчанию; запуск и остановка — \a start() и \a stop(). Может быть исполнителем событий для \a PIObject (см. \ref using_advanced "Потоки и события").
* **PITimer** — периодические вызовы с заданной частотой (например в Гц). Подключение обработчика; запуск и остановка таймера. Используется в \ref using_basic и в примерах машины состояний.
* **Синхронизация** — \a PIMutex, \a PISpinlock, \a PIConditionVariable, \a PISemaphore, \a PIReadWriteLock для защиты общих данных и согласования потоков.
* **PIThreadPoolExecutor** — отправка задач в пул рабочих потоков; ожидание завершения или остановка пула.
* **PIThreadPoolLoop** — параллельный запуск функции по диапазону (стиль parallel-for).
* **PIBlockingDequeue** — блокирующая очередь производитель–потребитель для передачи работы между потоками.
Для исключений-безопасной блокировки используйте \a PIMutexLocker и аналогичные охранные классы. События из других потоков можно ставить в очередь и обрабатывать в потоке объекта через \a callQueuedEvents() (см. \ref PIObject_sec0). Полный API: \a pithread.h, \a pitimer.h, \a pimutex.h, \a pithreadpoolexecutor.h, \a piblockingqueue.h, \a pithreadmodule.h.

View File

@@ -1,64 +0,0 @@
\~english \page using_advanced Further topics
\~russian \page using_advanced Дополнительные темы
\~english
After \ref using_basic you may want to explore:
* \ref summary — full list of PIP modules and classes (containers, I/O, threading, math, state machine, etc.).
* \ref config — reading and writing configuration with \a PIConfig (files, dotted paths, INI-style sections).
* \ref code_model — code generation: metadata, serialization operators, PIMETA, \c pip_cmg and CMake integration.
* \ref iostream — binary streams (\a PIBinaryStream, \a PIByteArray), operators and \a PIMemoryBlock.
* \ref chunk_stream — versioned serialization with \a PIChunkStream (chunks by id, backward compatibility).
* \ref state_machine — state machine concepts, states, transitions, conditions, \a PIStateMachine.
* \ref connection — complex I/O: \a PIConnection, device pool, filters, senders, diagnostics.
* \ref client_server — TCP server and client (\a PIClientServer::Server, \a PIClientServer::Client).
* \ref console — tiling console \a PIScreen, tiles, widgets (list, button, progress, input, etc.).
* \ref application — application-level: \a PICLI, \a PILog, \a PISystemMonitor, \a PISingleApplication, \a PITranslator.
* \ref threading — multithreading: \a PIThread, \a PITimer, synchronization, executor, blocking queue.
* \ref examples — index of sample code in doc/examples.
Events and handlers are documented on the \a PIObject reference page (\ref PIObject_sec0).
\par Threading and events
Many PIP classes inherit \a PIObject and use events: handlers can be invoked directly or queued. When events are queued (e.g. from another thread), they are dispatched in the object's thread; call \a callQueuedEvents() or \a maybeCallQueuedEvents() to drain the queue. \a PIThread can act as the performer for such objects. See \ref PIObject_sec0 and \a PIThread.
\par Introspection
With \c PIP_INTROSPECTION defined at build time, the introspection module provides macros and APIs to traverse objects and containers at runtime (e.g. for debugging or serialization). Build PIP with this option and link the introspection library; see the introspection headers in \a piintrospection_base.h and related files.
\par GPU / OpenCL
The OpenCL module wraps OpenCL for buffers and programs. See \a piopencl.h for the public API. Behavior and limitations may depend on the implementation; check the header and backend when integrating.
\~russian
После \ref using_basic имеет смысл перейти к:
* \ref summary — полный перечень модулей и классов PIP (контейнеры, ввод-вывод, потоки, математика, машина состояний и др.).
* \ref config — чтение и запись конфигурации с помощью \a PIConfig (файлы, точечные пути, секции в стиле INI).
* \ref code_model — кодогенерация: метаинформация, операторы сериализации, PIMETA, утилита \c pip_cmg и интеграция с CMake.
* \ref iostream — бинарные потоки (\a PIBinaryStream, \a PIByteArray), операторы и \a PIMemoryBlock.
* \ref chunk_stream — версионная сериализация с \a PIChunkStream (чанки по id, обратная совместимость).
* \ref state_machine — машина состояний: концепции, состояния, переходы, условия, \a PIStateMachine.
* \ref connection — сложный ввод-вывод: \a PIConnection, пул устройств, фильтры, отправители, диагностика.
* \ref client_server — TCP-сервер и клиент (\a PIClientServer::Server, \a PIClientServer::Client).
* \ref console — тайлинговая консоль \a PIScreen, тайлы, виджеты (список, кнопка, прогресс, ввод и др.).
* \ref application — уровень приложения: \a PICLI, \a PILog, \a PISystemMonitor, \a PISingleApplication, \a PITranslator.
* \ref threading — многопоточность: \a PIThread, \a PITimer, синхронизация, исполнитель, блокирующая очередь.
* \ref examples — перечень примеров в doc/examples.
События и обработчики описаны на странице \a PIObject (\ref PIObject_sec0).
\par Потоки и события
Многие классы PIP наследуют \a PIObject и используют события: обработчики могут вызываться сразу или ставиться в очередь. При постановке в очередь (например из другого потока) они обрабатываются в потоке объекта; вызов \a callQueuedEvents() или \a maybeCallQueuedEvents() обрабатывает очередь. \a PIThread может выступать исполнителем для таких объектов. См. \ref PIObject_sec0 и \a PIThread.
\par Интроспекция
При сборке с макросом \c PIP_INTROSPECTION модуль интроспекции предоставляет макросы и API для обхода объектов и контейнеров в runtime (например для отладки или сериализации). Соберите PIP с этой опцией и подключите библиотеку интроспекции; см. заголовки \a piintrospection_base.h и связанные.
\par GPU / OpenCL
Модуль OpenCL — обёртка над OpenCL для буферов и программ. Публичный API: \a piopencl.h. Поведение и ограничения зависят от реализации; при интеграции смотрите заголовок и бэкенд.

View File

@@ -3,10 +3,10 @@
\~english \~english
Many novice programmers face common tasks when interacting with the system: output to console, Many novice programmers are solved many common task with system integrity: output to console,
detecting keyboard presses, working with serial ports, ethernet or files, and more. keyboard buttons press detecting, working with serial ports, ethernet or files, and many other.
This library addresses these tasks; code based on PIP will compile and work These tasks can solve this library, and code, based only on PIP will be compile and work
similarly on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX. similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX.
Typical application on PIP looks like this: \n Typical application on PIP looks like this: \n
\~russian \~russian
@@ -112,17 +112,17 @@ int main(int argc, char * argv[]) {
This code demonstrates simple interactive configurable program, which can be started with console This code demonstrates simple interactive configurable program, which can be started with console
display or not, and with debug or not. \b MainClass is central class that also can be inherited from display or not, and with debug or not. \b MainClass is central class that also can be inherited from
\a PIThread and reimplement \a run() function. \a PIThread and reimplement \a run() function.
\n Many PIP classes have events and event handlers, which can be connected one to another. \n Many PIP classes has events and event handlers, which can be connected one to another.
Details you can see at \a PIObject reference page (\ref PIObject_sec0). Details you can see at \a PIObject reference page (\ref PIObject_sec0).
\n To configure your program from file use \a PIConfig (see \ref config). \n To configure your program from file use \a PIConfig.
\n For more topics see \ref using_advanced. \n If you want more information see \ref using_advanced
\~russian \~russian
Этот код демонстрирует простую конфигурируемую программу, которая может быть запущена с Этот код демонстрирует простую конфигурируемую программу, которая может быть запущена с
консолью или без неё, с отладочным выводом или без. \b MainClass — центральный класс, который This code demonstrates simple interactive configurable program, which can be started with console
также может быть унаследован от \a PIThread с переопределением \a run(). display or not, and with debug or not. \b MainClass is central class that also can be inherited from
\n У многих классов PIP есть события и обработчики, которые можно связывать между собой. \a PIThread and reimplement \a run() function.
Подробности — на странице \a PIObject (\ref PIObject_sec0). \n Many PIP classes has events and event handlers, which can be connected one to another.
\n Для настройки приложения из файла используйте \a PIConfig (см. \ref config). Details you can see at \a PIObject reference page (\ref PIObject_sec0).
\n Дополнительные темы — на странице \ref using_advanced. \n To configure your program from file use \a PIConfig.

View File

@@ -17,6 +17,7 @@ list(APPEND COMPONENT_ADD_INCLUDEDIRS "../libs/main/thread")
set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spi_flash libsodium) set(COMPONENT_PRIV_REQUIRES pthread lwip freertos vfs spi_flash libsodium)
register_component() register_component()
set(PIP_FREERTOS ON) set(PIP_FREERTOS ON)
set(PIP_MICRO ON)
set(LIB OFF) set(LIB OFF)
set(INCLUDE_DIRS ${IDF_INCLUDE_DIRECTORIES}) set(INCLUDE_DIRS ${IDF_INCLUDE_DIRECTORIES})
list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/newlib/platform_include) list(APPEND INCLUDE_DIRS $ENV{IDF_PATH}/components/newlib/platform_include)

View File

@@ -72,7 +72,11 @@ PIClientServer::Server::~Server() {
clean_thread->waitForFinish(); clean_thread->waitForFinish();
piDeleteSafety(clean_thread); piDeleteSafety(clean_thread);
stopServer(); stopServer();
closeAll(); for (auto c: clients) {
c->aboutDelete();
c->destroy();
delete c;
}
piDeleteSafety(tcp_server); piDeleteSafety(tcp_server);
} }

View File

@@ -0,0 +1,35 @@
/*
PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piscreenconsole.h"
using namespace PIScreenTypes;
TileVars::TileVars(const PIString & n): PIScreenTile(n) {
alignment = Left;
}
void TileVars::sizeHint(int & w, int & h) const {}
void TileVars::drawEvent(PIScreenDrawer * d) {}
PIScreenConsoleTile::PIScreenConsoleTile() {}

View File

@@ -59,7 +59,7 @@ bool PIHTTPClient::init() {
if (is_cancel) return false; if (is_cancel) return false;
CurlThreadPool::instance(); CurlThreadPool::instance();
if (!PRIVATE->init()) return false; if (!PRIVATE->init()) return false;
auto ait = request.queryArguments().makeIterator(); auto ait = request.arguments().makeIterator();
while (ait.next()) { while (ait.next()) {
if (!url.contains('?')) if (!url.contains('?'))
url.append('?'); url.append('?');
@@ -93,7 +93,6 @@ bool PIHTTPClient::init() {
// curl_easy_setopt(PRIVATE->handle, CURLOPT_VERBOSE, 1L); // curl_easy_setopt(PRIVATE->handle, CURLOPT_VERBOSE, 1L);
// curl_easy_setopt(PRIVATE->handle, CURLOPT_ERRORBUFFER, buffer_error.data()); // curl_easy_setopt(PRIVATE->handle, CURLOPT_ERRORBUFFER, buffer_error.data());
curl_easy_setopt(PRIVATE->handle, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(PRIVATE->handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(PRIVATE->handle, CURLOPT_SSL_VERIFYHOST, ignore_ssl_errors ? 0L : 1L);
if (request.body().isNotEmpty()) { if (request.body().isNotEmpty()) {
curl_easy_setopt(PRIVATE->handle, CURLOPT_UPLOAD, 1L); curl_easy_setopt(PRIVATE->handle, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(PRIVATE->handle, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(request.body().size())); curl_easy_setopt(PRIVATE->handle, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(request.body().size()));
@@ -247,7 +246,7 @@ PIHTTPClient * PIHTTPClient::onFinish(std::function<void()> f) {
PIHTTPClient * PIHTTPClient::onFinish(std::function<void(const PIHTTP::MessageConst &)> f) { PIHTTPClient * PIHTTPClient::onFinish(std::function<void(const PIHTTP::MessageConst &)> f) {
on_finish = std::move(f); on_finish = f;
return this; return this;
} }
@@ -258,7 +257,7 @@ PIHTTPClient * PIHTTPClient::onError(std::function<void()> f) {
PIHTTPClient * PIHTTPClient::onError(std::function<void(const PIHTTP::MessageConst &)> f) { PIHTTPClient * PIHTTPClient::onError(std::function<void(const PIHTTP::MessageConst &)> f) {
on_error = std::move(f); on_error = f;
return this; return this;
} }
@@ -269,13 +268,7 @@ PIHTTPClient * PIHTTPClient::onAbort(std::function<void()> f) {
PIHTTPClient * PIHTTPClient::onAbort(std::function<void(const PIHTTP::MessageConst &)> f) { PIHTTPClient * PIHTTPClient::onAbort(std::function<void(const PIHTTP::MessageConst &)> f) {
on_abort = std::move(f); on_abort = f;
return this;
}
PIHTTPClient * PIHTTPClient::ignoreSSLErrors() {
ignore_ssl_errors = true;
return this; return this;
} }

View File

@@ -45,7 +45,7 @@ bool PIHTTPServer::registerPath(const PIString & path, PIHTTP::Method method, Re
Endpoint ep; Endpoint ep;
if (!ep.create(path)) return false; if (!ep.create(path)) return false;
ep.method = method; ep.method = method;
ep.function = std::move(functor); ep.function = functor;
endpoints[ep.priority] << ep; endpoints[ep.priority] << ep;
return true; return true;
} }

View File

@@ -1,13 +1,3 @@
/*! \file piapplicationmodule.h
* \ingroup Application
* \~\brief
* \~english Application-level classes.
* \~russian Классы уровня "приложение".
*
* \~\details
* \~english Includes the public CLI, logging, single-application, system monitoring, and translation headers.
* \~russian Подключает публичные заголовки CLI, логирования, одиночного приложения, системного мониторинга и перевода.
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -40,14 +30,14 @@
//! target_link_libraries([target] PIP) //! target_link_libraries([target] PIP)
//! \endcode //! \endcode
//! //!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english //! \~english
//! This umbrella header includes public Application classes for command-line //! These files provides some classes for help to create application
//! parsing, logging, single-instance control, process monitoring and translation.
//! //!
//! \~russian //! \~russian
//! Этот зонтичный заголовок подключает публичные классы Application для //! Эти файлы предоставляют классы для облегчения создания приложения
//! разбора командной строки, ведения лога, контроля одного экземпляра,
//! мониторинга процесса и перевода.
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -1,8 +1,9 @@
//! \~\file picli.h /*! \file picli.h
//! \~\ingroup Application * \ingroup Application
//! \brief * \~\brief
//! \~english Command-line argument parser * \~english Command-Line parser
//! \~russian Парсер аргументов командной строки * \~russian Парсер командной строки
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Command-Line Parser Command-Line Parser
@@ -28,15 +29,10 @@
#include "piset.h" #include "piset.h"
#include "pistringlist.h" #include "pistringlist.h"
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english Command-line argument parser class //! \~english Command-Line parser.
//! \~russian Класс парсера аргументов командной строки //! \~russian Парсер командной строки.
//! \details
//! \~english The PICLI class provides convenient parsing of command-line arguments. It supports short keys (e.g., -c), full keys (e.g.,
//! --console), and arguments with/without values.
//! \~russian Класс PICLI предоставляет удобный разбор аргументов командной строки. Поддерживаются короткие ключи (например, -c), полные
//! ключи (например, --console) и аргументы с значениями/без значений.
class PIP_EXPORT PICLI { class PIP_EXPORT PICLI {
public: public:
//! \~english Constructs %PICLI from "argc" and "argv" from "int main()" method. //! \~english Constructs %PICLI from "argc" and "argv" from "int main()" method.
@@ -68,25 +64,13 @@ 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 positional argument by index.
//! \~russian Возвращает обязательный позиционный аргумент по индексу.
PIString mandatoryArgument(int index); PIString mandatoryArgument(int index);
//! \~english Returns optional positional argument by index.
//! \~russian Возвращает необязательный позиционный аргумент по индексу.
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 all mandatory positional arguments.
//! \~russian Возвращает все обязательные позиционные аргументы.
const PIStringList & mandatoryArguments(); const PIStringList & mandatoryArguments();
//! \~english Returns all optional positional arguments.
//! \~russian Возвращает все необязательные позиционные аргументы.
const PIStringList & optionalArguments(); const PIStringList & optionalArguments();
//! \~english Returns program execute command without arguments. //! \~english Returns program execute command without arguments.
@@ -109,52 +93,18 @@ public:
//! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет. //! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет.
PIString argumentFullKey(const PIString & name); PIString argumentFullKey(const PIString & name);
//! \~english Returns prefix used for short keys.
//! \~russian Возвращает префикс коротких ключей.
const PIString & shortKeyPrefix() const { return _prefix_short; } const PIString & shortKeyPrefix() const { return _prefix_short; }
//! \~english Returns prefix used for full keys.
//! \~russian Возвращает префикс полных ключей.
const PIString & fullKeyPrefix() const { return _prefix_full; } const PIString & fullKeyPrefix() const { return _prefix_full; }
//! \~english Returns expected count of mandatory positional arguments.
//! \~russian Возвращает ожидаемое количество обязательных позиционных аргументов.
int mandatoryArgumentsCount() const { return _count_mand; } int mandatoryArgumentsCount() const { return _count_mand; }
//! \~english Returns expected count of optional positional arguments.
//! \~russian Возвращает ожидаемое количество необязательных позиционных аргументов.
int optionalArgumentsCount() const { return _count_opt; } int optionalArgumentsCount() const { return _count_opt; }
//! \~english Sets prefix used for short keys such as "-d".
//! \~russian Устанавливает префикс коротких ключей, например "-d".
void setShortKeyPrefix(const PIString & prefix); void setShortKeyPrefix(const PIString & prefix);
//! \~english Sets prefix used for full keys such as "--debug".
//! \~russian Устанавливает префикс полных ключей, например "--debug".
void setFullKeyPrefix(const PIString & prefix); void setFullKeyPrefix(const PIString & prefix);
//! \~english Sets count of mandatory positional arguments collected before optional ones.
//! \~russian Устанавливает количество обязательных позиционных аргументов, собираемых до необязательных.
void setMandatoryArgumentsCount(const int count); void setMandatoryArgumentsCount(const int count);
//! \~english Sets count of optional positional arguments. Negative value means unlimited.
//! \~russian Устанавливает количество необязательных позиционных аргументов. Отрицательное значение означает без ограничения.
void setOptionalArgumentsCount(const int count); void setOptionalArgumentsCount(const int count);
//! \~english Returns debug mode flag.
//! \~russian Возвращает флаг режима отладки.
bool debug() const { return debug_; } bool debug() const { return debug_; }
//! \~english Enables or disables debug mode.
//! \~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 human-readable object name.
//! \~russian Возвращает читаемое имя объекта.
PIString name() const { return PIStringAscii("CLI"); } PIString name() const { return PIStringAscii("CLI"); }
private: private:

View File

@@ -1,8 +1,9 @@
//! \~\file pilog.h /*! \file pilog.h
//! \~\ingroup Application * \ingroup Application
//! \~\brief * \~\brief
//! \~english High-level log * \~english High-level log
//! \~russian Высокоуровневый лог * \~russian Высокоуровневый лог
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
High-level log High-level log
@@ -29,23 +30,15 @@
#include "piiostream.h" #include "piiostream.h"
#include "pithread.h" #include "pithread.h"
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english High-level log //! \~english High-level log
//! \~russian Высокоуровневый лог //! \~russian Высокоуровневый лог
//! \~\details
//! \~english Provides log with optional file and console output, with configurable timestamp format and line format.
//! \~russian Предоставляет лог с опциональным выводом в файл и консоль, с настраиваемым форматом метки времени и форматом строки.
class PIP_EXPORT PILog: public PIThread { class PIP_EXPORT PILog: public PIThread {
PIOBJECT_SUBCLASS(PILog, PIThread) PIOBJECT_SUBCLASS(PILog, PIThread)
public: public:
//! \~english Constructs log with console output, timestamped lines and rotated log files.
//! \~russian Создает лог с выводом в консоль, строками с метками времени и ротацией файлов.
PILog(); PILog();
//! \~english Stops logging thread and flushes queued messages.
//! \~russian Останавливает поток логирования и дописывает сообщения из очереди.
~PILog(); ~PILog();
//! \~english Message category //! \~english Message category
@@ -65,8 +58,8 @@ public:
All /** \~english All \~russian Все */ = 0xFF, All /** \~english All \~russian Все */ = 0xFF,
}; };
//! \~english Enables or disables output channel "o". //! \~english Set output channel \"o\" to \"on\".
//! \~russian Включает или выключает канал вывода "o". //! \~russian Установить канал вывода \"o\" в \"on\".
void setOutput(Output o, bool on = true) { output.setFlag(o, on); } void setOutput(Output o, bool on = true) { output.setFlag(o, on); }
//! \~english Returns prefix for filename. //! \~english Returns prefix for filename.
@@ -87,7 +80,7 @@ public:
//! \~english Returns directory for log files. //! \~english Returns directory for log files.
//! \~russian Возвращает директорию файлов лога. //! \~russian Возвращает директорию для файлов.
PIString dir() const { return log_dir; } PIString dir() const { return log_dir; }
//! \~english Set directory for log files. Should be set \b after \a setLogName()! //! \~english Set directory for log files. Should be set \b after \a setLogName()!
@@ -99,8 +92,8 @@ public:
//! \~russian Возвращает время жизни файла. //! \~russian Возвращает время жизни файла.
PISystemTime fileSplitTime() const { return split_time; } PISystemTime fileSplitTime() const { return split_time; }
//! \~english Sets log file rotation interval. A new file is created every "st". //! \~english Set lifetime for file. Each "st" interval new file will be created.
//! \~russian Устанавливает интервал ротации файла лога. Новый файл создается каждые "st". //! \~russian Устанавливает время жизни файла. Каждый интервал "st" будет создан новый файл.
void setFileSplitTime(PISystemTime st) { split_time = st; } void setFileSplitTime(PISystemTime st) { split_time = st; }
@@ -117,8 +110,8 @@ public:
//! \~russian Возвращает формат строки. //! \~russian Возвращает формат строки.
PIString lineFormat() const { return line_format; } PIString lineFormat() const { return line_format; }
//! \~english Sets line format. "t" is timestamp, "c" is category and "m" is message. Default is "t - c: m". //! \~english Set line format. "t" is timestamp, "c" is category and "m" is message. Default is "t - c: m".
//! \~russian Устанавливает формат строки. "t" - метка времени, "c" - категория, "m" - сообщение. По умолчанию "t - c: m". //! \~russian Устанавливает формат строки. "t" - метка времени, "c" - категория и "m" - сообщение. По умолчанию "t - c: m".
void setLineFormat(const PIString & f); void setLineFormat(const PIString & f);
@@ -126,8 +119,9 @@ public:
//! \~russian Возвращает максимальную категорию. //! \~russian Возвращает максимальную категорию.
Level level() const { return max_level; } Level level() const { return max_level; }
//! \~english Sets maximum accepted level. Messages above "l" are ignored. Default is \a Level::Debug. //! \~english Set maximum level. All levels greater than \"l\" will be ignored. Default is \a Level::Debug.
//! \~russian Устанавливает максимальный принимаемый уровень. Сообщения выше "l" игнорируются. По умолчанию \a Level::Debug. //! \~russian Устанавливает максимальную категорию. Все сообщения с большей категорией, чем \"l\", будут игнорироваться. По умолчанию \a
//! Level::Debug.
void setLevel(Level l); void setLevel(Level l);
//! \~english Returns \a PICout for \a Level::Error level. //! \~english Returns \a PICout for \a Level::Error level.
@@ -146,12 +140,12 @@ public:
//! \~russian Возвращает \a PICout для категории \a Level::Debug. //! \~russian Возвращает \a PICout для категории \a Level::Debug.
PICout debug(PIObject * context = nullptr); PICout debug(PIObject * context = nullptr);
//! \~english Writes all queued lines and stops logging. Also called from destructor. //! \~english Write all queued lines and stop. Also called in destructor.
//! \~russian Записывает все строки из очереди и останавливает логирование. Также вызывается из деструктора. //! \~russian Записывает все строки из очереди и останавливается. Также вызывается в деструкторе.
void stop(); void stop();
//! \~english Reads all rotated and current log lines and returns them as %PIStringList. //! \~english Read all previous and current log content and returns them as %PIStringList.
//! \~russian Читает строки из текущего и уже ротированных логов и возвращает их как %PIStringList. //! \~russian Читает все предыдущие и текущий логи и возвращает их как %PIStringList.
PIStringList readAllLogs() const; PIStringList readAllLogs() const;
private: private:

View File

@@ -1,8 +1,9 @@
//! \~\file pisingleapplication.h /*! \file pisingleapplication.h
//! \~\ingroup Application * \ingroup Application
//! \~\brief * \~\brief
//! \~english Single-instance application control * \~english Single-instance application control
//! \~russian Контроль одного экземпляра приложения * \~russian Контроль одного экземпляра приложения
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Single application Single application
@@ -29,44 +30,35 @@
class PISharedMemory; class PISharedMemory;
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english Single-instance application control. //! \~english Single-instance application control.
//! \~russian Контроль одного экземпляра приложения. //! \~russian Контроль одного экземпляра приложения.
//! \~\details
//! \~english The PISingleApplication class provides single-instance application control. It allows detecting if the current application
//! instance is the first one launched and enables inter-process communication between multiple instances. Multiple instances with the same
//! "app_name" can detect each other and communicate. The first instance becomes the server, receiving messages from subsequent instances.
//! \~russian Класс PISingleApplication предоставляет контроль одного экземпляра приложения. Он позволяет определить, является ли текущий
//! экземпляр первым запущенным, и обеспечивает межпроцессное взаимодействие между несколькими экземплярами. Несколько экземпляров с
//! одинаковым "app_name" могут обнаруживать друг друга и обмениваться сообщениями. Первый экземпляр становится сервером, принимающим
//! сообщения от последующих экземпляров.
class PIP_EXPORT PISingleApplication: public PIThread { class PIP_EXPORT PISingleApplication: public PIThread {
PIOBJECT_SUBCLASS(PISingleApplication, PIThread); PIOBJECT_SUBCLASS(PISingleApplication, PIThread);
public: public:
//! \~english Constructs %PISingleApplication for application name "app_name". //! \~english Construct %PISingleApplication with name "app_name"
//! \~russian Создает %PISingleApplication для имени приложения "app_name". //! \~russian Создает %PISingleApplication с именем "app_name"
PISingleApplication(const PIString & app_name = PIString()); PISingleApplication(const PIString & app_name = PIString());
//! \~english Stops instance monitoring and releases shared resources.
//! \~russian Останавливает мониторинг экземпляра и освобождает общие ресурсы.
~PISingleApplication(); ~PISingleApplication();
//! \~english Returns whether this process is the first launched instance. //! \~english Returns if this application instance is launched first
//! \~russian Возвращает, является ли этот процесс первым запущенным экземпляром. //! \~russian Возвращает первым ли был запущен этот экземпляр приложения
bool isFirst() const; bool isFirst() const;
EVENT_HANDLER1(void, sendMessage, const PIByteArray &, m);
EVENT1(messageReceived, PIByteArray, m);
//! \handlers //! \handlers
//! \{ //! \{
//! \fn void sendMessage(const PIByteArray & m) //! \fn void sendMessage(const PIByteArray & m)
//! \brief //! \brief
//! \~english Sends message "m" to the first launched application instance //! \~english Send message "m" to first launched application
//! \~russian Посылает сообщение "m" первому запущенному экземпляру приложения //! \~russian Посылает сообщение "m" первому запущеному приложению
EVENT_HANDLER1(void, sendMessage, const PIByteArray &, m);
//! \} //! \}
//! \events //! \events
@@ -74,9 +66,8 @@ public:
//! \fn void messageReceived(PIByteArray m) //! \fn void messageReceived(PIByteArray m)
//! \brief //! \brief
//! \~english Emitted by the first launched application when receiving a message from another instance //! \~english Raise on first launched application receive message from another
//! \~russian Вызывается первым запущенным приложением при получении сообщения от другого экземпляра //! \~russian Вызывается первым запущеным приложением по приему сообщения от других
EVENT1(messageReceived, PIByteArray, m);
//! \} //! \}

View File

@@ -178,6 +178,9 @@ PISystemTime uint64toST(uint64_t v) {
void PISystemMonitor::run() { void PISystemMonitor::run() {
cur_tm.clear(); cur_tm.clear();
tbid.clear(); tbid.clear();
ProcessStats tstat;
tstat.ID = pID_;
#ifndef PIP_NO_THREADS
__PIThreadCollection * pitc = __PIThreadCollection::instance(); __PIThreadCollection * pitc = __PIThreadCollection::instance();
pitc->lock(); pitc->lock();
PIVector<PIThread *> tv = pitc->threads(); PIVector<PIThread *> tv = pitc->threads();
@@ -185,12 +188,10 @@ void PISystemMonitor::run() {
if (t->isPIObject()) tbid[t->tid()] = t->name(); if (t->isPIObject()) tbid[t->tid()] = t->name();
pitc->unlock(); pitc->unlock();
// piCout << tbid.keys().toType<uint>(); // piCout << tbid.keys().toType<uint>();
ProcessStats tstat; # ifdef FREERTOS
tstat.ID = pID_;
#ifdef MICRO_PIP
for (auto * t: tv) for (auto * t: tv)
if (t->isPIObject()) gatherThread(t->tid()); if (t->isPIObject()) gatherThread(t->tid());
#else # else // FREERTOS
# ifndef WINDOWS # ifndef WINDOWS
double delay_ms = delay_.toMilliseconds(); double delay_ms = delay_.toMilliseconds();
tbid[pID_] = "main"; tbid[pID_] = "main";
@@ -210,7 +211,7 @@ void PISystemMonitor::run() {
tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms; tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms;
cycle = 0; cycle = 0;
// piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms; // piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms;
# else # else // MAC_OS
PRIVATE->file.seekToBegin(); PRIVATE->file.seekToBegin();
PIString str = PIString::fromAscii(PRIVATE->file.readAll()); PIString str = PIString::fromAscii(PRIVATE->file.readAll());
int si = str.find('(') + 1, fi = 0, cc = 1; int si = str.find('(') + 1, fi = 0, cc = 1;
@@ -264,8 +265,8 @@ void PISystemMonitor::run() {
if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot]) continue; if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot]) continue;
gatherThread(i.name().toInt()); gatherThread(i.name().toInt());
} }
# endif # endif // MAC_OS
# else # else // WINDOWS
if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) { if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) {
tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize; tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize;
} }
@@ -315,8 +316,9 @@ void PISystemMonitor::run() {
tstat.cpu_load_user = 0.f; tstat.cpu_load_user = 0.f;
} }
PRIVATE->tm.reset(); PRIVATE->tm.reset();
# endif # endif // WINDOWS
#endif # endif // FREERTOS
#endif // PIP_NO_THREADS
tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f); tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f);
tstat.cpu_load_user = piClampf(tstat.cpu_load_user, 0.f, 100.f); tstat.cpu_load_user = piClampf(tstat.cpu_load_user, 0.f, 100.f);

View File

@@ -1,8 +1,9 @@
//! \~\file pisystemmonitor.h /*! \file pisystemmonitor.h
//! \~\ingroup Application * \ingroup Application
//! \brief * \~\brief
//! \~english System resources monitoring * \~english System resources monitoring
//! \~russian Мониторинг ресурсов системы * \~russian Мониторинг ресурсов системы
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Process resource monitor Process resource monitor
@@ -29,30 +30,23 @@
#include "pithread.h" #include "pithread.h"
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english Process and thread resource monitoring. //! \~english Process monitoring.
//! \~russian Мониторинг ресурсов процесса и его потоков. //! \~russian Мониторинг процесса.
//! \details
//! \~english This module provides process and system resource monitoring capabilities including CPU usage, memory consumption, and thread
//! statistics. It supports cross-platform monitoring on Linux, Windows, macOS, and ESP platforms.
//! \~russian Этот модуль предоставляет возможности мониторинга ресурсов процессов и системы, включая использование CPU, потребление памяти
//! и статистику потоков. Поддерживается кроссплатформенный мониторинг на Linux, Windows, macOS и ESP платформах.
class PIP_EXPORT PISystemMonitor: public PIThread { class PIP_EXPORT PISystemMonitor: public PIThread {
PIOBJECT_SUBCLASS(PISystemMonitor, PIThread); PIOBJECT_SUBCLASS(PISystemMonitor, PIThread);
friend class PIIntrospectionServer; friend class PIIntrospectionServer;
public: public:
//! \~english Constructs unassigned %PISystemMonitor. //! \~english Constructs unassigned %PISystemMonitor
//! \~russian Создает непривязанный %PISystemMonitor. //! \~russian Создает непривязанный %PISystemMonitor
PISystemMonitor(); PISystemMonitor();
//! \~english Stops monitoring and detaches from the current process target.
//! \~russian Останавливает мониторинг и отсоединяет объект от текущей цели.
~PISystemMonitor(); ~PISystemMonitor();
#pragma pack(push, 1) #pragma pack(push, 1)
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english Process statistics (fixed-size fields). //! \~english Process statistics (fixed-size fields).
//! \~russian Статистика процесса (фиксированные поля). //! \~russian Статистика процесса (фиксированные поля).
@@ -101,16 +95,16 @@ public:
//! \~russian Память данных в байтах //! \~russian Память данных в байтах
ullong data_memsize = 0; ullong data_memsize = 0;
//! \~english Total RAM in bytes. //! \~english
//! \~russian Общий объем RAM в байтах. //! \~russian
ullong ram_total = 0; ullong ram_total = 0;
//! \~english Free RAM in bytes. //! \~english
//! \~russian Свободный объем RAM в байтах. //! \~russian
ullong ram_free = 0; ullong ram_free = 0;
//! \~english Used RAM in bytes. //! \~english
//! \~russian Используемый объем RAM в байтах. //! \~russian
ullong ram_used = 0; ullong ram_used = 0;
//! \~english CPU load in kernel space //! \~english CPU load in kernel space
@@ -122,7 +116,7 @@ public:
float cpu_load_user = 0.f; float cpu_load_user = 0.f;
}; };
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english Thread statistics (fixed-size fields). //! \~english Thread statistics (fixed-size fields).
//! \~russian Статистика потока (фиксированные поля). //! \~russian Статистика потока (фиксированные поля).
@@ -157,13 +151,13 @@ public:
}; };
#pragma pack(pop) #pragma pack(pop)
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english Process statistics. //! \~english Process statistics.
//! \~russian Статистика процесса. //! \~russian Статистика процесса.
struct PIP_EXPORT ProcessStats: ProcessStatsFixed { struct PIP_EXPORT ProcessStats: ProcessStatsFixed {
//! \~english Fills human-readable memory size fields. //! \~english Fill human-readable fields
//! \~russian Заполняет поля с человекочитаемыми размерами памяти. //! \~russian Заполнить читаемые поля
void makeStrings(); void makeStrings();
//! \~english Execution command //! \~english Execution command
@@ -195,7 +189,7 @@ public:
PIString data_memsize_readable; PIString data_memsize_readable;
}; };
//! \~\ingroup Application //! \ingroup Application
//! \~\brief //! \~\brief
//! \~english Thread statistics. //! \~english Thread statistics.
//! \~russian Статистика потока. //! \~russian Статистика потока.
@@ -207,59 +201,51 @@ public:
#ifndef MICRO_PIP #ifndef MICRO_PIP
//! \~english Starts monitoring the process with PID "pID" using the given update interval. //! \~english Starts monitoring of process with PID "pID" and update interval "interval_ms" milliseconds
//! \~russian Запускает мониторинг процесса с PID "pID" с указанным интервалом обновления. //! \~russian Начинает мониторинг процесса с PID "pID" и интервалом обновления "interval_ms" миллисекунд
bool startOnProcess(int pID, PISystemTime interval = PISystemTime::fromSeconds(1.)); bool startOnProcess(int pID, PISystemTime interval = PISystemTime::fromSeconds(1.));
#endif #endif
//! \~english Starts monitoring the current application process. //! \~english Starts monitoring of application process with update interval "interval_ms" milliseconds
//! \~russian Запускает мониторинг текущего процесса приложения. //! \~russian Начинает мониторинг процесса приложения с интервалом обновления "interval_ms" миллисекунд
bool startOnSelf(PISystemTime interval = PISystemTime::fromSeconds(1.)); bool startOnSelf(PISystemTime interval = PISystemTime::fromSeconds(1.));
//! \~english Stops monitoring. //! \~english Stop monitoring
//! \~russian Останавливает мониторинг. //! \~russian Останавливает мониторинг
void stop(); void stop();
//! \~english Returns PID of the monitored process. //! \~english Returns monitoring process PID
//! \~russian Возвращает PID наблюдаемого процесса. //! \~russian Возвращает PID наблюдаемого процесса
int pID() const { return pID_; } int pID() const { return pID_; }
//! \~english Returns latest process statistics snapshot. //! \~english Returns monitoring process statistics
//! \~russian Возвращает последний снимок статистики процесса. //! \~russian Возвращает статистику наблюдаемого процесса
ProcessStats statistic() const; ProcessStats statistic() const;
//! \~english Returns latest per-thread statistics snapshot. //! \~english Returns monitoring process threads statistics
//! \~russian Возвращает последний снимок статистики по потокам. //! \~russian Возвращает статистику потоков наблюдаемого процесса
PIVector<ThreadStats> threadsStatistic() const; PIVector<ThreadStats> threadsStatistic() const;
//! \~english Replaces current process statistics with external data.
//! \~russian Заменяет текущую статистику процесса внешними данными.
void setStatistic(const ProcessStats & s); void setStatistic(const ProcessStats & s);
//! \~english Returns total RAM in bytes on supported platforms. //! \~english
//! \~russian Возвращает общий объем RAM в байтах на поддерживаемых платформах. //! \~russian
static ullong totalRAM(); static ullong totalRAM();
//! \~english Returns free RAM in bytes on supported platforms. //! \~english
//! \~russian Возвращает свободный объем RAM в байтах на поддерживаемых платформах. //! \~russian
static ullong freeRAM(); static ullong freeRAM();
//! \~english Returns used RAM in bytes on supported platforms. //! \~english
//! \~russian Возвращает используемый объем RAM в байтах на поддерживаемых платформах. //! \~russian
static ullong usedRAM(); static ullong usedRAM();
//! \~\events //! \~english
//! \~\{ //! \~russian
//! \~\fn void measured()
//! \~english Raised after a new statistics snapshot is measured.
//! \~russian Вызывается после измерения нового снимка статисти
EVENT(measured); EVENT(measured);
//! \~\}
private: private:
void run() override; void run() override;
void gatherThread(llong id); void gatherThread(llong id);

View File

@@ -1,8 +1,9 @@
//! \~\file pitranslator.h /*! \file pitranslator.h
//! \~\ingroup Application * \ingroup Application
//! \brief * \~\brief
//! \~english Translation support * \~english Translation support
//! \~russian Поддержка перевода * \~russian Поддержка перевода
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Translation support Translation support
@@ -28,74 +29,24 @@
#include "pistring.h" #include "pistring.h"
#ifdef DOXYGEN #define piTr PITranslator::tr
#define piTrNoOp PITranslator::trNoOp
//! \relatesalso PITranslator //! \ingroup Application
//! \~\brief
//! \~english Alias to \a PITranslator::tr().
//! \~russian Алиас к \a PITranslator::tr().
# define piTr
//! \relatesalso PITranslator
//! \~\brief
//! \~english Alias to \a PITranslator::trNoOp().
//! \~russian Алиас к \a PITranslator::trNoOp().
# define piTrNoOp
#else
# define piTr PITranslator::tr
# define piTrNoOp PITranslator::trNoOp
#endif
//! \~\ingroup Application
//! \~\brief //! \~\brief
//! \~english Translation support //! \~english Translation support
//! \~russian Поддержка перевода //! \~russian Поддержка перевода
//! \~\details
//! \~english Provides translation support with context-aware string wrappers and multiple loading methods.
//! %PITranslator stores loaded translations in a process-wide singleton.
//! If translation or context is missing, the source string is returned unchanged.
//! \~russian Предоставляет поддержку перевода с контекстно-зависимыми обертками строк и методами загрузки.
//! %PITranslator хранит загруженные переводы в синглтоне процесса.
//! Если перевод или контекст не найдены, исходная строка возвращается без изменений.
class PIP_EXPORT PITranslator { class PIP_EXPORT PITranslator {
public: public:
//! \~english Returns translated string for "in" in optional "context".
//! \~russian Возвращает перевод строки "in" в необязательном "context".
static PIString tr(const PIString & in, const PIString & context = {}); static PIString tr(const PIString & in, const PIString & context = {});
//! \~english Converts UTF-8 string literal to %PIString and translates it.
//! \~russian Преобразует UTF-8 строковый литерал в %PIString и переводит его.
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 Marks string for translation-aware code paths and returns it unchanged.
//! \~russian Помечает строку для кода, работающего с переводом, и возвращает ее без изменений.
static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; } static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; }
//! \~english UTF-8 overload of \a trNoOp().
//! \~russian UTF-8 перегрузка для \a trNoOp().
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 Clears current translations and loads language files matching "short_lang" from "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 translations from textual configuration content.
//! \~russian Загружает переводы из текстового конфигурационного содержимого.
static void loadConfig(const PIString & content); static void loadConfig(const PIString & content);
//! \~english Loads translations from binary content in PIP translation format.
//! \~russian Загружает переводы из бинарного содержимого в формате переводов PIP.
static bool load(const PIByteArray & content); static bool load(const PIByteArray & content);
//! \~english Loads translations from file and checks its translation header.
//! \~russian Загружает переводы из файла и проверяет его заголовок переводов.
static bool loadFile(const PIString & path); static bool loadFile(const PIString & path);
private: private:
@@ -108,24 +59,10 @@ private:
}; };
//! \~\ingroup Application
//! \~\brief
//! \~english Context-aware string wrapper that automatically translates strings using PITranslator::tr().
//! Helper returned by \a operator""_tr for optional-context translation.
//! \~russian Контекстно-зависимая обертка строки, автоматически переводящая строки с помощью PITranslator::tr().
//! Вспомогательный тип, возвращаемый \a operator""_tr для перевода с необязательным контекстом.
class PIStringContextTr { class PIStringContextTr {
public: public:
//! \~english Stores source string for later translation.
//! \~russian Сохраняет исходную строку для последующего перевода.
PIStringContextTr(PIString && s): _s(s) {} PIStringContextTr(PIString && s): _s(s) {}
//! \~english Translates stored string without explicit context.
//! \~russian Переводит сохраненную строку без явного контекста.
operator PIString() const { return PITranslator::tr(_s); } operator PIString() const { return PITranslator::tr(_s); }
//! \~english Translates stored string in context "ctx".
//! \~russian Переводит сохраненную строку в контексте "ctx".
PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); } PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); }
private: private:
@@ -133,24 +70,10 @@ private:
}; };
//! \~\ingroup Application
//! \~\brief
//! \~english Context-aware string wrapper that preserves original strings without translation (no-op).
//! Helper returned by \a operator""_trNoOp that keeps source text unchanged.
//! \~russian Контекстно-зависимая обертка строки, сохраняющая оригинальные строки без перевода (заглушка).
//! Вспомогательный тип, возвращаемый \a operator""_trNoOp, который сохраняет исходный текст без изменений.
class PIStringContextTrNoOp { class PIStringContextTrNoOp {
public: public:
//! \~english Stores source string without translating it.
//! \~russian Сохраняет исходную строку без перевода.
PIStringContextTrNoOp(PIString && s): _s(s) {} PIStringContextTrNoOp(PIString && s): _s(s) {}
//! \~english Returns stored string unchanged.
//! \~russian Возвращает сохраненную строку без изменений.
operator PIString() const { return _s; } operator PIString() const { return _s; }
//! \~english Returns stored string unchanged and ignores "ctx".
//! \~russian Возвращает сохраненную строку без изменений и игнорирует "ctx".
PIString operator()(const PIString & ctx = {}) const { return _s; } PIString operator()(const PIString & ctx = {}) const { return _s; }
private: private:
@@ -159,17 +82,15 @@ private:
//! \~\brief //! \~\brief
//! \~english User-defined literal that defers translation through \a PITranslator::tr(). //! \~english Translate string with \a PITranslator::tr()
//! \~russian Пользовательский литерал, откладывающий перевод через \a PITranslator::tr(). //! \~russian Перевести строку с помощью \a PITranslator::tr()
//! \~\code "hello"_tr \endcode
inline PIStringContextTr operator""_tr(const char * v, size_t sz) { inline PIStringContextTr operator""_tr(const char * v, size_t sz) {
return PIStringContextTr(PIString::fromUTF8(v, sz)); return PIStringContextTr(PIString::fromUTF8(v, sz));
} }
//! \~\brief //! \~\brief
//! \~english User-defined literal that keeps source text unchanged via \a PITranslator::trNoOp(). //! \~english Translate string with \a PITranslator::tr()
//! \~russian Пользовательский литерал, сохраняющий исходный текст без изменений через \a PITranslator::trNoOp(). //! \~russian Перевести строку с помощью \a PITranslator::tr()
//! \~\code "hello"_trNoOp \endcode
inline PIStringContextTrNoOp operator""_trNoOp(const char * v, size_t sz) { inline PIStringContextTrNoOp operator""_trNoOp(const char * v, size_t sz) {
return PIStringContextTrNoOp(PIString::fromUTF8(v, sz)); return PIStringContextTrNoOp(PIString::fromUTF8(v, sz));
} }

View File

@@ -1,8 +1,9 @@
//! \~\file piclientserver_client.h /*! \file piclientserver_client.h
//! \~\ingroup ClientServer * \ingroup ClientServer
//! \brief * \~\brief
//! \~english Client-side and server-side client connection classes * \~english
//! \~russian Классы клиентского подключения и серверного представления клиента * \~russian
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -32,27 +33,18 @@ namespace PIClientServer {
// ServerClient // ServerClient
//! \~\ingroup ClientServer //! ~english Server-side client implementation
//! \~\brief //! ~russian Серверная реализация клиента
//! \~english Server-side representation of one accepted client connection.
//! \~russian Серверное представление одного принятого клиентского соединения.
//! \details
//! \~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 Constructs an unbound server-side client object.
//! \~russian Создает непривязанный объект серверного клиента.
ServerClient() {} ServerClient() {}
protected: protected:
//! \~english Called right before the server deletes this client object. //! ~english Called before client destruction
//! \~russian Вызывается непосредственно перед удалением этого объекта сервером. //! ~russian Вызывается перед уничтожением клиента
virtual void aboutDelete() {} virtual void aboutDelete() {}
private: private:
@@ -62,28 +54,17 @@ private:
// Client // Client
//! \~\ingroup ClientServer //! ~english Client implementation for connecting to servers
//! \~\brief //! ~russian Клиентская реализация для подключения к серверам
//! \~english Active client connection that initiates a connection to a server.
//! \~russian Активное клиентское соединение, которое само подключается к серверу.
//! \details
//! \~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 Constructs a client ready to connect to a remote server.
//! \~russian Создает клиент, готовый к подключению к удаленному серверу.
Client(); Client();
//! \~english Destroys the client and closes its connection if needed.
//! \~russian Уничтожает клиента и при необходимости закрывает его соединение.
~Client(); ~Client();
//! \~english Connects to the server at address "addr". //! ~english Connects to specified server address
//! \~russian Подключается к серверу по адресу "addr". //! ~russian Подключается к указанному адресу сервера
void connect(PINetworkAddress addr); void connect(PINetworkAddress addr);
protected: protected:

View File

@@ -1,11 +1,9 @@
//! \~\file piclientserver_client_base.h /*! \file piclientserver_client_base.h
//! \~\ingroup ClientServer * \ingroup ClientServer
//! \brief * \~\brief
//! \~english Base class for client-server communication * \~english
//! \~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,93 +35,77 @@ namespace PIClientServer {
class Server; class Server;
//! \~\ingroup ClientServer class ClientInterface {};
//! \~\brief
//! \~english Base class for client and server-side client communication. Provides TCP connection management, diagnostics, and packet //! ~english Base class for client-server communication with diagnostics support
//! streaming capabilities. //! ~russian Базовый класс для клиент-серверного взаимодействия с поддержкой диагностики
//! \~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:
//! \~english Constructs a disconnected client connection object.
//! \~russian Создает объект клиентского соединения в отключенном состоянии.
ClientBase(); ClientBase();
//! \~english Destroys the client connection and releases owned resources.
//! \~russian Уничтожает клиентское соединение и освобождает связанные ресурсы.
virtual ~ClientBase(); virtual ~ClientBase();
//! ~english Gets underlying TCP connection
//! \~english Returns the underlying TCP transport object. //! ~russian Возвращает TCP-соединение
//! \~russian Возвращает базовый объект TCP-транспорта.
const PIEthernet * getTCP() const { return tcp; } const PIEthernet * getTCP() const { return tcp; }
//! \~english Closes the connection immediately. //! ~english Closes the connection
//! \~russian Немедленно закрывает соединение. //! ~russian Закрывает соединение
void close(); void close();
//! \~english Stops the connection workflow and waits until shutdown completes. //! ~english Gracefully stops and waits for completion
//! \~russian Останавливает работу соединения и ждет полного завершения. //! ~russian Плавно останавливает и ожидает завершения
void stopAndWait(); void stopAndWait();
//! \~english Sends raw payload bytes through the stream packer. //! ~english Writes byte array to the connection
//! \~russian Отправляет сырые байты полезной нагрузки через упаковщик потока. //! ~russian Записывает массив байтов в соединение
int write(const void * d, const size_t s); int write(const void * d, const size_t s);
//! \~english Sends payload stored in "ba". //! ~english Writes byte array to the connection
//! \~russian Отправляет полезную нагрузку из "ba". //! ~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 connection diagnostics collection. //! ~english Enables diagnostics collection
//! \~russian Включает сбор диагностики соединения. //! ~russian Включает сбор диагностики
void enableDiagnostics(); void enableDiagnostics();
//! \~english Returns a snapshot of current diagnostics counters. //! ~english Gets current diagnostics state
//! \~russian Возвращает снимок текущих диагностических счетчиков. //! ~russian Возвращает текущее состояние диагностики
PIDiagnostics::State diagnostics() const; PIDiagnostics::State diagnostics() const;
//! \~english Returns how many payload bytes of the current packet are already received (all bytes count passed in \a receivePacketStart()). //! ~english Gets current received packet bytes already received (all bytes count passed in \a receivePacketStart())
//! \~russian Возвращает, сколько байтов полезной нагрузки текущего пакета уже получено (общее количество передается в \a receivePacketStart()). //! ~russian Возвращает сколько байт принимаемого пакета получено (общее количество передается в \a receivePacketStart())
int receivePacketProgress() const; int receivePacketProgress() const;
//! \~english Returns the current packet framing configuration.
//! \~russian Возвращает текущую конфигурацию пакетирования.
const PIStreamPackerConfig & configuration() const { return stream.configuration(); } const PIStreamPackerConfig & configuration() const { return stream.configuration(); }
//! \~english Returns the current packet framing configuration for modification.
//! \~russian Возвращает текущую конфигурацию пакетирования для изменения.
PIStreamPackerConfig & configuration() { return stream.configuration(); } PIStreamPackerConfig & configuration() { return stream.configuration(); }
//! \~english Replaces the packet framing configuration.
//! \~russian Заменяет конфигурацию пакетирования.
void setConfiguration(const PIStreamPackerConfig & config) { stream.setConfiguration(config); } void setConfiguration(const PIStreamPackerConfig & config) { stream.setConfiguration(config); }
protected: protected:
//! \~english Called when a full payload packet is received. //! ~english Called when data is received
//! \~russian Вызывается при получении полного пакета полезной нагрузки. //! ~russian Вызывается при получении данных
virtual void readed(PIByteArray data) {} virtual void readed(PIByteArray data) {}
//! \~english Called after the TCP connection becomes active. //! ~english Called when connection is established
//! \~russian Вызывается после перехода TCP-соединения в активное состояние. //! ~russian Вызывается при установке соединения
virtual void connected() {} virtual void connected() {}
//! \~english Called after the connection is closed. //! ~english Called when connection is closed
//! \~russian Вызывается после закрытия соединения. //! ~russian Вызывается при закрытии соединения
virtual void disconnected() {} virtual void disconnected() {}
//! \~english Called when reception of a new packet starts. //! ~english Called when packet receiving starts
//! \~russian Вызывается при начале приема нового пакета. //! ~russian Вызывается при начале получения пакета
virtual void receivePacketStart(int size) {} virtual void receivePacketStart(int size) {}
//! \~english Called when reception of the current packet finishes. //! ~english Called when packet receiving ends
//! \~russian Вызывается при завершении приема текущего пакета. //! ~russian Вызывается при завершении получения пакета
virtual void receivePacketEnd() {} virtual void receivePacketEnd() {}
void init(); void init();

View File

@@ -1,8 +1,9 @@
//! \~\file piclientserver_server.h /*! \file piclientserver_server.h
//! \~\ingroup ClientServer * \ingroup ClientServer
//! \brief * \~\brief
//! \~english TCP Server * \~english
//! \~russian TCP Сервер * \~russian
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -37,73 +38,55 @@ namespace PIClientServer {
class ServerClient; class ServerClient;
//! \~\ingroup ClientServer //! ~english TCP server for client-server communication
//! \~\brief //! ~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 Constructs a stopped server with default limits.
//! \~russian Создает остановленный сервер с ограничениями по умолчанию.
Server(); Server();
//! \~english Stops the server and releases transport resources.
//! \~russian Останавливает сервер и освобождает транспортные ресурсы.
virtual ~Server(); virtual ~Server();
//! \~english Starts listening for clients on address "addr". //! ~english Starts listening on specified address
//! \~russian Начинает принимать клиентов по адресу "addr". //! ~russian Начинает прослушивание на указанном адресе
void listen(PINetworkAddress addr); void listen(PINetworkAddress addr);
//! \~english Starts listening on all interfaces at port "port". //! ~english Starts listening on all interfaces
//! \~russian Начинает прослушивание на всех интерфейсах на порту "port". //! ~russian Начинает прослушивание на всех интерфейсах
//! \~\details
//! \~english Equivalent to listen({0, port}), binds to all available network interfaces.
//! \~russian Эквивалентно listen({0, port}), привязывается ко всем доступным сетевым интерфейсам.
void listenAll(ushort port) { listen({0, port}); } void listenAll(ushort port) { listen({0, port}); }
//! \~english Stops accepting clients and shuts the server down. //! ~english Stops the server
//! \~russian Прекращает прием клиентов и завершает работу сервера. //! ~russian Останавливает сервер
void stopServer(); void stopServer();
//! \~english Closes all currently connected clients. //! ~english Closes all client connections
//! \~russian Закрывает все текущие клиентские соединения. //! ~russian Закрывает все клиентские соединения
//! \~\details
//! \~english Immediately closes all active client connections without stopping the server.
//! \~russian Немедленно закрывает все активные клиентские соединения без остановки сервера.
void closeAll(); void closeAll();
//! \~english Returns the configured maximum number of simultaneous clients. //! ~english Gets maximum allowed clients
//! \~russian Возвращает настроенный максимум одновременных клиентов. //! ~russian Возвращает максимальное число клиентов
int getMaxClients() const { return max_clients; } int getMaxClients() const { return max_clients; }
//! \~english Sets the maximum number of simultaneous clients. //! ~english Sets maximum allowed clients
//! \~russian Устанавливает максимальное число одновременных клиентов. //! ~russian Устанавливает максимальное число клиентов
//! \~\details
//! \~english Sets the maximum number of concurrent client connections. Default is 1000.
//! \~russian Устанавливает максимальное количество одновременных клиентских подключений. По умолчанию 1000.
void setMaxClients(int new_max_clients); void setMaxClients(int new_max_clients);
//! \~english Returns the number of currently connected clients. //! ~english Gets current clients count
//! \~russian Возвращает текущее количество подключенных клиентов. //! ~russian Возвращает текущее количество клиентов
int clientsCount() const; int clientsCount() const;
//! \~english Calls "func" for each currently connected client. //! ~english Executes function for each connected client
//! \~russian Вызывает "func" для каждого текущего подключенного клиента. //! ~russian Выполняет функцию для каждого подключённого клиента
void forEachClient(std::function<void(ServerClient *)> func); void forEachClient(std::function<void(ServerClient *)> func);
//! \~english Sets the factory used to create accepted client objects. //! ~english Sets factory for creating new client instances
//! \~russian Устанавливает фабрику, создающую объекты принятых клиентов. //! ~russian Устанавливает фабрику для создания клиентских экземпляров
void setClientFactory(std::function<ServerClient *()> f) { client_factory = std::move(f); } void setClientFactory(std::function<ServerClient *()> f) { client_factory = f; }
private: private:
void newClient(ServerClient * c); void newClient(ServerClient * c);

View File

@@ -1,8 +1,3 @@
//! \~\file piclientservermodule.h
//! \~\ingroup ClientServer
//! \~\brief
//! \~english Umbrella header and module group for TCP client-server helpers
//! \~russian Общий заголовок и группа модуля для TCP-клиент-серверных компонентов
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -39,10 +34,10 @@
//! \~russian \par Общее //! \~russian \par Общее
//! //!
//! \~english //! \~english
//! These headers provide a TCP server with server-side client objects and an active client for remote connections. //! These files provides server with clients dispatching for server-side and client for client-side.
//! //!
//! \~russian //! \~russian
//! Эти заголовки предоставляют TCP-сервер с серверными объектами клиентов и активного клиента для удаленных подключений. //! Эти файлы предоставляют сервер с диспетчеризацией клиентов для серверной стороны и клиента для клиентской стороны.
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -1,8 +1,9 @@
//! \~\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
*/
/* /*
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
@@ -29,18 +30,11 @@
#include "piethernet.h" #include "piethernet.h"
#include "pistreampacker.h" #include "pistreampacker.h"
//! \~\ingroup Cloud
//! \brief
//! \~english Base class for cloud client and server.
//! \~russian Базовый класс для облачного клиента и сервера.
class PIP_CLOUD_EXPORT PICloudBase { class PIP_CLOUD_EXPORT PICloudBase {
public: public:
//! \~english Constructs the shared PICloud transport state.
//! \~russian Создает общее транспортное состояние PICloud.
PICloudBase(); PICloudBase();
//! \~english Returns the logical server name configured for the transport.
//! \~russian Возвращает логическое имя сервера, настроенное для транспорта.
PIString serverName() const; PIString serverName() const;
protected: protected:

View File

@@ -1,8 +1,9 @@
//! \~\file picloudclient.h /*! \file picloudclient.h
//! \~\ingroup Cloud * \ingroup Cloud
//! \~\brief * \~\brief
//! \~english Client-side PICloud device for one named server * \~english PICloud Client
//! \~russian Клиентское устройство PICloud для одного именованного сервера * \~russian Клиент PICloud
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Client PICloud Client
@@ -28,61 +29,27 @@
#include "picloudbase.h" #include "picloudbase.h"
#include "piconditionvar.h" #include "piconditionvar.h"
//! \~\ingroup Cloud
//! \~\brief //! \brief PICloudClient
//! \~english %PIIODevice implementation for a logical PICloud client.
//! \~russian Реализация %PIIODevice для логического клиента PICloud.
class PIP_CLOUD_EXPORT PICloudClient class PIP_CLOUD_EXPORT PICloudClient
: public PIIODevice : public PIIODevice
, public PICloudBase { , public PICloudBase {
PIIODEVICE(PICloudClient, ""); PIIODEVICE(PICloudClient, "");
public: public:
//! \~english Constructs a client for transport endpoint "path" and mode "mode".
//! \~russian Создает клиент для транспортной точки "path" и режима "mode".
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Destroys the client and closes the underlying transport.
//! \~russian Уничтожает клиент и закрывает нижележащий транспорт.
virtual ~PICloudClient(); virtual ~PICloudClient();
//! \~english Sets the logical server name used during the PICloud handshake.
//! \~russian Устанавливает логическое имя сервера, используемое при рукопожатии PICloud.
void setServerName(const PIString & server_name); void setServerName(const PIString & server_name);
//! \~english Enables or disables automatic reconnect of the underlying TCP link.
//! \~russian Включает или выключает автоматическое переподключение нижележащего TCP-соединения.
void setKeepConnection(bool on); void setKeepConnection(bool on);
//! \~english Returns whether the logical PICloud session is established.
//! \~russian Возвращает, установлена ли логическая сессия PICloud.
bool isConnected() const { return is_connected; } bool isConnected() const { return is_connected; }
//! \~english Returns the number of payload bytes buffered for \a read().
//! \~russian Возвращает количество байтов полезной нагрузки, буферизованных для \a read().
ssize_t bytesAvailable() const override { return buff.size(); } ssize_t bytesAvailable() const override { return buff.size(); }
//! \~english Interrupts pending connection and read waits.
//! \~russian Прерывает ожидающие операции подключения и чтения.
void interrupt() override; void interrupt() override;
//! \events
//! \{
//! \fn void connected()
//! \~english Raised after the logical PICloud session becomes ready.
//! \~russian Вызывается после того, как логическая сессия PICloud готова к работе.
EVENT(connected); EVENT(connected);
//! \fn void disconnected()
//! \~english Raised when the logical PICloud session is closed.
//! \~russian Вызывается при закрытии логической сессии PICloud.
EVENT(disconnected); EVENT(disconnected);
//! \}
protected: protected:
bool openDevice() override; bool openDevice() override;
bool closeDevice() override; bool closeDevice() override;

View File

@@ -1,13 +1,3 @@
/*! \file picloudmodule.h
* \ingroup Cloud
* \~\brief
* \~english Umbrella header for the PICloud module
* \~russian Зонтичный заголовок модуля PICloud
*
* \~\details
* \~english Includes the public client, server, and low-level transport helpers of the module.
* \~russian Подключает публичные клиентские, серверные и низкоуровневые транспортные помощники модуля.
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -28,8 +18,8 @@
*/ */
//! \defgroup Cloud Cloud //! \defgroup Cloud Cloud
//! \~\brief //! \~\brief
//! \~english Named cloud endpoints over an ethernet transport //! \~english Cloud transport over ethernet
//! \~russian Именованные облачные конечные точки поверх Ethernet-транспорта //! \~russian Облачный транспорт через ethernet
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module_Cloud Building with CMake //! \~english \section cmake_module_Cloud Building with CMake
@@ -44,10 +34,10 @@
//! \~russian \par Общее //! \~russian \par Общее
//! //!
//! \~english //! \~english
//! Includes logical client and server devices together with low-level PICloud framing helpers. //! These files provides server-side and client-side of PICloud transport.
//! //!
//! \~russian //! \~russian
//! Подключает логические клиентские и серверные устройства вместе с низкоуровневыми помощниками кадрирования PICloud. //! Эти файлы обеспечивают серверную и клиентскую сторону транспорта PICloud.
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -1,8 +1,9 @@
//! \~\file picloudserver.h /*! \file picloudserver.h
//! \~\ingroup Cloud * \ingroup Cloud
//! \~\brief * \~\brief
//! \~english Server-side PICloud device for one named endpoint * \~english PICloud Server
//! \~russian Серверное устройство PICloud для одной именованной конечной точки * \~russian Сервер PICloud
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Server PICloud Server
@@ -28,43 +29,23 @@
#include "picloudbase.h" #include "picloudbase.h"
#include "piconditionvar.h" #include "piconditionvar.h"
//! \~\ingroup Cloud
//! \~\brief
//! \~english %PIIODevice implementation for a logical PICloud server.
//! \~russian Реализация %PIIODevice для логического сервера 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:
//! \~english Constructs a logical server for transport endpoint "path" and mode "mode". //! PICloudServer
//! \~russian Создает логический сервер для транспортной точки "path" и режима "mode".
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Destroys the server and closes all logical clients.
//! \~russian Уничтожает сервер и закрывает всех логических клиентов.
virtual ~PICloudServer(); virtual ~PICloudServer();
//! \~\ingroup Cloud
//! \~\brief
//! \~english Per-client %PIIODevice exposed by %PICloudServer.
//! \~russian Клиентское %PIIODevice, предоставляемое %PICloudServer.
//! \~\details
//! \~english Instances are created by \a newConnection() and represent one logical cloud client.
//! \~russian Экземпляры создаются через \a newConnection() и представляют одного логического облачного клиента.
class Client: public PIIODevice { class Client: public PIIODevice {
PIIODEVICE(PICloudServer::Client, ""); PIIODEVICE(PICloudServer::Client, "");
friend class PICloudServer; friend class PICloudServer;
public: public:
//! \~english Constructs a wrapper for logical client "id" owned by server "srv".
//! \~russian Создает обертку для логического клиента "id", принадлежащего серверу "srv".
Client(PICloudServer * srv = nullptr, uint id = 0); Client(PICloudServer * srv = nullptr, uint id = 0);
//! \~english Destroys the client wrapper.
//! \~russian Уничтожает клиентскую обертку.
virtual ~Client(); virtual ~Client();
protected: protected:
@@ -86,25 +67,12 @@ public:
std::atomic_bool is_connected; std::atomic_bool is_connected;
}; };
//! \~english Sets the logical server name announced by this server.
//! \~russian Устанавливает логическое имя сервера, объявляемое этим сервером.
void setServerName(const PIString & server_name); void setServerName(const PIString & server_name);
//! \~english Returns a snapshot of the currently connected logical clients.
//! \~russian Возвращает снимок текущих подключенных логических клиентов.
PIVector<PICloudServer::Client *> clients() const; PIVector<PICloudServer::Client *> clients() const;
//! \events
//! \{
//! \fn void newConnection(PICloudServer::Client * client)
//! \~english Raised when a new logical client appears for this server name.
//! \~russian Вызывается, когда для этого имени сервера появляется новый логический клиент.
EVENT1(newConnection, PICloudServer::Client *, client); EVENT1(newConnection, PICloudServer::Client *, client);
//! \}
protected: protected:
bool openDevice() override; bool openDevice() override;
bool closeDevice() override; bool closeDevice() override;

View File

@@ -1,9 +1,9 @@
//! \~\file picloudtcp.h /*! \file picloudtcp.h
//! \~\ingroup Cloud * \ingroup Cloud
//! \~\brief * \~\brief
//! \~english Low-level TCP framing helpers for PICloud * \~english PICloud TCP transport
//! \~russian Низкоуровневые помощники TCP-кадрирования для PICloud * \~russian TCP слой PICloud
//! */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud TCP transport PICloud TCP transport
@@ -31,113 +31,50 @@
#include "pistring.h" #include "pistring.h"
class PIEthernet;
class PIStreamPacker; class PIStreamPacker;
//! \~\ingroup Cloud
//! \~english Namespace for low-level PICloud transport helpers.
//! \~russian Пространство имен для низкоуровневых транспортных помощников PICloud.
namespace PICloud { namespace PICloud {
//! \~\ingroup Cloud
//! \~\brief
//! \~english Builds and parses PICloud frames on top of %PIStreamPacker.
//! \~russian Формирует и разбирает кадры PICloud поверх %PIStreamPacker.
class PIP_CLOUD_EXPORT TCP { class PIP_CLOUD_EXPORT TCP {
public: public:
//! \~english Supported PICloud frame versions.
//! \~russian Поддерживаемые версии кадров PICloud.
enum Version { enum Version {
Version_1 = 1 /** \~english First protocol version \~russian Первая версия протокола */, Version_1 = 1,
Version_2 = 2 /** \~english Current protocol version \~russian Текущая версия протокола */ Version_2 = 2,
}; };
//! \~english Logical destination role of a PICloud frame.
//! \~russian Логическая роль получателя кадра PICloud.
enum Role { enum Role {
InvalidRole = 0 /** \~english Invalid or unknown role \~russian Некорректная или неизвестная роль */, InvalidRole = 0,
Server = 1 /** \~english Frame for a logical server \~russian Кадр для логического сервера */, Server = 1,
Client = 2 /** \~english Frame for a logical client \~russian Кадр для логического клиента */ Client = 2,
}; };
//! \~english Kind of PICloud frame payload.
//! \~russian Вид полезной нагрузки кадра PICloud.
enum Type { enum Type {
InvalidType = 0 /** \~english Invalid or unknown frame \~russian Некорректный или неизвестный кадр */, InvalidType = 0,
Connect = 1 /** \~english Connect or registration frame \~russian Кадр подключения или регистрации */, Connect = 1,
Disconnect = 2 /** \~english Disconnect notification frame \~russian Кадр уведомления об отключении */, Disconnect = 2,
Data = 3 /** \~english Payload data frame \~russian Кадр с полезными данными */, Data = 3,
Ping = 4 /** \~english Keepalive frame \~russian Кадр поддержания соединения */ Ping = 4,
}; };
//! \~english Constructs a PICloud frame helper bound to packer "s".
//! \~russian Создает помощник кадров PICloud, связанный с упаковщиком "s".
TCP(PIStreamPacker * s); TCP(PIStreamPacker * s);
//! \~english Sets the logical role written into outgoing frames.
//! \~russian Устанавливает логическую роль, записываемую в исходящие кадры.
void setRole(Role r); void setRole(Role r);
//! \~english Returns the logical role of this helper.
//! \~russian Возвращает логическую роль этого помощника.
Role role() const { return (Role)header.role; } Role role() const { return (Role)header.role; }
//! \~english Sets the logical server name used by connect and keepalive frames.
//! \~russian Устанавливает логическое имя сервера, используемое кадрами подключения и поддержания соединения.
void setServerName(const PIString & server_name_); void setServerName(const PIString & server_name_);
//! \~english Returns the configured logical server name.
//! \~russian Возвращает настроенное логическое имя сервера.
PIString serverName() const; PIString serverName() const;
//! \~english Sends the initial connect frame for the current server name.
//! \~russian Отправляет начальный кадр подключения для текущего имени сервера.
void sendStart(); void sendStart();
//! \~english Sends a connect frame for logical client "client_id".
//! \~russian Отправляет кадр подключения для логического клиента "client_id".
void sendConnected(uint client_id); void sendConnected(uint client_id);
//! \~english Sends a disconnect frame for logical client "client_id".
//! \~russian Отправляет кадр отключения для логического клиента "client_id".
void sendDisconnected(uint client_id); void sendDisconnected(uint client_id);
//! \~english Sends a payload frame for the current logical role.
//! \~russian Отправляет кадр с полезными данными для текущей логической роли.
int sendData(const PIByteArray & data); int sendData(const PIByteArray & data);
//! \~english Sends a payload frame tagged with logical client "client_id".
//! \~russian Отправляет кадр с полезными данными, помеченный логическим клиентом "client_id".
int sendData(const PIByteArray & data, uint client_id); int sendData(const PIByteArray & data, uint client_id);
//! \~english Sends a keepalive frame.
//! \~russian Отправляет кадр поддержания соединения.
void sendPing(); void sendPing();
//! \~english Parses frame header and returns its type and destination role.
//! \~russian Разбирает заголовок кадра и возвращает его тип и роль получателя.
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba);
//! \~english Returns whether current role uses direct payload parsing.
//! \~russian Возвращает, использует ли текущая роль прямой разбор полезной нагрузки.
bool canParseData(PIByteArray & ba); bool canParseData(PIByteArray & ba);
//! \~english Extracts logical client identifier and payload from a server-side data frame.
//! \~russian Извлекает идентификатор логического клиента и полезную нагрузку из серверного кадра данных.
PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba); PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba);
//! \~english Validates and returns raw connect payload used for server identity exchange.
//! \~russian Проверяет и возвращает сырой payload подключения, используемый при обмене идентичностью сервера.
PIByteArray parseConnect_d(PIByteArray & ba); PIByteArray parseConnect_d(PIByteArray & ba);
//! \~english Extracts logical client identifier from a connect frame.
//! \~russian Извлекает идентификатор логического клиента из кадра подключения.
uint parseConnect(PIByteArray & ba); uint parseConnect(PIByteArray & ba);
//! \~english Extracts logical client identifier from a disconnect frame.
//! \~russian Извлекает идентификатор логического клиента из кадра отключения.
uint parseDisconnect(PIByteArray & ba); uint parseDisconnect(PIByteArray & ba);
private: private:

View File

@@ -1,11 +1,9 @@
//! \~\file picodeinfo.h /*! \file picodeinfo.h
//! \~\ingroup Code * \ingroup Code
//! \~\brief * \~\brief
//! \~english C++ code info structs. See \ref code_model. * \~english C++ code info structs. See \ref code_model.
//! \~russian Структуры для C++ кода. Подробнее \ref code_model. * \~russian Структуры для C++ кода. Подробнее \ref code_model.
//! \~\details */
//! \~english Contains structures for code generation and reflection: TypeInfo, FunctionInfo, ClassInfo, EnumInfo, EnumeratorInfo.
//! \~russian Содержит структуры для кодогенерации и рефлексии: TypeInfo, FunctionInfo, ClassInfo, EnumInfo, EnumeratorInfo.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
C++ code info structs C++ code info structs
@@ -38,49 +36,34 @@ class PIVariant;
//! \~english Namespace contains structures for code generation. See \ref code_model. //! \~english Namespace contains structures for code generation. See \ref code_model.
//! \~russian Пространство имен содержит структуры для кодогенерации. Подробнее \ref code_model. //! \~russian Пространство имен содержит структуры для кодогенерации. Подробнее \ref code_model.
//! \~\details
//! \~english Provides classes and structures for code introspection, including type information, function details, class metadata, and enum
//! information.
//! \~russian Предоставляет классы и структуры для интроспекции кода, включая информацию о типах, детали функций, метаданные классов и
//! информацию о перечислениях.
namespace PICodeInfo { namespace PICodeInfo {
//! \~english Type modifiers. //! \~english
//! \~russian Модификаторы типа. //! Type modifiers
//! \~russian
//! Модификаторы типа
enum TypeFlag { enum TypeFlag {
NoFlag /** \~english No modifiers. \~russian Модификаторы отсутствуют. */, NoFlag,
Const = 0x01 /** \~english \c const modifier. \~russian Модификатор \c const. */, Const /** const */ = 0x01,
Static = 0x02 /** \~english \c static modifier. \~russian Модификатор \c static. */, Static /** static */ = 0x02,
Mutable = 0x04 /** \~english \c mutable modifier. \~russian Модификатор \c mutable. */, Mutable /** mutable */ = 0x04,
Volatile = 0x08 /** \~english \c volatile modifier. \~russian Модификатор \c volatile. */, Volatile /** volatile */ = 0x08,
Inline = 0x10 /** \~english \c inline modifier. \~russian Модификатор \c inline. */, Inline /** inline */ = 0x10,
Virtual = 0x20 /** \~english \c virtual modifier. \~russian Модификатор \c virtual. */, Virtual /** virtual */ = 0x20,
Extern = 0x40 /** \~english \c extern modifier. \~russian Модификатор \c extern. */ Extern /** extern */ = 0x40
}; };
//! \~english Bitmask of type modifiers.
//! \~russian Битовая маска модификаторов типа.
typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags; typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
//! \~english Custom metadata map produced by \c PIMETA.
//! \~russian Карта пользовательских метаданных, создаваемых \c PIMETA.
typedef PIMap<PIString, PIString> MetaMap; typedef PIMap<PIString, PIString> MetaMap;
//! \~english Callback returning serialized member data by member name.
//! \~russian Обратный вызов, возвращающий сериализованные данные члена по имени.
typedef PIByteArray (*AccessValueFunction)(const void *, const char *); typedef PIByteArray (*AccessValueFunction)(const void *, const char *);
//! \~english Callback returning a member type name by member name.
//! \~russian Обратный вызов, возвращающий имя типа члена по его имени.
typedef const char * (*AccessTypeFunction)(const char *); typedef const char * (*AccessTypeFunction)(const char *);
//! \~english Callback returning a member offset by member name.
//! \~russian Обратный вызов, возвращающий смещение члена по его имени.
typedef int (*AccessOffsetFunction)(const char *); typedef int (*AccessOffsetFunction)(const char *);
//! \~english Type information //! \~english Type information
//! \~russian Информация о типе //! \~russian Информация о типе
struct PIP_EXPORT TypeInfo { struct PIP_EXPORT TypeInfo {
//! \~english Constructs type information for one variable or argument.
//! \~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;
@@ -88,8 +71,8 @@ struct PIP_EXPORT TypeInfo {
bits = b; bits = b;
} }
//! \~english Returns whether the described variable is a bitfield. //! \~english Returns if variable if bitfield
//! \~russian Возвращает, является ли описываемая переменная битовым полем. //! \~russian Возвращает битовым ли полем является переменная
bool isBitfield() const { return bits > 0; } bool isBitfield() const { return bits > 0; }
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
@@ -126,7 +109,7 @@ struct PIP_EXPORT FunctionInfo {
PIConstChars name; PIConstChars name;
//! \~english Return type //! \~english Return type
//! \~russian Возвращаемый тип //! \~russian Возвращаемые тип
TypeInfo return_type; TypeInfo return_type;
//! \~english Arguments types //! \~english Arguments types
@@ -138,28 +121,26 @@ 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 Constructs an empty class description.
//! \~russian Создает пустое описание класса.
ClassInfo() { is_anonymous = false; } ClassInfo() { is_anonymous = false; }
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA //! \~russian Произвольное содержимое PIMETA
MetaMap meta; MetaMap meta;
//! \~english Indicates that the type was declared without a name //! \~english Anonymous or not
//! \~russian Показывает, что тип был объявлен без имени //! \~russian Анонимный или нет
bool is_anonymous; bool is_anonymous;
//! \~english Declaration kind, for example \c class or \c struct //! \~english Type
//! \~russian Вид объявления, например \c class или \c struct //! \~russian Тип
PIConstChars type; PIConstChars type;
//! \~english Name //! \~english Name
//! \~russian Имя //! \~russian Имя
PIConstChars name; PIConstChars name;
//! \~english Base class names //! \~english Parent names
//! \~russian Имена базовых классов //! \~russian Имена родителей
PIVector<PIConstChars> parents; PIVector<PIConstChars> parents;
//! \~english Variables //! \~english Variables
@@ -170,8 +151,8 @@ struct PIP_EXPORT ClassInfo {
//! \~russian Методы //! \~russian Методы
PIVector<PICodeInfo::FunctionInfo> functions; PIVector<PICodeInfo::FunctionInfo> functions;
//! \~english Registered derived class descriptions //! \~english Subclass list
//! \~russian Зарегистрированные описания производных классов //! \~russian Список наследников
PIVector<PICodeInfo::ClassInfo *> children_info; PIVector<PICodeInfo::ClassInfo *> children_info;
}; };
@@ -179,14 +160,10 @@ struct PIP_EXPORT ClassInfo {
//! \~english Enumerator information //! \~english Enumerator information
//! \~russian Информация об элементе перечисления //! \~russian Информация об элементе перечисления
struct PIP_EXPORT EnumeratorInfo { struct PIP_EXPORT EnumeratorInfo {
//! \~english Constructs one enum member description.
//! \~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 the enumerator to the %PIVariantTypes representation.
//! \~russian Преобразует элемент перечисления в представление %PIVariantTypes.
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
@@ -206,16 +183,16 @@ struct PIP_EXPORT EnumeratorInfo {
//! \~english Enum information //! \~english Enum information
//! \~russian Информация о перечислении //! \~russian Информация о перечислении
struct PIP_EXPORT EnumInfo { struct PIP_EXPORT EnumInfo {
//! \~english Returns the member name for the value \a value. //! \~english Returns member name with value "value"
//! \~russian Возвращает имя элемента для значения \a value. //! \~russian Возвращает имя элемента со значением "value"
PIString memberName(int value) const; PIString memberName(int value) const;
//! \~english Returns the member value for the name \a name. //! \~english Returns member value with name "name"
//! \~russian Возвращает значение элемента для имени \a name. //! \~russian Возвращает значение элемента с именем "name"
int memberValue(const PIString & name) const; int memberValue(const PIString & name) const;
//! \~english Converts the enum description to %PIVariantTypes::Enum. //! \~english Returns as PIVariantTypes::Enum
//! \~russian Преобразует описание перечисления в %PIVariantTypes::Enum. //! \~russian Возвращает как PIVariantTypes::Enum
PIVariantTypes::Enum toPIVariantEnum(); PIVariantTypes::Enum toPIVariantEnum();
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
@@ -232,8 +209,6 @@ struct PIP_EXPORT EnumInfo {
}; };
//! \~english Writes a declaration-like view of \a v to \a s.
//! \~russian Записывает в \a s представление \a v в стиле объявления.
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 ";
@@ -246,15 +221,11 @@ inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
return s; return s;
} }
//! \~english Writes an enum member description to \a s.
//! \~russian Записывает описание элемента перечисления в \a s.
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 Writes a human-readable class description to \a s.
//! \~russian Записывает в \a s человекочитаемое описание класса.
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;
@@ -291,8 +262,6 @@ inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
return s; return s;
} }
//! \~english Writes a human-readable enum description to \a s.
//! \~russian Записывает в \a s человекочитаемое описание перечисления.
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";
@@ -327,70 +296,71 @@ private:
NO_COPY_CLASS(__Storage__) NO_COPY_CLASS(__Storage__)
}; };
class PIP_EXPORT __StorageAccess__ { class PIP_EXPORT
public: __StorageAccess__{public:
static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes() { //! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name
return *(__Storage__::instance()->classesInfo); //! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени
} // namespace PICodeInfo static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes(){return *(__Storage__::instance()->classesInfo);
} // namespace PICodeInfo
static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { return *(__Storage__::instance()->enumsInfo); } //! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name
//! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени
static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() {
return *(__Storage__::instance()->enumsInfo);
}
static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() {
return *(__Storage__::instance()->accessValueFunctions); return *(__Storage__::instance()->accessValueFunctions);
} }
static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() {
return *(__Storage__::instance()->accessTypeFunctions); return *(__Storage__::instance()->accessTypeFunctions);
} }
static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() {
return *(__Storage__::instance()->accessOffsetFunctions); return *(__Storage__::instance()->accessOffsetFunctions);
} }
}; }
;
//! \relatesalso PICodeInfo
//! \~english Macro for the global code model registries.
//! \~russian Макрос для доступа к глобальным реестрам модели кода.
#define PICODEINFO PICodeInfo::__StorageAccess__ #define PICODEINFO PICodeInfo::__StorageAccess__
class PIP_EXPORT ClassInfoInterface { class PIP_EXPORT
public: ClassInfoInterface{public: const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()"){
const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()") { return __Storage__::instance() -> classesInfo;
return __Storage__::instance()->classesInfo; }
} }
}; ;
static ClassInfoInterface classesInfo; static ClassInfoInterface classesInfo;
class PIP_EXPORT EnumsInfoInterface { class PIP_EXPORT
public: EnumsInfoInterface{public: const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()"){
const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()") { return __Storage__::instance() -> enumsInfo;
return __Storage__::instance()->enumsInfo; }
} }
}; ;
static EnumsInfoInterface enumsInfo; static EnumsInfoInterface enumsInfo;
class PIP_EXPORT AccessValueFunctionInterface { class PIP_EXPORT AccessValueFunctionInterface{
public: public: const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->()
const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessValueFunctions()") { const DEPRECATEDM("use PICODEINFO::accessValueFunctions()"){
return __Storage__::instance()->accessValueFunctions; return __Storage__::instance() -> accessValueFunctions;
} }
}; }
;
static AccessValueFunctionInterface accessValueFunctions; static AccessValueFunctionInterface accessValueFunctions;
class PIP_EXPORT AccessTypeFunctionInterface { class PIP_EXPORT AccessTypeFunctionInterface{
public: public: const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->()
const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()") { const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()"){
return __Storage__::instance()->accessTypeFunctions; return __Storage__::instance() -> accessTypeFunctions;
} }
}; }
;
static AccessTypeFunctionInterface accessTypeFunctions; static AccessTypeFunctionInterface accessTypeFunctions;
@@ -402,8 +372,6 @@ STATIC_INITIALIZER_BEGIN
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
//! \~english Returns a serialized value of \a member_name from an instance of \a class_name.
//! \~russian Возвращает сериализованное значение \a member_name из экземпляра \a class_name.
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);
@@ -411,8 +379,6 @@ inline PIByteArray getMemberValue(const void * p, const char * class_name, const
return af(p, member_name); return af(p, member_name);
} }
//! \~english Returns the registered type name of \a member_name in \a class_name.
//! \~russian Возвращает зарегистрированное имя типа \a member_name в \a class_name.
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);
@@ -420,20 +386,14 @@ inline const char * getMemberType(const char * class_name, const char * member_n
return af(member_name); return af(member_name);
} }
//! \~english Returns \a member_name from \a class_name as %PIVariant when accessors are registered.
//! \~russian Возвращает \a member_name из \a class_name как %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 assignable values into \a ret through the stream operator.
//! \~russian Сериализует присваиваемые значения в \a ret через оператор потока.
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 Fallback overload for values that cannot be written to the byte-array stream.
//! \~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,13 +1,3 @@
/*! \file picodemodule.h
* \ingroup Code
* \~\brief
* \~english Umbrella header for the code parsing module
* \~russian Общий заголовок модуля разбора кода
*
* \~\details
* \~english Includes the public code information and parser headers.
* \~russian Подключает публичные заголовки информации о коде и парсера.
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -44,12 +34,12 @@
//! \~russian \par Общее //! \~russian \par Общее
//! //!
//! \~english //! \~english
//! This module provides C++ source parsing and the storage types used by the //! These files provides parsing C++ code and storage to use results of \a pip_cmg utility.
//! \a pip_cmg utility. See \ref code_model. //! See \ref code_model.
//! //!
//! \~russian //! \~russian
//! Этот модуль предоставляет разбор исходного кода C++ и типы хранения, //! Эти файлы обеспечивают разбор C++ кода и хранение результатов работы утилиты \a pip_cmg.
//! используемые утилитой \a pip_cmg. Подробнее \ref code_model. //! Подробнее \ref code_model.
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -1,8 +1,9 @@
//! \~\file picodeparser.h /*! \file picodeparser.h
//! \~\ingroup Code * \ingroup Code
//! \~\brief * \~\brief
//! \~english C++ code parser * \~english C++ code parser
//! \~russian Разбор C++ кода * \~russian Разбор C++ кода
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
C++ code parser C++ code parser
@@ -36,88 +37,44 @@ inline bool _isCChar(const PIString & c) {
return _isCChar(c[0]); return _isCChar(c[0]);
} }
//! \~\ingroup Code
//! \~\brief
//! \~english Parser of C/C++ declarations used by the code model tools.
//! \~russian Разборщик объявлений C/C++, используемый инструментами модели кода.
//! \~\details
//! \~english Parser for analyzing C++ source files. Extracts information about classes, structures, enums, macros, functions, and members.
//! \~russian Парсер для анализа C++ исходных файлов. Извлекает информацию о классах, структурах, перечислениях, макросах, функциях и
//! членах.
class PIP_EXPORT PICodeParser { class PIP_EXPORT PICodeParser {
public: public:
//! \~english Constructs a parser with built-in PIP macro presets.
//! \~russian Создает разборщик со встроенными предустановками макросов PIP.
PICodeParser(); PICodeParser();
//! \~english Visibility of a parsed declaration inside the current scope.
//! \~russian Видимость разобранного объявления в текущей области.
enum Visibility { enum Visibility {
Global /** \~english Global or namespace-level declaration. \~russian Глобальное объявление или объявление уровня пространства имен. Global,
*/ Public,
, Protected,
Public /** \~english Public class member. \~russian Открытый член класса. */, Private
Protected /** \~english Protected class member. \~russian Защищенный член класса. */,
Private /** \~english Private class member. \~russian Закрытый член класса. */
}; };
//! \~english Parsed declaration attributes.
//! \~russian Атрибуты разобранного объявления.
enum Attribute { enum Attribute {
NoAttributes = 0x0 /** \~english No attributes. \~russian Атрибуты отсутствуют. */, NoAttributes = 0x0,
Const = 0x01 /** \~english \c const declaration. \~russian Объявление с \c const. */, Const = 0x01,
Static = 0x02 /** \~english \c static declaration. \~russian Объявление с \c static. */, Static = 0x02,
Mutable = 0x04 /** \~english \c mutable declaration. \~russian Объявление с \c mutable. */, Mutable = 0x04,
Volatile = 0x08 /** \~english \c volatile declaration. \~russian Объявление с \c volatile. */, Volatile = 0x08,
Inline = 0x10 /** \~english \c inline declaration. \~russian Объявление с \c inline. */, Inline = 0x10,
Virtual = 0x20 /** \~english \c virtual declaration. \~russian Объявление с \c virtual. */, Virtual = 0x20,
Extern = 0x40 /** \~english \c extern declaration. \~russian Объявление с \c extern. */ Extern = 0x40
}; };
//! \~english Bitmask of parsed declaration attributes.
//! \~russian Битовая маска атрибутов разобранного объявления.
typedef PIFlags<Attribute> Attributes; typedef PIFlags<Attribute> Attributes;
//! \~english Preprocessor define name and value.
//! \~russian Имя и значение макроса \c define.
typedef PIPair<PIString, PIString> Define; typedef PIPair<PIString, PIString> Define;
//! \~english Typedef alias and target type.
//! \~russian Псевдоним typedef и целевой тип.
typedef PIPair<PIString, PIString> Typedef; typedef PIPair<PIString, PIString> Typedef;
//! \~english Parsed metadata map.
//! \~russian Карта разобранных метаданных.
typedef PIMap<PIString, PIString> MetaMap; typedef PIMap<PIString, PIString> MetaMap;
//! \~english Parsed function-like 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 Expands the macro body with arguments from \a args_.
//! \~russian Разворачивает тело макроса с аргументами из \a args_.
PIString expand(PIString args_, bool * ok = 0) const; PIString expand(PIString args_, bool * ok = 0) const;
//! \~english Macro name.
//! \~russian Имя макроса.
PIString name; PIString name;
//! \~english Macro replacement text.
//! \~russian Текст замены макроса.
PIString value; PIString value;
//! \~english Ordered list of macro argument names.
//! \~russian Упорядоченный список имен аргументов макроса.
PIStringList args; PIStringList args;
}; };
//! \~english Parsed member declaration or function signature.
//! \~russian Разобранное объявление члена или сигнатура функции.
struct PIP_EXPORT Member { struct PIP_EXPORT Member {
Member() { Member() {
visibility = Global; visibility = Global;
@@ -126,58 +83,20 @@ public:
is_type_ptr = false; is_type_ptr = false;
attributes = NoAttributes; attributes = NoAttributes;
} }
//! \~english Returns whether the member is declared as a bitfield.
//! \~russian Возвращает, объявлен ли член как битовое поле.
bool isBitfield() const { return bits > 0; } bool isBitfield() const { return bits > 0; }
//! \~english Parsed metadata attached to the member.
//! \~russian Разобранные метаданные, привязанные к члену.
MetaMap meta; MetaMap meta;
//! \~english Member type or return type.
//! \~russian Тип члена или возвращаемый тип.
PIString type; PIString type;
//! \~english Member name.
//! \~russian Имя члена.
PIString name; PIString name;
//! \~english Full textual argument declarations.
//! \~russian Полные текстовые объявления аргументов.
PIStringList arguments_full; PIStringList arguments_full;
//! \~english Argument types only.
//! \~russian Только типы аргументов.
PIStringList arguments_type; PIStringList arguments_type;
//! \~english Parsed array dimensions.
//! \~russian Разобранные размеры массива.
PIStringList dims; PIStringList dims;
//! \~english Member visibility.
//! \~russian Видимость члена.
Visibility visibility; Visibility visibility;
//! \~english Member attributes.
//! \~russian Атрибуты члена.
Attributes attributes; Attributes attributes;
//! \~english Indicates that the parsed type is a pointer.
//! \~russian Показывает, что разобранный тип является указателем.
bool is_type_ptr; bool is_type_ptr;
//! \~english Parsed size in bytes when available.
//! \~russian Разобранный размер в байтах, если он известен.
int size; int size;
//! \~english Bit count for bitfields, or \c -1 otherwise.
//! \~russian Количество бит для битового поля или \c -1 в остальных случаях.
int bits; int bits;
}; };
//! \~english Parsed class, struct or namespace.
//! \~russian Разобранный класс, структура или пространство имен.
struct PIP_EXPORT Entity { struct PIP_EXPORT Entity {
Entity() { Entity() {
visibility = Global; visibility = Global;
@@ -185,165 +104,57 @@ public:
size = 0; size = 0;
parent_scope = 0; parent_scope = 0;
} }
//! \~english Parsed metadata attached to the entity.
//! \~russian Разобранные метаданные, привязанные к сущности.
MetaMap meta; MetaMap meta;
//! \~english Entity kind, for example \c class, \c struct or \c namespace.
//! \~russian Вид сущности, например \c class, \c struct или \c namespace.
PIString type; PIString type;
//! \~english Entity name.
//! \~russian Имя сущности.
PIString name; PIString name;
//! \~english Source file where the entity was parsed.
//! \~russian Исходный файл, в котором была разобрана сущность.
PIString file; PIString file;
//! \~english Entity visibility inside its parent scope.
//! \~russian Видимость сущности внутри родительской области.
Visibility visibility; Visibility visibility;
//! \~english Parsed size in bytes when available.
//! \~russian Разобранный размер в байтах, если он известен.
int size; int size;
//! \~english Indicates that the entity was declared without a name.
//! \~russian Показывает, что сущность объявлена без имени.
bool is_anonymous; bool is_anonymous;
//! \~english Immediate containing entity, or \c nullptr for the root scope.
//! \~russian Непосредственная содержащая сущность или \c nullptr для корневой области.
Entity * parent_scope; Entity * parent_scope;
//! \~english Direct base entities.
//! \~russian Непосредственные базовые сущности.
PIVector<Entity *> parents; PIVector<Entity *> parents;
//! \~english Parsed member functions.
//! \~russian Разобранные функции-члены.
PIVector<Member> functions; PIVector<Member> functions;
//! \~english Parsed data members.
//! \~russian Разобранные поля данных.
PIVector<Member> members; PIVector<Member> members;
//! \~english Typedefs declared inside the entity.
//! \~russian Typedef-объявления внутри сущности.
PIVector<Typedef> typedefs; PIVector<Typedef> typedefs;
}; };
//! \~english Parsed enumerator entry.
//! \~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;
value = v; value = v;
meta = m; meta = m;
} }
//! \~english Parsed metadata attached to the enumerator.
//! \~russian Разобранные метаданные, привязанные к элементу перечисления.
MetaMap meta; MetaMap meta;
//! \~english Enumerator name.
//! \~russian Имя элемента перечисления.
PIString name; PIString name;
//! \~english Enumerator value.
//! \~russian Значение элемента перечисления.
int value; int value;
}; };
//! \~english Parsed enumeration.
//! \~russian Разобранное перечисление.
struct PIP_EXPORT Enum { struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()) { name = n; } Enum(const PIString & n = PIString()) { name = n; }
//! \~english Parsed metadata attached to the enum.
//! \~russian Разобранные метаданные, привязанные к перечислению.
MetaMap meta; MetaMap meta;
//! \~english Enum name.
//! \~russian Имя перечисления.
PIString name; PIString name;
//! \~english Parsed enumerators.
//! \~russian Разобранные элементы перечисления.
PIVector<EnumeratorInfo> members; PIVector<EnumeratorInfo> members;
}; };
//! \~english Parses one source file and optionally follows its includes.
//! \~russian Разбирает один исходный файл и при необходимости следует по его include-зависимостям.
void parseFile(const PIString & file, bool follow_includes = true); void parseFile(const PIString & file, bool follow_includes = true);
//! \~english Parses several source files into one parser state.
//! \~russian Разбирает несколько исходных файлов в одном состоянии разборщика.
void parseFiles(const PIStringList & files, bool follow_includes = true); void parseFiles(const PIStringList & files, bool follow_includes = true);
//! \~english Parses source text provided directly in memory.
//! \~russian Разбирает исходный текст, переданный напрямую из памяти.
void parseFileContent(PIString fc); void parseFileContent(PIString fc);
//! \~english Adds a directory to the include search list.
//! \~russian Добавляет каталог в список поиска include-файлов.
void includeDirectory(const PIString & dir) { includes << dir; } void includeDirectory(const PIString & dir) { includes << dir; }
//! \~english Adds a custom preprocessor definition before parsing.
//! \~russian Добавляет пользовательское препроцессорное определение перед разбором.
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 Returns whether an enum with \a name was parsed.
//! \~russian Возвращает, было ли разобрано перечисление с именем \a name.
bool isEnum(const PIString & name); bool isEnum(const PIString & name);
//! \~english Finds a parsed entity by its full name.
//! \~russian Ищет разобранную сущность по ее полному имени.
Entity * findEntityByName(const PIString & en); Entity * findEntityByName(const PIString & en);
//! \~english Returns the set of files already processed by the parser.
//! \~russian Возвращает набор файлов, уже обработанных разборщиком.
PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); } PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); }
//! \~english Returns the file detected as the main translation unit.
//! \~russian Возвращает файл, определенный как основной единицей трансляции.
PIString mainFile() const { return main_file; } PIString mainFile() const { return main_file; }
//! \~english Returns the synthetic global scope entity.
//! \~russian Возвращает синтетическую сущность глобальной области.
const PICodeParser::Entity * global() const { return &root_; } const PICodeParser::Entity * global() const { return &root_; }
//! \~english Returns the maximum number of macro substitution passes.
//! \~russian Возвращает максимальное число проходов подстановки макросов.
int macrosSubstitutionMaxIterations() const { return macros_iter; } int macrosSubstitutionMaxIterations() const { return macros_iter; }
//! \~english Sets the maximum number of macro substitution passes.
//! \~russian Задает максимальное число проходов подстановки макросов.
void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; } void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; }
//! \~english Parsed \c define directives, including built-in and custom ones.
//! \~russian Разобранные директивы \c define, включая встроенные и пользовательские.
PIVector<Define> defines, custom_defines; PIVector<Define> defines, custom_defines;
//! \~english Parsed function-like macros.
//! \~russian Разобранные функциональные макросы.
PIVector<Macro> macros; PIVector<Macro> macros;
//! \~english Parsed enums from the processed files.
//! \~russian Разобранные перечисления из обработанных файлов.
PIVector<Enum> enums; PIVector<Enum> enums;
//! \~english Parsed top-level typedef declarations.
//! \~russian Разобранные typedef-объявления верхнего уровня.
PIVector<Typedef> typedefs; PIVector<Typedef> typedefs;
//! \~english Parsed entities discovered in the processed files.
//! \~russian Разобранные сущности, найденные в обработанных файлах.
PIVector<Entity *> entities; PIVector<Entity *> entities;
private: private:

View File

@@ -1,12 +1,3 @@
//! \~\file piconsolemodule.h
//! \~\ingroup Console
//! \~\brief
//! \~english Console module headers
//! \~russian Заголовочные файлы модуля консоли
//! \~\details
//! \~english This file includes all Console module headers providing keyboard input, screen management, and tile-based UI.
//! \~russian Этот файл включает все заголовочные файлы модуля консоли, обеспечивающие ввод с клавиатуры, управление экраном и UI на основе
//! тайлов.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -27,8 +18,8 @@
*/ */
//! \defgroup Console Console //! \defgroup Console Console
//! \~\brief //! \~\brief
//! \~english Console screen, input, and terminal utilities //! \~english Console graphic
//! \~russian Средства консольного экрана, ввода и терминала //! \~russian Графика в консоли
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module_Console Building with CMake //! \~english \section cmake_module_Console Building with CMake
@@ -43,10 +34,10 @@
//! \~russian \par Общее //! \~russian \par Общее
//! //!
//! \~english //! \~english
//! These files provide keyboard capture from the console, a simple tile-based screen API and a virtual terminal. //! These files provides grab keyboard from console, simple tiling manager and virtual terminal.
//! //!
//! \~russian //! \~russian
//! Эти файлы предоставляют захват клавиатуры из консоли, простой экранный API на тайлах и виртуальный терминал. //! Эти файлы обеспечивают захват клавиатуры в консоли, простой тайловый менеджер и виртуальный терминал.
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -18,9 +18,11 @@
*/ */
#include "pikbdlistener.h" #include "pikbdlistener.h"
#include "piincludes_p.h" #ifndef MICRO_PIP
#include "piliterals.h"
#include "piwaitevent_p.h" # include "piincludes_p.h"
# include "piliterals.h"
# include "piwaitevent_p.h"
// clang-format off // clang-format off
#ifndef WINDOWS #ifndef WINDOWS
# include <termios.h> # include <termios.h>
@@ -49,7 +51,7 @@ bool PIKbdListener::exiting;
PIKbdListener * PIKbdListener::_object = 0; PIKbdListener * PIKbdListener::_object = 0;
#ifndef WINDOWS # ifndef WINDOWS
// unix // unix
const PIKbdListener::EscSeq PIKbdListener::esc_seq[] = { const PIKbdListener::EscSeq PIKbdListener::esc_seq[] = {
{"OA", PIKbdListener::UpArrow, 0, 0, 1}, {"OA", PIKbdListener::UpArrow, 0, 0, 1},
@@ -130,22 +132,22 @@ void setupTerminal(bool on) {
printf(on ? "h" : "l"); printf(on ? "h" : "l");
fflush(0); fflush(0);
} }
#endif # endif
PRIVATE_DEFINITION_START(PIKbdListener) PRIVATE_DEFINITION_START(PIKbdListener)
#ifdef WINDOWS # ifdef WINDOWS
void *hIn, *hOut; void *hIn, *hOut;
DWORD smode, tmode; DWORD smode, tmode;
CONSOLE_SCREEN_BUFFER_INFO sbi; CONSOLE_SCREEN_BUFFER_INFO sbi;
#else # else
struct termios sterm, tterm; struct termios sterm, tterm;
#endif # endif
#ifdef WINDOWS # ifdef WINDOWS
DWORD DWORD
#else # else
int int
#endif # endif
ret; ret;
PIWaitEvent event; PIWaitEvent event;
PRIVATE_DEFINITION_END(PIKbdListener) PRIVATE_DEFINITION_END(PIKbdListener)
@@ -154,13 +156,13 @@ PRIVATE_DEFINITION_END(PIKbdListener)
PIKbdListener::PIKbdListener(KBFunc slot, void * _d, bool startNow): PIThread() { PIKbdListener::PIKbdListener(KBFunc slot, void * _d, bool startNow): PIThread() {
setName("keyboard_listener"_a); setName("keyboard_listener"_a);
_object = this; _object = this;
#ifdef WINDOWS # ifdef WINDOWS
PRIVATE->hIn = GetStdHandle(STD_INPUT_HANDLE); PRIVATE->hIn = GetStdHandle(STD_INPUT_HANDLE);
PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE); PRIVATE->hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(PRIVATE->hIn, &PRIVATE->smode); GetConsoleMode(PRIVATE->hIn, &PRIVATE->smode);
#else # else
tcgetattr(0, &PRIVATE->sterm); tcgetattr(0, &PRIVATE->sterm);
#endif # endif
ret_func = slot; ret_func = slot;
kbddata_ = _d; kbddata_ = _d;
dbl_interval = 400; dbl_interval = 400;
@@ -178,10 +180,10 @@ PIKbdListener::~PIKbdListener() {
void PIKbdListener::begin() { void PIKbdListener::begin() {
#ifdef WINDOWS # ifdef WINDOWS
GetConsoleMode(PRIVATE->hIn, &PRIVATE->tmode); GetConsoleMode(PRIVATE->hIn, &PRIVATE->tmode);
SetConsoleMode(PRIVATE->hIn, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS); SetConsoleMode(PRIVATE->hIn, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS);
#else # else
struct termios term; struct termios term;
tcgetattr(0, &term); tcgetattr(0, &term);
term.c_lflag &= ~(ECHO | ICANON); term.c_lflag &= ~(ECHO | ICANON);
@@ -189,11 +191,11 @@ void PIKbdListener::begin() {
PRIVATE->tterm = term; PRIVATE->tterm = term;
tcsetattr(0, TCSANOW, &term); tcsetattr(0, TCSANOW, &term);
setupTerminal(true); setupTerminal(true);
#endif # endif
} }
#ifdef WINDOWS # ifdef WINDOWS
PIKbdListener::KeyModifiers getModifiers(DWORD v, bool * shift = 0) { PIKbdListener::KeyModifiers getModifiers(DWORD v, bool * shift = 0) {
PIKbdListener::KeyModifiers ret; PIKbdListener::KeyModifiers ret;
bool ctrl = v & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED); bool ctrl = v & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED);
@@ -214,7 +216,7 @@ PIKbdListener::MouseButtons getButtons(DWORD v) {
if (v & FROM_LEFT_2ND_BUTTON_PRESSED) ret |= PIKbdListener::MouseMiddle; if (v & FROM_LEFT_2ND_BUTTON_PRESSED) ret |= PIKbdListener::MouseMiddle;
return ret; return ret;
} }
#endif # endif
void PIKbdListener::readKeyboard() { void PIKbdListener::readKeyboard() {
@@ -222,7 +224,7 @@ void PIKbdListener::readKeyboard() {
ke.modifiers = 0; ke.modifiers = 0;
char rc[8]; char rc[8];
piZeroMemory(rc, 8); piZeroMemory(rc, 8);
#ifdef WINDOWS # ifdef WINDOWS
INPUT_RECORD ir; INPUT_RECORD ir;
ReadConsoleInput(PRIVATE->hIn, &ir, 1, &(PRIVATE->ret)); ReadConsoleInput(PRIVATE->hIn, &ir, 1, &(PRIVATE->ret));
switch (ir.EventType) { switch (ir.EventType) {
@@ -406,7 +408,7 @@ void PIKbdListener::readKeyboard() {
} break; } break;
default: piMSleep(10); return; default: piMSleep(10); return;
} }
#else # else
tcsetattr(0, TCSANOW, &PRIVATE->tterm); tcsetattr(0, TCSANOW, &PRIVATE->tterm);
if (!PRIVATE->event.wait(0)) return; if (!PRIVATE->event.wait(0)) return;
PRIVATE->ret = read(0, rc, 8); PRIVATE->ret = read(0, rc, 8);
@@ -533,7 +535,7 @@ void PIKbdListener::readKeyboard() {
cout << endl;*/ cout << endl;*/
} }
if (ke.key == 0 && PRIVATE->ret > 1) ke.key = PIChar::fromSystem(rc).unicode16Code(); if (ke.key == 0 && PRIVATE->ret > 1) ke.key = PIChar::fromSystem(rc).unicode16Code();
#endif # endif
if ((rc[0] == '\n' || rc[0] == '\r') && PRIVATE->ret == 1) ke.key = Return; if ((rc[0] == '\n' || rc[0] == '\r') && PRIVATE->ret == 1) ke.key = Return;
if (exit_enabled && ke.key == exit_key) { if (exit_enabled && ke.key == exit_key) {
PIKbdListener::exiting = true; PIKbdListener::exiting = true;
@@ -560,30 +562,32 @@ bool PIKbdListener::stopAndWait(PISystemTime timeout) {
void PIKbdListener::end() { void PIKbdListener::end() {
// cout << "list end" << endl; // cout << "list end" << endl;
#ifdef WINDOWS # ifdef WINDOWS
SetConsoleMode(PRIVATE->hIn, PRIVATE->smode); SetConsoleMode(PRIVATE->hIn, PRIVATE->smode);
#else # else
tcsetattr(0, TCSANOW, &PRIVATE->sterm); tcsetattr(0, TCSANOW, &PRIVATE->sterm);
setupTerminal(false); setupTerminal(false);
#endif # endif
} }
void PIKbdListener::setActive(bool yes) { void PIKbdListener::setActive(bool yes) {
is_active = yes; is_active = yes;
if (is_active) { if (is_active) {
#ifdef WINDOWS # ifdef WINDOWS
SetConsoleMode(PRIVATE->hIn, PRIVATE->tmode); SetConsoleMode(PRIVATE->hIn, PRIVATE->tmode);
#else # else
tcsetattr(0, TCSANOW, &PRIVATE->tterm); tcsetattr(0, TCSANOW, &PRIVATE->tterm);
setupTerminal(true); setupTerminal(true);
#endif # endif
} else { } else {
#ifdef WINDOWS # ifdef WINDOWS
SetConsoleMode(PRIVATE->hIn, PRIVATE->smode); SetConsoleMode(PRIVATE->hIn, PRIVATE->smode);
#else # else
tcsetattr(0, TCSANOW, &PRIVATE->sterm); tcsetattr(0, TCSANOW, &PRIVATE->sterm);
setupTerminal(false); setupTerminal(false);
#endif # endif
} }
} }
#endif // MICRO_PIP

View File

@@ -1,8 +1,9 @@
//! \~\file pikbdlistener.h /*! \file pikbdlistener.h
//! \~\ingroup Console * \ingroup Console
//! \~\brief * \~\brief
//! \~english Console keyboard and mouse input listener * \~english Keyboard console input listener
//! \~russian Слушатель клавиатурного и мышиного консольного ввода * \~russian Консольный захват клавиатуры
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Keyboard grabber for console Keyboard grabber for console
@@ -25,14 +26,14 @@
#ifndef PIKBDLISTENER_H #ifndef PIKBDLISTENER_H
#define PIKBDLISTENER_H #define PIKBDLISTENER_H
#include "pithread.h" #include "pibase.h"
#include "pitime.h"
//! \relatesalso PIKbdListener #ifndef MICRO_PIP
//! \~\brief
//! \~english Waits until the active listener captures the configured exit key and then stops it. # include "pithread.h"
//! \~russian Ожидает, пока активный слушатель перехватит настроенную клавишу выхода, и затем останавливает его. # 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()) { \
@@ -40,107 +41,87 @@
} }
//! \~\ingroup Console
//! \~\brief
//! \~english Console input listener for keyboard and mouse events.
//! \~russian Слушатель консольного ввода для событий клавиатуры и мыши.
class PIP_EXPORT PIKbdListener: public PIThread { class PIP_EXPORT PIKbdListener: public PIThread {
PIOBJECT_SUBCLASS(PIKbdListener, PIThread); PIOBJECT_SUBCLASS(PIKbdListener, PIThread);
friend class PIConsole; friend class PIConsole;
friend class PITerminal; friend class PITerminal;
public: public:
//! \~english Keyboard keys reported as non-character codes. //! Special keyboard keys
//! \~russian Клавиши, передаваемые как несимвольные коды.
enum SpecialKey { enum SpecialKey {
Tab = 0x09 /** \~english Tab key \~russian Клавиша Tab */, Tab /** Tab key */ = 0x09,
Return = 0x0a /** \~english Enter key \~russian Клавиша Enter */, Return /** Enter key */ = 0x0a,
Esc = 0x1b /** \~english Escape key \~russian Клавиша Escape */, Esc /** Escape key */ = 0x1b,
Space = 0x20 /** \~english Space key \~russian Клавиша пробела */, Space /** Space key */ = 0x20,
Backspace = 0x7f /** \~english Backspace key \~russian Клавиша Backspace */, Backspace /** Backspace key */ = 0x7f,
UpArrow = -1 /** \~english Up arrow key \~russian Стрелка вверх */, UpArrow /** Up arrow key */ = -1,
DownArrow = -2 /** \~english Down arrow key \~russian Стрелка вниз */, DownArrow /** Down arrow key */ = -2,
RightArrow = -3 /** \~english Right arrow key \~russian Стрелка вправо */, RightArrow /** Right arrow key */ = -3,
LeftArrow = -4 /** \~english Left arrow key \~russian Стрелка влево */, LeftArrow /** Left arrow key */ = -4,
Home = -5 /** \~english Home key \~russian Клавиша Home */, Home /** Home key */ = -5,
End = -6 /** \~english End key \~russian Клавиша End */, End /** End key */ = -6,
PageUp = -7 /** \~english Page Up key \~russian Клавиша Page Up */, PageUp /** Page up key */ = -7,
PageDown = -8 /** \~english Page Down key \~russian Клавиша Page Down */, PageDown /** Page down key */ = -8,
Insert = -9 /** \~english Insert key \~russian Клавиша Insert */, Insert /** Delete key */ = -9,
Delete = -10 /** \~english Delete key \~russian Клавиша Delete */, Delete /** Delete key */ = -10,
F1 = -11 /** \~english F1 key \~russian Клавиша F1 */, F1 /** F1 key */ = -11,
F2 = -12 /** \~english F2 key \~russian Клавиша F2 */, F2 /** F2 key */ = -12,
F3 = -13 /** \~english F3 key \~russian Клавиша F3 */, F3 /** F3 key */ = -13,
F4 = -14 /** \~english F4 key \~russian Клавиша F4 */, F4 /** F4 key */ = -14,
F5 = -15 /** \~english F5 key \~russian Клавиша F5 */, F5 /** F5 key */ = -15,
F6 = -16 /** \~english F6 key \~russian Клавиша F6 */, F6 /** F6 key */ = -16,
F7 = -17 /** \~english F7 key \~russian Клавиша F7 */, F7 /** F7 key */ = -17,
F8 = -18 /** \~english F8 key \~russian Клавиша F8 */, F8 /** F8 key */ = -18,
F9 = -19 /** \~english F9 key \~russian Клавиша F9 */, F9 /** F9 key */ = -19,
F10 = -20 /** \~english F10 key \~russian Клавиша F10 */, F10 /** F10 key */ = -20,
F11 = -21 /** \~english F11 key \~russian Клавиша F11 */, F11 /** F11 key */ = -21,
F12 = -22 /** \~english F12 key \~russian Клавиша F12 */ F12 /** F12 key */ = -22
}; };
//! \~english Keyboard modifier bit flags. //! Keyboard modifiers
//! \~russian Битовые флаги модификаторов клавиатуры.
enum KeyModifier { enum KeyModifier {
Ctrl = 0x1 /** \~english Control key \~russian Клавиша Control */, Ctrl /** Control key */ = 0x1,
Shift = 0x2 /** \~english Shift key \~russian Клавиша Shift */, Shift /** Shift key */ = 0x2,
Alt = 0x4 /** \~english Alt key \~russian Клавиша Alt */, Alt /** Alt key */ = 0x4
// Meta = 0x8 /** Meta (windows) key */ // Meta /** Meta (windows) key */ = 0x8
}; };
//! \~english Combination of \a KeyModifier flags.
//! \~russian Комбинация флагов \a KeyModifier.
typedef PIFlags<KeyModifier> KeyModifiers; typedef PIFlags<KeyModifier> KeyModifiers;
//! \~english Information about one keyboard event. //! This struct contains information about pressed keyboard key
//! \~russian Информация об одном событии клавиатуры.
struct PIP_EXPORT KeyEvent { struct PIP_EXPORT KeyEvent {
//! \~english Constructs an empty event or initializes it with key and modifiers.
//! \~russian Создает пустое событие или инициализирует его клавишей и модификаторами.
KeyEvent(int k = 0, KeyModifiers m = 0) { KeyEvent(int k = 0, KeyModifiers m = 0) {
key = k; key = k;
modifiers = m; modifiers = m;
} }
//! \~english Pressed key code. It can be a character code or one of \a SpecialKey values. //! Pressed key. It can be simple \b char or special key (see PIKbdListener::SpecialKey)
//! \~russian Код нажатой клавиши. Это может быть код символа или одно из значений \a SpecialKey.
int key; int key;
//! \~english Active keyboard modifiers as a combination of \a KeyModifier flags. //! Active keyboard modifiers. It contains PIKbdListener::KeyModifier bitfields
//! \~russian Активные модификаторы клавиатуры как комбинация флагов \a KeyModifier.
KeyModifiers modifiers; KeyModifiers modifiers;
}; };
//! \~english Mouse button bit flags. //! Mouse buttons
//! \~russian Битовые флаги кнопок мыши.
enum MouseButton { enum MouseButton {
MouseLeft = 0x01 /** \~english Left button \~russian Левая кнопка */, MouseLeft /** Left button */ = 0x01,
MouseRight = 0x02 /** \~english Right button \~russian Правая кнопка */, MouseRight /** Right button */ = 0x02,
MouseMiddle = 0x04 /** \~english Middle button \~russian Средняя кнопка */ MouseMiddle /** Middle button */ = 0x04
}; };
//! \~english Mouse action kind. //! Mouse actions
//! \~russian Вид действия мыши.
enum MouseAction { enum MouseAction {
MouseButtonPress /** \~english Mouse button pressed \~russian Нажатие кнопки мыши */, MouseButtonPress /** Mouse button pressed */,
MouseButtonRelease /** \~english Mouse button released \~russian Отпускание кнопки мыши */, MouseButtonRelease /** Mouse button released */,
MouseButtonDblClick /** \~english Mouse button double-click \~russian Двойной щелчок кнопкой мыши */, MouseButtonDblClick /** Mouse button double click */,
MouseMove /** \~english Mouse moved \~russian Перемещение мыши */, MouseMove /** Mouse moved */,
MouseWheel /** \~english Mouse wheel rotated \~russian Прокрутка колеса мыши */ MouseWheel /** Mouse wheel rotated */
}; };
//! \~english Combination of pressed \a MouseButton flags.
//! \~russian Комбинация нажатых флагов \a MouseButton.
typedef PIFlags<MouseButton> MouseButtons; typedef PIFlags<MouseButton> MouseButtons;
//! \~english Information about one mouse event. //! This struct contains information about mouse action
//! \~russian Информация об одном событии мыши.
struct PIP_EXPORT MouseEvent { struct PIP_EXPORT MouseEvent {
//! \~english Constructs an event with coordinates at the origin.
//! \~russian Создает событие с координатами в начале области.
MouseEvent(MouseAction a = MouseButtonPress, MouseButtons b = 0, KeyModifiers m = 0) { MouseEvent(MouseAction a = MouseButtonPress, MouseButtons b = 0, KeyModifiers m = 0) {
x = y = 0; x = y = 0;
action = a; action = a;
@@ -148,162 +129,113 @@ public:
modifiers = m; modifiers = m;
} }
//! \~english Event X coordinate in screen space, starting from zero. //! Event X coordinate in view-space, from 0
//! \~russian Координата X события в экранном пространстве, начиная с нуля.
int x; int x;
//! \~english Event Y coordinate in screen space, starting from zero. //! Event Y coordinate in view-space, from 0
//! \~russian Координата Y события в экранном пространстве, начиная с нуля.
int y; int y;
//! \~english Mouse action kind. //! Mouse action type
//! \~russian Вид действия мыши.
MouseAction action; MouseAction action;
//! \~english Pressed mouse buttons as a combination of \a MouseButton flags. //! Pressed buttons. It contains PIKbdListener::MouseButton bitfields
//! \~russian Нажатые кнопки мыши как комбинация флагов \a MouseButton.
MouseButtons buttons; MouseButtons buttons;
//! \~english Active keyboard modifiers as a combination of \a KeyModifier flags. //! Active keyboard modifiers. It contains PIKbdListener::KeyModifier bitfields
//! \~russian Активные модификаторы клавиатуры как комбинация флагов \a KeyModifier.
KeyModifiers modifiers; KeyModifiers modifiers;
}; };
//! \~english Information about one mouse wheel event. //! This struct contains information about mouse wheel action
//! \~russian Информация об одном событии колеса мыши.
struct PIP_EXPORT WheelEvent: public MouseEvent { struct PIP_EXPORT WheelEvent: public MouseEvent {
//! \~english Constructs a wheel event with downward direction by default.
//! \~russian Создает событие колеса мыши; по умолчанию направление вниз.
WheelEvent(): MouseEvent() { direction = false; } WheelEvent(): MouseEvent() { direction = false; }
//! \~english Wheel direction: \b true for up, \b false for down. //! Wheel direction, /b true - up, /b fasle - down
//! \~russian Направление прокрутки: \b true вверх, \b false вниз.
bool direction; bool direction;
}; };
//! \~english Callback receiving a key event and user data.
//! \~russian Обратный вызов, принимающий событие клавиши и пользовательские данные.
typedef std::function<void(KeyEvent, void *)> KBFunc; typedef std::function<void(KeyEvent, void *)> KBFunc;
//! \~english Constructs a listener with optional callback, user data, and auto-start mode. //! Constructs keyboard listener with external function "slot" and custom data "data"
//! \~russian Создает слушатель с необязательным обратным вызовом, пользовательскими данными и автозапуском.
explicit PIKbdListener(KBFunc slot = 0, void * data = 0, bool startNow = true); explicit PIKbdListener(KBFunc slot = 0, void * data = 0, bool startNow = true);
//! \~english Stops the listener and restores the console state.
//! \~russian Останавливает слушатель и восстанавливает состояние консоли.
~PIKbdListener(); ~PIKbdListener();
//! \~english Returns the user data passed back with callbacks and events. //! Returns custom data
//! \~russian Возвращает пользовательские данные, передаваемые обратно в обратные вызовы и события.
void * data() { return kbddata_; } void * data() { return kbddata_; }
//! \~english Sets the user data passed back with callbacks and events. //! Set custom data to "_data"
//! \~russian Задает пользовательские данные, возвращаемые в обратных вызовах и событиях.
void setData(void * _data) { kbddata_ = _data; } void setData(void * _data) { kbddata_ = _data; }
//! \~english Sets the callback receiving both key event and user data. //! Set external function to "slot"
//! \~russian Устанавливает обратный вызов, получающий событие клавиши и пользовательские данные. void setSlot(KBFunc slot) { ret_func = slot; }
void setSlot(KBFunc slot) { ret_func = std::move(slot); }
//! \~english Sets the callback that only receives the key event and ignores user data. //! Set external function to "slot"
//! \~russian Устанавливает обратный вызов, получающий только событие клавиши и игнорирующий пользовательские данные.
void setSlot(std::function<void(KeyEvent)> slot) { void setSlot(std::function<void(KeyEvent)> slot) {
ret_func = [slot](KeyEvent e, void *) { slot(e); }; ret_func = [slot](KeyEvent e, void *) { slot(e); };
} }
//! \~english Returns whether the exit key is currently being captured. //! Returns if exit key if awaiting
//! \~russian Возвращает, включен ли сейчас перехват клавиши выхода.
bool exitCaptured() const { return exit_enabled; } bool exitCaptured() const { return exit_enabled; }
//! \~english Returns the configured exit key. The default is \c 'Q'. //! Returns exit key, default 'Q'
//! \~russian Возвращает настроенную клавишу выхода. По умолчанию это \c 'Q'.
int exitKey() const { return exit_key; } int exitKey() const { return exit_key; }
//! \~english Returns the double-click interval in milliseconds.
//! \~russian Возвращает интервал двойного щелчка в миллисекундах.
double doubleClickInterval() const { return dbl_interval; } double doubleClickInterval() const { return dbl_interval; }
//! \~english Sets the mouse double-click interval in milliseconds.
//! \~russian Задает интервал двойного щелчка мыши в миллисекундах.
void setDoubleClickInterval(double v) { dbl_interval = v; } void setDoubleClickInterval(double v) { dbl_interval = v; }
//! \~english Performs one low-level polling cycle and dispatches decoded input events.
//! \~russian Выполняет один цикл низкоуровневого опроса и отправляет декодированные события ввода.
void readKeyboard(); void readKeyboard();
//! \~english Requests listener shutdown and interrupts a pending wait for console input.
//! \~russian Запрашивает остановку слушателя и прерывает текущее ожидание консольного ввода.
void stop(); void stop();
//! \~english Requests shutdown and waits until console capture is restored or the timeout expires.
//! \~russian Запрашивает остановку и ждет восстановления режима консоли до истечения таймаута.
bool stopAndWait(PISystemTime timeout = {}); bool stopAndWait(PISystemTime timeout = {});
//! \~english Returns whether low-level console capture is currently enabled. //! Returns if keyboard listening is active (not running!)
//! \~russian Возвращает, включен ли сейчас низкоуровневый захват консольного ввода.
bool isActive() { return is_active; } bool isActive() { return is_active; }
//! \handlers
//! \{
//! \fn void enableExitCapture(int key = 'Q')
//! \~english Enables capture of exit key \a key.
//! \~russian Включает перехват клавиши выхода \a key.
EVENT_HANDLER(void, enableExitCapture) { enableExitCapture('Q'); } EVENT_HANDLER(void, enableExitCapture) { enableExitCapture('Q'); }
EVENT_HANDLER1(void, enableExitCapture, int, key) { EVENT_HANDLER1(void, enableExitCapture, int, key) {
exit_enabled = true; exit_enabled = true;
exit_key = key; exit_key = key;
} }
//! \fn void disableExitCapture()
//! \~english Disables exit key capture.
//! \~russian Выключает перехват клавиши выхода.
EVENT_HANDLER(void, disableExitCapture) { exit_enabled = false; } EVENT_HANDLER(void, disableExitCapture) { exit_enabled = false; }
//! \fn void setActive(bool yes = true)
//! \~english Enables or disables low-level console input capture.
//! \~russian Включает или выключает низкоуровневый захват консольного ввода.
EVENT_HANDLER(void, setActive) { setActive(true); } EVENT_HANDLER(void, setActive) { setActive(true); }
EVENT_HANDLER1(void, setActive, bool, yes); EVENT_HANDLER1(void, setActive, bool, yes);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void *, data);
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void *, data);
//! \handlers
//! \{
//! \fn void enableExitCapture(int key = 'Q')
//! \brief Enable exit key "key" awaiting
//! \fn void disableExitCapture()
//! \brief Disable exit key awaiting
//! \fn void setActive(bool yes = true)
//! \brief Set keyboard listening is active or not
//! \} //! \}
//! \events //! \events
//! \{ //! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data) //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \~english Raised when a key event is decoded. \a data is the user data pointer. //! \brief Raise on key "key" pressed, "data" is custom data
//! \~russian Вызывается, когда декодировано событие клавиши. \a data содержит указатель на пользовательские данные.
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
//! \fn void mouseEvent(PIKbdListener::MouseEvent mouse, void * data)
//! \~english Raised when a mouse button or move event is decoded. \a data is the user data pointer.
//! \~russian Вызывается, когда декодировано событие кнопки мыши или перемещения. \a data содержит указатель на пользовательские данные.
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void *, data);
//! \fn void wheelEvent(PIKbdListener::WheelEvent wheel, void * data)
//! \~english Raised when a mouse wheel event is decoded. \a data is the user data pointer.
//! \~russian Вызывается, когда декодировано событие колеса мыши. \a data содержит указатель на пользовательские данные.
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void *, data);
//! \} //! \}
//! \~english Returns the listener instance currently registered by the console subsystem.
//! \~russian Возвращает экземпляр слушателя, который сейчас зарегистрирован консольной подсистемой.
static PIKbdListener * instance() { return _object; }
//! \~english Becomes \b true after the configured exit key is captured.
//! \~russian Становится \b true после перехвата настроенной клавиши выхода.
static bool exiting; static bool exiting;
static PIKbdListener * instance() { return _object; }
private: private:
void begin() override; void begin() override;
void run() override { readKeyboard(); } void run() override { readKeyboard(); }
void end() override; void end() override;
#ifndef WINDOWS # ifndef WINDOWS
struct PIP_EXPORT EscSeq { struct PIP_EXPORT EscSeq {
const char * seq; const char * seq;
int key; int key;
@@ -323,7 +255,7 @@ private:
}; };
static const EscSeq esc_seq[]; static const EscSeq esc_seq[];
#endif # endif
PRIVATE_DECLARATION(PIP_EXPORT) PRIVATE_DECLARATION(PIP_EXPORT)
KBFunc ret_func; KBFunc ret_func;
@@ -340,16 +272,16 @@ private:
//! \relatesalso PIBinaryStream //! \relatesalso PIBinaryStream
//! \~english Store operator for MouseEvent. //! \~english Store operator
//! \~russian Оператор сохранения для MouseEvent. //! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIKbdListener::MouseEvent) { BINARY_STREAM_WRITE(PIKbdListener::MouseEvent) {
s << v.x << v.y << v.action << v.buttons << v.modifiers; s << v.x << v.y << v.action << v.buttons << v.modifiers;
return s; return s;
} }
//! \relatesalso PIBinaryStream //! \relatesalso PIBinaryStream
//! \~english Restore operator for MouseEvent. //! \~english Restore operator
//! \~russian Оператор извлечения для MouseEvent. //! \~russian Оператор извлечения
BINARY_STREAM_READ(PIKbdListener::MouseEvent) { BINARY_STREAM_READ(PIKbdListener::MouseEvent) {
s >> v.x >> v.y >> v.action >> v.buttons >> v.modifiers; s >> v.x >> v.y >> v.action >> v.buttons >> v.modifiers;
return s; return s;
@@ -357,16 +289,16 @@ BINARY_STREAM_READ(PIKbdListener::MouseEvent) {
//! \relatesalso PIBinaryStream //! \relatesalso PIBinaryStream
//! \~english Store operator for WheelEvent. //! \~english Store operator
//! \~russian Оператор сохранения для WheelEvent. //! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIKbdListener::WheelEvent) { BINARY_STREAM_WRITE(PIKbdListener::WheelEvent) {
s << (*(PIKbdListener::MouseEvent *)&v) << v.direction; s << (*(PIKbdListener::MouseEvent *)&v) << v.direction;
return s; return s;
} }
//! \relatesalso PIBinaryStream //! \relatesalso PIBinaryStream
//! \~english Restore operator for WheelEvent. //! \~english Restore operator
//! \~russian Оператор извлечения для WheelEvent. //! \~russian Оператор извлечения
BINARY_STREAM_READ(PIKbdListener::WheelEvent) { BINARY_STREAM_READ(PIKbdListener::WheelEvent) {
s >> (*(PIKbdListener::MouseEvent *)&v) >> v.direction; s >> (*(PIKbdListener::MouseEvent *)&v) >> v.direction;
return s; return s;
@@ -377,4 +309,5 @@ REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent)
REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent) REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent)
REGISTER_PIVARIANTSIMPLE(PIKbdListener::WheelEvent) REGISTER_PIVARIANTSIMPLE(PIKbdListener::WheelEvent)
#endif // MICRO_PIP
#endif // PIKBDLISTENER_H #endif // PIKBDLISTENER_H

View File

@@ -1,8 +1,9 @@
//! \~\file piscreen.h /*! \file piscreen.h
//! \~\ingroup Console * \ingroup Console
//! \~\brief * \~\brief
//! \~english Console screen manager and tile host * \~english Console tiling manager
//! \~russian Менеджер консольного экрана и контейнер тайлов * \~russian Консольный тайловый менеджер
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console GUI Console GUI
@@ -30,10 +31,6 @@
#include "piscreentile.h" #include "piscreentile.h"
//! \~\ingroup Console
//! \~\brief
//! \~english Console screen manager with tile layout, drawing, and input routing.
//! \~russian Менеджер консольного экрана с раскладкой тайлов, отрисовкой и маршрутизацией ввода.
class PIP_CONSOLE_EXPORT PIScreen class PIP_CONSOLE_EXPORT PIScreen
: public PIThread : public PIThread
, public PIScreenTypes::PIScreenBase { , public PIScreenTypes::PIScreenBase {
@@ -41,122 +38,69 @@ class PIP_CONSOLE_EXPORT PIScreen
class SystemConsole; class SystemConsole;
public: public:
//! \~english Constructs a screen with an internal keyboard listener, optional callback, and auto-start mode. //! Constructs %PIScreen with key handler "slot" and if "startNow" start it
//! \~russian Создает экран со встроенным слушателем клавиатуры, необязательным обратным вызовом и режимом автозапуска.
//! \~\details
//! \~english Constructs a new PIScreen instance with optional immediate start.
//! \~russian Создает новый экземпляр PIScreen с опциональным немедленным запуском.
//! \~\param startNow
//! \~english Start immediately if true.
//! \~russian Запустить немедленно, если true.
//! \~\param slot
//! \~english Keyboard handler function.
//! \~russian Функция обработчика клавиатуры.
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0); PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
//! \~english Destroys PIScreen and cleans up resources.
//! \~russian Уничтожает PIScreen и очищает ресурсы.
~PIScreen(); ~PIScreen();
//! \~english Enables catching the exit key (default is 'Q') to stop the screen. //! Directly call function from \a PIKbdListener
//! \~russian Включает захват клавиши выхода (по умолчанию 'Q') для остановки экрана.
void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); } void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); }
//! \~english Disables catching the exit key. //! Directly call function from \a PIKbdListener
//! \~russian Отключает захват клавиши выхода.
void disableExitCapture() { listener->disableExitCapture(); } void disableExitCapture() { listener->disableExitCapture(); }
//! \~english Returns whether exit key capture is enabled. //! Directly call function from \a PIKbdListener
//! \~russian Возвращает, включен ли перехват клавиши выхода.
bool exitCaptured() const { return listener->exitCaptured(); } bool exitCaptured() const { return listener->exitCaptured(); }
//! \~english Returns the configured exit key. //! Directly call function from \a PIKbdListener
//! \~russian Возвращает настроенную клавишу выхода.
int exitKey() const { return listener->exitKey(); } int exitKey() const { return listener->exitKey(); }
//! \~english Returns the current console width in characters.
//! \~russian Возвращает текущую ширину консоли в символах.
int windowWidth() const { return console.width; } int windowWidth() const { return console.width; }
//! \~english Returns the current console height in characters.
//! \~russian Возвращает текущую высоту консоли в символах.
int windowHeight() const { return console.height; } int windowHeight() const { return console.height; }
//! \~english Returns whether mouse hit-testing and routing are enabled.
//! \~russian Возвращает, включены ли проверка попадания и маршрутизация событий мыши.
bool isMouseEnabled() const { return mouse_; } bool isMouseEnabled() const { return mouse_; }
//! \~english Enables or disables mouse routing and tile hit-testing.
//! \~russian Включает или выключает маршрутизацию мыши и проверку попадания по тайлам.
void setMouseEnabled(bool on); void setMouseEnabled(bool on);
//! \~english Returns the root tile covering the whole screen.
//! \~russian Возвращает корневой тайл, покрывающий весь экран.
PIScreenTile * rootTile() { return &root; } PIScreenTile * rootTile() { return &root; }
//! \~english Searches the root tile subtree by object name.
//! \~russian Ищет тайл по имени объекта в поддереве корневого тайла.
//! \~\return
//! \~english Tile pointer if found, otherwise nullptr.
//! \~russian Указатель на тайл, если найден, иначе nullptr.
PIScreenTile * tileByName(const PIString & name); PIScreenTile * tileByName(const PIString & name);
//! \~english Sets a dialog tile drawn above the root tree, centered on screen, and focused first. Pass \c nullptr to remove it.
//! \~russian Задает диалоговый тайл, рисуемый поверх корневого дерева, центрируемый на экране и первым получающий фокус. Передайте \c
//! nullptr, чтобы убрать его.
void setDialogTile(PIScreenTile * t); void setDialogTile(PIScreenTile * t);
//! \~english Returns the currently active dialog tile or \c nullptr.
//! \~russian Возвращает активный диалоговый тайл или \c nullptr.
PIScreenTile * dialogTile() const { return tile_dialog; } PIScreenTile * dialogTile() const { return tile_dialog; }
//! \~english Returns the drawer used to fill the off-screen cell buffer for the next frame.
//! \~russian Возвращает рисовальщик, используемый для заполнения внеэкранного буфера ячеек следующего кадра.
PIScreenDrawer * drawer() { return &drawer_; } PIScreenDrawer * drawer() { return &drawer_; }
//! \~english Clears the off-screen cell buffer. The terminal is updated on the next draw cycle.
//! \~russian Очищает внеэкранный буфер ячеек. Терминал обновится на следующем цикле отрисовки.
void clear() { drawer_.clear(); } void clear() { drawer_.clear(); }
//! \~english Resizes the internal console buffers used for subsequent frames.
//! \~russian Изменяет размер внутренних консольных буферов, используемых в следующих кадрах.
void resize(int w, int h) { console.resize(w, h); } void resize(int w, int h) { console.resize(w, h); }
EVENT_HANDLER0(void, waitForFinish);
EVENT_HANDLER0(void, start) { start(false); }
EVENT_HANDLER1(void, start, bool, wait);
EVENT_HANDLER0(void, stop) { stop(false); }
EVENT_HANDLER1(void, stop, bool, clear);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e);
//! \handlers //! \handlers
//! \{ //! \{
//! \fn void waitForFinish() //! \fn void waitForFinish()
//! \~english Blocks until the captured exit key is pressed and then stops the screen. //! \brief block until finished (exit key will be pressed)
//! \~russian Блокирует выполнение, пока не будет нажата перехватываемая клавиша выхода, затем останавливает экран.
EVENT_HANDLER0(void, waitForFinish);
//! \fn void start(bool wait = false) //! \fn void start(bool wait = false)
//! \~english Starts the screen thread and optionally waits until the configured exit key is captured. //! \brief Start console output and if "wait" block until finished (exit key will be pressed)
//! \~russian Запускает поток экрана и при необходимости ждет, пока не будет перехвачена настроенная клавиша выхода.
EVENT_HANDLER0(void, start) { start(false); }
EVENT_HANDLER1(void, start, bool, wait);
//! \fn void stop(bool clear = false) //! \fn void stop(bool clear = false)
//! \~english Stops the screen thread, restores console state, and optionally clears the terminal. //! \brief Stop console output and if "clear" clear the screen
//! \~russian Останавливает поток экрана, восстанавливает состояние консоли и при необходимости очищает терминал.
EVENT_HANDLER0(void, stop) { stop(false); }
EVENT_HANDLER1(void, stop, bool, clear);
//! \} //! \}
//! \events //! \events
//! \{ //! \{
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data) //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
//! \~english Raised when a key was not consumed by focus navigation or the focused tile. \a data is the screen user data pointer. //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
//! \~russian Вызывается, когда клавиша не была поглощена навигацией фокуса или тайлом с фокусом. \a data содержит пользовательский
//! указатель экрана.
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
//! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e) //! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e)
//! \~english Raised when a tile reports a custom event \a e. //! \brief Raise on some event "e" from tile "tile"
//! \~russian Вызывается, когда тайл сообщает пользовательское событие \a e.
EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e);
//! \} //! \}

View File

@@ -0,0 +1,82 @@
/*! \file piscreenconsole.h
* \ingroup Console
* \~\brief
* \~english Tile for PIScreen with PIConsole API
* \~russian Тайл для PIScreen с API PIConsole
*/
/*
PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISCREENCONSOLE_H
#define PISCREENCONSOLE_H
#include "pip_console_export.h"
#include "piscreentiles.h"
/// NOTE: incomplete class
/// TODO: write TileVars
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
public:
TileVars(const PIString & n = PIString());
protected:
struct PIP_CONSOLE_EXPORT Variable {
Variable() {
nx = ny = type = offset = bitFrom = bitCount = size = 0;
format = PIScreenTypes::CellFormat();
ptr = 0;
}
bool isEmpty() const { return (ptr == 0); }
PIString name;
PIScreenTypes::CellFormat format;
int nx;
int ny;
int type;
int offset;
int bitFrom;
int bitCount;
int size;
const void * ptr;
/*void operator =(const Variable & src) {
name = src.name;
format = src.format;
nx = src.nx;
ny = src.ny;
type = src.type;
offset = src.offset;
bitFrom = src.bitFrom;
bitCount = src.bitCount;
size = src.size;
ptr = src.ptr;
}*/
};
PIVector<Variable> variables;
PIScreenTypes::Alignment alignment;
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
};
class PIP_CONSOLE_EXPORT PIScreenConsoleTile: public PIScreenTile {
public:
PIScreenConsoleTile();
};
#endif // PISCREENCONSOLE_H

View File

@@ -1,8 +1,9 @@
//! \~\file piscreendrawer.h /*! \file piscreendrawer.h
//! \~\ingroup Console * \ingroup Console
//! \~\brief * \~\brief
//! \~english Drawing helpers for %PIScreen cell buffers * \~english Drawer for PIScreen
//! \~russian Вспомогательные средства рисования для буферов ячеек %PIScreen * \~russian Отрисовщик для PIScreen
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Drawer for PIScreen Drawer for PIScreen
@@ -29,54 +30,31 @@
#include "piscreentypes.h" #include "piscreentypes.h"
#include "pistring.h" #include "pistring.h"
//! \~\ingroup Console
//! \~\brief
//! \~english Helper that draws primitives and text into a %PIScreen cell buffer.
//! \~russian Вспомогательный класс для рисования примитивов и текста в буфере ячеек %PIScreen.
//! \~\details
//! \~english Provides methods for drawing primitives such as pixels, lines, rectangles, and text on console screen.
//! \~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:
//! \~english Predefined pseudographic and widget-state symbols.
//! \~russian Предопределенные псевдографические символы и символы состояний виджетов.
//! \~\details
//! \~english Defines available characters for drawing ASCII art primitives.
//! \~russian Определяет доступные символы для рисования ASCII-арта примитивов.
enum ArtChar { enum ArtChar {
LineVertical = 1 /** \~english Vertical line symbol. \~russian Символ вертикальной линии. */, LineVertical = 1,
LineHorizontal /** \~english Horizontal line symbol. \~russian Символ горизонтальной линии. */, LineHorizontal,
Cross /** \~english Line intersection symbol. \~russian Символ пересечения линий. */, Cross,
CornerTopLeft /** \~english Top-left frame corner. \~russian Левый верхний угол рамки. */, CornerTopLeft,
CornerTopRight /** \~english Top-right frame corner. \~russian Правый верхний угол рамки. */, CornerTopRight,
CornerBottomLeft /** \~english Bottom-left frame corner. \~russian Левый нижний угол рамки. */, CornerBottomLeft,
CornerBottomRight /** \~english Bottom-right frame corner. \~russian Правый нижний угол рамки. */, CornerBottomRight,
Unchecked /** \~english Unchecked box symbol. \~russian Символ неотмеченного флажка. */, Unchecked,
Checked /** \~english Checked box symbol. \~russian Символ отмеченного флажка. */ Checked
}; };
//! \~english Clears the whole target buffer.
//! \~russian Очищает весь целевой буфер.
void clear(); void clear();
//! \~english Clears a rectangular area in the target buffer with spaces.
//! \~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, ' '); }
//! \~english Draws one cell at position `(x, y)`.
//! \~russian Рисует одну ячейку в позиции `(x, y)`.
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);
//! \~english Draws a line between two points.
//! \~russian Рисует линию между двумя точками.
void drawLine(int x0, void drawLine(int x0,
int y0, int y0,
int x1, int x1,
@@ -85,9 +63,6 @@ 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);
//! \~english Draws a rectangular outline with the specified symbol.
//! \~russian Рисует контур прямоугольника указанным символом.
void drawRect(int x0, void drawRect(int x0,
int y0, int y0,
int x1, int x1,
@@ -96,9 +71,6 @@ 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);
//! \~english Draws a frame using predefined art symbols.
//! \~russian Рисует рамку предопределенными псевдографическими символами.
void drawFrame(int x0, void drawFrame(int x0,
int y0, int y0,
int x1, int x1,
@@ -106,18 +78,12 @@ 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);
//! \~english Draws text starting at `(x, y)`.
//! \~russian Рисует текст, начиная с позиции `(x, y)`.
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);
//! \~english Fills a rectangular area with one symbol and cell format.
//! \~russian Заполняет прямоугольную область одним символом и форматом ячейки.
void fillRect(int x0, void fillRect(int x0,
int y0, int y0,
int x1, int x1,
@@ -126,17 +92,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);
//! \~english Copies a cell matrix into a rectangular area.
//! \~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);
//! \~english Returns a predefined art symbol.
//! \~russian Возвращает предопределенный псевдографический символ.
PIChar artChar(const ArtChar type) const { return arts_.value(type, PIChar(' ')); } PIChar artChar(const ArtChar type) const { return arts_.value(type, PIChar(' ')); }
//! \~english Fills an arbitrary cell buffer with default cells.
//! \~russian Заполняет произвольный буфер ячеек значениями по умолчанию.
static void clear(PIVector<PIVector<PIScreenTypes::Cell>> & cells); static void clear(PIVector<PIVector<PIScreenTypes::Cell>> & cells);
private: private:

View File

@@ -1,8 +1,9 @@
//! \~\file piscreentile.h /*! \file piscreentile.h
//! \~\ingroup Console * \ingroup Console
//! \brief * \~\brief
//! \~english Basic PIScreen tile * \~english Basic PIScreen tile
//! \~russian Базовый тайл для PIScreen * \~russian Базовый тайл для PIScreen
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile
@@ -31,74 +32,27 @@
class PIScreenDrawer; class PIScreenDrawer;
//! \~\ingroup Console
//! \~\brief
//! \~english Base tile in the console screen tree.
//! \~russian Базовый тайл в дереве консольного экрана.
//! \details
//! \~english Base class for all screen tiles providing layout and event handling.
//! \~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:
//! \~english Constructs a tile with name, child layout direction, and size policy.
//! \~russian Создает тайл с именем, направлением раскладки дочерних элементов и политикой размера.
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);
//! \~english Destroys the tile and its owned child tiles.
//! \~russian Уничтожает тайл и принадлежащие ему дочерние тайлы.
virtual ~PIScreenTile(); virtual ~PIScreenTile();
//! \~english Adds child tile \a t, makes this tile its parent, and attaches the subtree to the same screen bridge.
//! \~russian Добавляет дочерний тайл \a t, делает этот тайл его родителем и подключает поддерево к тому же экранному мосту.
void addTile(PIScreenTile * t); void addTile(PIScreenTile * t);
//! \~english Detaches child tile \a t without deleting it and removes its screen association.
//! \~russian Отсоединяет дочерний тайл \a t без удаления и снимает его связь с экраном.
void takeTile(PIScreenTile * t); void takeTile(PIScreenTile * t);
//! \~english Removes and deletes child tile \a t.
//! \~russian Удаляет дочерний тайл \a t и уничтожает его.
void removeTile(PIScreenTile * t); void removeTile(PIScreenTile * t);
//! \~english Returns the parent tile or \c nullptr for the root.
//! \~russian Возвращает родительский тайл или \c nullptr для корня.
PIScreenTile * parentTile() const { return parent; } PIScreenTile * parentTile() const { return parent; }
//! \~english Returns all descendant tiles. Hidden tiles can be skipped with \a only_visible.
//! \~russian Возвращает все дочерние тайлы по дереву. Скрытые тайлы можно пропустить через \a only_visible.
PIVector<PIScreenTile *> children(bool only_visible = false); PIVector<PIScreenTile *> children(bool only_visible = false);
//! \~english Returns the first visible direct child covering screen point \a x, \a y.
//! \~russian Возвращает первый видимый прямой дочерний тайл, покрывающий экранную точку \a x, \a y.
PIScreenTile * childUnderMouse(int x, int y); PIScreenTile * childUnderMouse(int x, int y);
//! \~english Makes the tile visible for subsequent layout, hit-testing, and drawing passes.
//! \~russian Делает тайл видимым для последующих проходов компоновки, проверки попадания и отрисовки.
void show() { visible = true; } void show() { visible = true; }
//! \~english Hides the tile from layout, hit-testing, and drawing passes.
//! \~russian Скрывает тайл из проходов компоновки, проверки попадания и отрисовки.
void hide() { visible = false; } void hide() { visible = false; }
//! \~english Requests focus for this tile if it is attached to a screen and allows focus.
//! \~russian Запрашивает фокус для этого тайла, если он подключен к экрану и допускает получение фокуса.
void setFocus(); void setFocus();
//! \~english Returns whether this tile currently owns focus.
//! \~russian Возвращает, принадлежит ли этому тайлу текущий фокус.
bool hasFocus() const { return has_focus; } bool hasFocus() const { return has_focus; }
//! \~english Sets all margins to \a m cells.
//! \~russian Устанавливает все отступы в \a m ячеек.
void setMargins(int m) { marginLeft = marginRight = marginTop = marginBottom = m; } void setMargins(int m) { marginLeft = marginRight = marginTop = marginBottom = m; }
//! \~english Sets left, right, top, and bottom margins in cells.
//! \~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;
@@ -106,129 +60,52 @@ public:
marginBottom = b; marginBottom = b;
} }
//! \~english Returns the tile X coordinate in screen space.
//! \~russian Возвращает координату X тайла в экранном пространстве.
int x() const { return x_; } int x() const { return x_; }
//! \~english Returns the tile Y coordinate in screen space.
//! \~russian Возвращает координату Y тайла в экранном пространстве.
int y() const { return y_; } int y() const { return y_; }
//! \~english Returns the current tile width in cells.
//! \~russian Возвращает текущую ширину тайла в ячейках.
int width() const { return width_; } int width() const { return width_; }
//! \~english Returns the current tile height in cells.
//! \~russian Возвращает текущую высоту тайла в ячейках.
int height() const { return height_; } int height() const { return height_; }
//! \~english Direction used to lay out child tiles.
//! \~russian Направление раскладки дочерних тайлов.
PIScreenTypes::Direction direction; PIScreenTypes::Direction direction;
//! \~english Size policy used by the parent during layout.
//! \~russian Политика размера, используемая родителем при компоновке.
PIScreenTypes::SizePolicy size_policy; PIScreenTypes::SizePolicy size_policy;
//! \~english Focus and navigation flags for the tile.
//! \~russian Флаги фокуса и навигации для тайла.
PIScreenTypes::FocusFlags focus_flags; PIScreenTypes::FocusFlags focus_flags;
//! \~english Background format used to prefill the tile area before drawing.
//! \~russian Формат фона, которым предварительно заполняется область тайла перед отрисовкой.
PIScreenTypes::CellFormat back_format; PIScreenTypes::CellFormat back_format;
//! \~english Background symbol used to prefill the tile area before drawing.
//! \~russian Символ фона, которым предварительно заполняется область тайла перед отрисовкой.
PIChar back_symbol; PIChar back_symbol;
//! \~english Minimum size limits accepted during layout.
//! \~russian Минимальные ограничения размера, допускаемые при компоновке.
int minimumWidth, minimumHeight; int minimumWidth, minimumHeight;
//! \~english Maximum size limits accepted during layout.
//! \~russian Максимальные ограничения размера, допускаемые при компоновке.
int maximumWidth, maximumHeight; int maximumWidth, maximumHeight;
//! \~english Outer margins in cells.
//! \~russian Внешние отступы в ячейках.
int marginLeft, marginRight, marginTop, marginBottom; int marginLeft, marginRight, marginTop, marginBottom;
//! \~english Spacing between visible child tiles in cells.
//! \~russian Интервал между видимыми дочерними тайлами в ячейках.
int spacing; int spacing;
//! \~english Whether the tile participates in layout, hit-testing, and drawing.
//! \~russian Участвует ли тайл в компоновке, проверке попадания и отрисовке.
bool visible; bool visible;
protected: protected:
//! \~english Returns the preferred tile size in \a w and \a h. The base implementation derives it from visible children, spacing, and margins. //! Returns desired tile size in "w" and "h"
//! \~russian Возвращает предпочтительный размер тайла в \a w и \a h. Базовая реализация вычисляет его по видимым дочерним тайлам, интервалам и отступам.
virtual void sizeHint(int & w, int & h) const; virtual void sizeHint(int & w, int & h) const;
//! \~english Called after the tile size changes to \a w by \a h during layout. //! Tile has been resized to "w"x"h"
//! \~russian Вызывается после изменения размера тайла до \a w на \a h во время компоновки.
virtual void resizeEvent(int w, int h) {} virtual void resizeEvent(int w, int h) {}
//! \~english Draws the tile with drawer \a d in screen coordinates. //! Draw tile with drawer "d" in world-space coordinates
//! \~russian Отрисовывает тайл через рисовальщик \a d в экранных координатах.
virtual void drawEvent(PIScreenDrawer * d) {} virtual void drawEvent(PIScreenDrawer * d) {}
//! \~english Handles keyboard input and returns \b true when the event is consumed. //! Return "true" if you process key
//! \~russian Обрабатывает клавиатурный ввод и возвращает \b true, если событие поглощено.
virtual bool keyEvent(PIKbdListener::KeyEvent key) { return false; } virtual bool keyEvent(PIKbdListener::KeyEvent key) { return false; }
//! \~english Handles mouse input and returns \b true when the event is consumed. //! Return "true" if you process event
//! \~russian Обрабатывает событие мыши и возвращает \b true, если событие поглощено.
virtual bool mouseEvent(PIKbdListener::MouseEvent me) { return false; } virtual bool mouseEvent(PIKbdListener::MouseEvent me) { return false; }
//! \~english Handles mouse wheel input and returns \b true when the event is consumed. //! Return "true" if you process wheel
//! \~russian Обрабатывает колесо мыши и возвращает \b true, если событие поглощено.
virtual bool wheelEvent(PIKbdListener::WheelEvent we) { return false; } virtual bool wheelEvent(PIKbdListener::WheelEvent we) { return false; }
//! \~english Raises tile event
//! \~russian Вызывает событие тайла
void raiseEvent(PIScreenTypes::TileEvent e); void raiseEvent(PIScreenTypes::TileEvent e);
//! \~english Sets screen reference
//! \~russian Устанавливает ссылку на экран
void setScreen(PIScreenTypes::PIScreenBase * s); void setScreen(PIScreenTypes::PIScreenBase * s);
//! \~english Deletes all owned child tiles.
//! \~russian Удаляет все принадлежащие дочерние тайлы.
void deleteChildren(); void deleteChildren();
//! \~english Draws background, tile contents, and then child tiles.
//! \~russian Отрисовывает фон, содержимое тайла и затем дочерние тайлы.
void drawEventInternal(PIScreenDrawer * d); void drawEventInternal(PIScreenDrawer * d);
//! \~english Recomputes child geometry according to size hints, margins, and policies.
//! \~russian Пересчитывает геометрию дочерних тайлов по предпочтительным размерам, отступам и политикам.
void layout(); void layout();
//! \~english Returns whether this tile should participate in automatic layout. Tiles with policy \a PIScreenTypes::Ignore are skipped.
//! \~russian Возвращает, должен ли тайл участвовать в автоматической компоновке. Тайлы с политикой \a PIScreenTypes::Ignore пропускаются.
bool needLayout() { return size_policy != PIScreenTypes::Ignore; } bool needLayout() { return size_policy != PIScreenTypes::Ignore; }
//! \~english Owned direct child tiles.
//! \~russian Принадлежащие прямые дочерние тайлы.
PIVector<PIScreenTile *> tiles; PIVector<PIScreenTile *> tiles;
//! \~english Parent tile or \c nullptr for the root or detached tiles.
//! \~russian Родительский тайл или \c nullptr для корня и отсоединенных тайлов.
PIScreenTile * parent; PIScreenTile * parent;
//! \~english Screen pointer, receiving tile notifications.
//! \~russian Ссылка на экран, принимающий уведомления от тайла.
PIScreenTypes::PIScreenBase * screen; PIScreenTypes::PIScreenBase * screen;
//! \~english Tile position and size in screen cells.
//! \~russian Положение и размер тайла в экранных ячейках.
int x_, y_, width_, height_; int x_, y_, width_, height_;
//! \~english Whether this tile currently owns focus.
//! \~russian Принадлежит ли этому тайлу текущий фокус.
bool has_focus; bool has_focus;
private: private:

View File

@@ -1,11 +1,9 @@
//! \~\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
@@ -32,36 +30,15 @@
#include "piscreentile.h" #include "piscreentile.h"
//! \~\ingroup Console
//! \~\brief
//! \~english Simple text tile with per-row formatting.
//! \~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:
//! \~english Row text with cell format.
//! \~russian Текст строки с форматом ячеек.
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
//! \~english Constructs an empty text tile.
//! \~russian Создает пустой текстовый тайл.
TileSimple(const PIString & n = PIString()); TileSimple(const PIString & n = PIString());
//! \~english Constructs a text tile with one row.
//! \~russian Создает текстовый тайл с одной строкой.
TileSimple(const Row & r); TileSimple(const Row & r);
//! \~english Destroys the text tile.
//! \~russian Уничтожает текстовый тайл.
virtual ~TileSimple() {} virtual ~TileSimple() {}
//! \~english Rows displayed by the tile.
//! \~russian Строки, отображаемые тайлом.
PIVector<Row> content; PIVector<Row> content;
//! \~english Horizontal text alignment inside the tile.
//! \~russian Горизонтальное выравнивание текста внутри тайла.
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
protected: protected:
@@ -72,49 +49,19 @@ protected:
class TileList; class TileList;
//! \~\ingroup Console
//! \~\brief
//! \~english Scroll bar tile used by list-like widgets.
//! \~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:
//! \~english Constructs a scroll bar tile.
//! \~russian Создает тайл полосы прокрутки.
TileScrollBar(const PIString & n = PIString()); TileScrollBar(const PIString & n = PIString());
//! \~english Destroys the scroll bar tile.
//! \~russian Уничтожает тайл полосы прокрутки.
virtual ~TileScrollBar() {} virtual ~TileScrollBar() {}
//! \~english Sets the minimum scroll value.
//! \~russian Устанавливает минимальное значение прокрутки.
void setMinimum(int v); void setMinimum(int v);
//! \~english Sets the maximum scroll value.
//! \~russian Устанавливает максимальное значение прокрутки.
void setMaximum(int v); void setMaximum(int v);
//! \~english Sets the current scroll value.
//! \~russian Устанавливает текущее значение прокрутки.
void setValue(int v); void setValue(int v);
//! \~english Returns the minimum scroll value.
//! \~russian Возвращает минимальное значение прокрутки.
int minimum() const { return minimum_; } int minimum() const { return minimum_; }
//! \~english Returns the maximum scroll value.
//! \~russian Возвращает максимальное значение прокрутки.
int maximum() const { return maximum_; } int maximum() const { return maximum_; }
//! \~english Returns the current scroll value.
//! \~russian Возвращает текущее значение прокрутки.
int value() const { return value_; } int value() const { return value_; }
//! \~english Thickness of the drawn bar in cells, perpendicular to the scroll direction.
//! \~russian Толщина отрисовываемой полосы в ячейках поперек направления прокрутки.
int thickness; int thickness;
protected: protected:
@@ -127,68 +74,29 @@ protected:
}; };
//! \~\ingroup Console
//! \~\brief
//! \~english Scrollable list tile with optional row selection.
//! \~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:
//! \~english Selection policy for list rows.
//! \~russian Режим выбора строк списка.
enum SelectionMode { enum SelectionMode {
NoSelection /** \~english Rows are not selectable. \~russian Выбор строк отключен. */, NoSelection,
SingleSelection /** \~english At most one row can be selected. \~russian Можно выбрать не более одной строки. */, SingleSelection,
MultiSelection /** \~english Multiple rows can be selected. \~russian Можно выбрать несколько строк. */ MultiSelection
}; };
//! \~english Events emitted by the list tile.
//! \~russian События, генерируемые тайлом списка.
enum EventType { enum EventType {
SelectionChanged /** \~english Selection set changed. \~russian Изменился набор выбранных строк. */, SelectionChanged,
RowPressed /** \~english Current row was activated; event data stores the row index. \~russian Текущая строка была активирована; данные события содержат индекс строки. */ RowPressed
}; };
//! \~english Constructs a list tile with the specified selection mode.
//! \~russian Создает тайл списка с указанным режимом выбора.
TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection); TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection);
//! \~english Destroys the list tile.
//! \~russian Уничтожает тайл списка.
virtual ~TileList() {} virtual ~TileList() {}
//! \~english Row text with cell format.
//! \~russian Текст строки с форматом ячеек.
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
//! \~english Rows displayed by the list.
//! \~russian Строки, отображаемые списком.
PIDeque<Row> content; PIDeque<Row> content;
//! \~english Alignment used to draw row text.
//! \~russian Выравнивание, используемое при рисовании текста строк.
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \~english Active row selection mode.
//! \~russian Текущий режим выбора строк.
SelectionMode selection_mode; SelectionMode selection_mode;
//! \~english Indexes of selected rows.
//! \~russian Индексы выбранных строк.
PISet<int> selected; PISet<int> selected;
int lhei, cur, offset;
//! \~english Cached count of visible content rows between the top and bottom scroll markers.
//! \~russian Кэшированное количество видимых строк содержимого между верхней и нижней метками прокрутки.
int lhei;
//! \~english Index of the current row used for focus and activation.
//! \~russian Индекс текущей строки, используемой для фокуса и активации.
int cur;
//! \~english Index of the first row currently visible in the viewport.
//! \~russian Индекс первой строки, видимой в текущей области просмотра.
int offset;
protected: protected:
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
@@ -202,34 +110,16 @@ protected:
}; };
//! \~\ingroup Console
//! \~\brief
//! \~english Push 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:
//! \~english Constructs a button tile.
//! \~russian Создает тайл кнопки.
TileButton(const PIString & n = PIString()); TileButton(const PIString & n = PIString());
//! \~english Destroys the button tile.
//! \~russian Уничтожает тайл кнопки.
virtual ~TileButton() {} virtual ~TileButton() {}
//! \~english Events emitted by the button.
//! \~russian События, генерируемые кнопкой.
enum EventType { enum EventType {
ButtonClicked /** \~english Button was activated. \~russian Кнопка была активирована. */ ButtonClicked
}; };
//! \~english Text format of the button label.
//! \~russian Формат текста надписи кнопки.
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \~english Button caption.
//! \~russian Подпись кнопки.
PIString text; PIString text;
protected: protected:
@@ -240,42 +130,18 @@ protected:
}; };
//! \~\ingroup Console
//! \~\brief
//! \~english Group of selectable buttons arranged in one tile.
//! \~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:
//! \~english Constructs a button group tile.
//! \~russian Создает тайл группы кнопок.
TileButtons(const PIString & n = PIString()); TileButtons(const PIString & n = PIString());
//! \~english Destroys the button group tile.
//! \~russian Уничтожает тайл группы кнопок.
virtual ~TileButtons() {} virtual ~TileButtons() {}
//! \~english Events emitted by the button group.
//! \~russian События, генерируемые группой кнопок.
enum EventType { enum EventType {
ButtonSelected /** \~english A button was selected; event data stores the button index. \~russian Кнопка была выбрана; данные события содержат индекс кнопки. */ ButtonSelected
}; };
//! \~english Button caption with cell format.
//! \~russian Подпись кнопки с форматом ячеек.
typedef PIPair<PIString, PIScreenTypes::CellFormat> Button; typedef PIPair<PIString, PIScreenTypes::CellFormat> Button;
//! \~english Alignment of the whole button group inside the tile bounds.
//! \~russian Выравнивание всей группы кнопок внутри границ тайла.
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \~english Button definitions shown by the tile.
//! \~russian Описания кнопок, отображаемых тайлом.
PIVector<Button> content; PIVector<Button> content;
//! \~english Index of the currently highlighted button.
//! \~russian Индекс текущей подсвеченной кнопки.
int cur; int cur;
protected: protected:
@@ -291,38 +157,17 @@ protected:
}; };
//! \~\ingroup Console
//! \~\brief
//! \~english Check box tile.
//! \~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:
//! \~english Constructs a check box tile.
//! \~russian Создает тайл флажка.
TileCheck(const PIString & n = PIString()); TileCheck(const PIString & n = PIString());
//! \~english Destroys the check box tile.
//! \~russian Уничтожает тайл флажка.
virtual ~TileCheck() {} virtual ~TileCheck() {}
//! \~english Events emitted by the check box.
//! \~russian События, генерируемые флажком.
enum EventType { enum EventType {
Toggled /** \~english Check state changed; event data stores the new boolean value. \~russian Состояние флажка изменилось; данные события содержат новое логическое значение. */ Toggled
}; };
//! \~english Text format of the caption.
//! \~russian Формат текста подписи.
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \~english Caption displayed after the check mark.
//! \~russian Подпись, отображаемая после флажка.
PIString text; PIString text;
//! \~english Current check state.
//! \~russian Текущее состояние флажка.
bool toggled; bool toggled;
protected: protected:
@@ -333,40 +178,16 @@ protected:
}; };
//! \~\ingroup Console
//! \~\brief
//! \~english Progress indicator tile.
//! \~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:
//! \~english Constructs a progress tile.
//! \~russian Создает тайл прогресса.
TileProgress(const PIString & n = PIString()); TileProgress(const PIString & n = PIString());
//! \~english Destroys the progress tile.
//! \~russian Уничтожает тайл прогресса.
virtual ~TileProgress() {} virtual ~TileProgress() {}
//! \~english Text format used for the overlaid label.
//! \~russian Формат текста, используемый для наложенной подписи.
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \~english Text shown before the numeric value.
//! \~russian Текст, отображаемый перед числовым значением.
PIString prefix; PIString prefix;
//! \~english Text shown after the numeric value.
//! \~russian Текст, отображаемый после числового значения.
PIString suffix; PIString suffix;
//! \~english Value treated as 100 percent.
//! \~russian Значение, принимаемое за 100 процентов.
double maximum; double maximum;
//! \~english Current progress value.
//! \~russian Текущее значение прогресса.
double value; double value;
protected: protected:
@@ -375,28 +196,13 @@ protected:
}; };
//! \~\ingroup Console
//! \~\brief
//! \~english Log view tile backed by the global %PICout buffer.
//! \~russian Тайл журнала, использующий глобальный буфер %PICout.
class PIP_CONSOLE_EXPORT TilePICout: public TileList { class PIP_CONSOLE_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile); PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);
public: public:
//! \~english Constructs a %PICout viewer tile.
//! \~russian Создает тайл просмотра %PICout.
TilePICout(const PIString & n = PIString()); TilePICout(const PIString & n = PIString());
//! \~english Destroys the %PICout viewer tile.
//! \~russian Уничтожает тайл просмотра %PICout.
virtual ~TilePICout() {} virtual ~TilePICout() {}
//! \~english Format applied to appended log lines.
//! \~russian Формат, применяемый к добавляемым строкам журнала.
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \~english Maximum number of lines retained from the %PICout buffer.
//! \~russian Максимальное количество строк, сохраняемых из буфера %PICout.
int max_lines; int max_lines;
protected: protected:
@@ -405,32 +211,14 @@ protected:
}; };
//! \~\ingroup Console
//! \~\brief
//! \~english Single-line editable 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:
//! \~english Constructs an input tile.
//! \~russian Создает тайл ввода.
TileInput(const PIString & n = PIString()); TileInput(const PIString & n = PIString());
//! \~english Destroys the input tile.
//! \~russian Уничтожает тайл ввода.
virtual ~TileInput() {} virtual ~TileInput() {}
//! \~english Format of the entered text.
//! \~russian Формат вводимого текста.
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \~english Current input text.
//! \~russian Текущий введенный текст.
PIString text; PIString text;
//! \~english Maximum input length setting reserved for the tile logic.
//! \~russian Параметр максимальной длины ввода, зарезервированный для логики тайла.
int max_length; int max_length;
protected: protected:

View File

@@ -1,11 +1,9 @@
//! \~\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,160 +32,92 @@
class PIScreenTile; class PIScreenTile;
//! \relatesalso PIScreenTile
//! \~english Namespace with shared screen cells, layout flags, and tile event types.
//! \~russian Пространство имен с общими типами экранных ячеек, флагами компоновки и событиями тайлов.
namespace PIScreenTypes { namespace PIScreenTypes {
//! \~english Color for a character or its background. //! Color for chars or background
//! \~russian Цвет символа или его фона.
enum Color { enum Color {
Default /** \~english Terminal default color \~russian Цвет терминала по умолчанию */, Default /** Default */,
Black /** \~english Black \~russian Черный */, Black /** Black */,
Red /** \~english Red \~russian Красный */, Red /** Red */,
Green /** \~english Green \~russian Зеленый */, Green /** Green */,
Blue /** \~english Blue \~russian Синий */, Blue /** Blue */,
Cyan /** \~english Cyan \~russian Голубой */, Cyan /** Cyan */,
Magenta /** \~english Magenta \~russian Пурпурный */, Magenta /** Magenta */,
Yellow /** \~english Yellow \~russian Желтый */, Yellow /** Yellow */,
White /** \~english White \~russian Белый */, White /** White */,
Transparent /** \~english Preserve the background already stored in the target cell \~russian Сохранить фон, уже записанный в целевой Transparent /** Save previous color */
ячейке */
}; };
//! \~english Character formatting flags. //! Flags for chars
//! \~russian Флаги оформления символа.
enum CharFlag { enum CharFlag {
Bold = 0x1 /** \~english Bold or bright text \~russian Жирный или яркий текст */, Bold /** Bold or bright */ = 0x1,
Blink = 0x2 /** \~english Blinking text \~russian Мигание текста */, Blink /** Blink text */ = 0x2,
Underline = 0x4 /** \~english Underlined text \~russian Подчеркнутый текст */, Underline /** Underline text */ = 0x4,
Inverse = 0x08 /** \~english Inverted foreground and background \~russian Инвертированные цвета текста и фона */ Inverse = 0x08
}; };
//! \~english Horizontal text alignment inside a tile. //! Alignment
//! \~russian Горизонтальное выравнивание текста внутри тайла.
enum Alignment { enum Alignment {
Left /** \~english Left alignment \~russian Выравнивание влево */, Left /** Left */,
Center /** \~english Center alignment \~russian Выравнивание по центру */, Center /** Center */,
Right /** \~english Right alignment \~russian Выравнивание вправо */ Right /** Right */
}; };
//! \~english Layout policy used by parent tiles. //! Size policy
//! \~russian Политика размера, используемая родительскими тайлами при компоновке.
enum SizePolicy { enum SizePolicy {
Fixed /** \~english Keep the requested size \~russian Сохранять запрошенный размер */, Fixed /** Fixed size */,
Preferred /** \~english Use preferred size first and share extra space after fixed tiles \~russian Сначала использовать предпочтительный Preferred /** Preferred size */,
размер и затем делить свободное место после фиксированных тайлов */ Expanding /** Maximum available size */,
, Ignore /** Ignore layout logic */
Expanding /** \~english Take extra space before preferred tiles when the parent can grow children \~russian Получать дополнительное
пространство раньше тайлов с предпочтительным размером, если родитель может расширять дочерние элементы */
,
Ignore /** \~english Skip automatic layout; geometry must be managed manually \~russian Не участвовать в автоматической компоновке;
геометрию нужно задавать вручную */
}; };
//! \~english Child layout direction. //! Direction
//! \~russian Направление раскладки дочерних тайлов.
enum Direction { enum Direction {
Horizontal /** \~english Horizontal layout \~russian Горизонтальная раскладка */, Horizontal /** Horizontal */,
Vertical /** \~english Vertical layout \~russian Вертикальная раскладка */ Vertical /** Vertical */
}; };
//! \~english Focus and navigation flags for tiles. //! Focus flags
//! \~russian Флаги фокуса и навигации для тайлов.
enum FocusFlag { enum FocusFlag {
CanHasFocus = 0x1 /** \~english Tile can receive focus \~russian Тайл может получать фокус */, CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab = 0x2 /** \~english Tab moves focus to the next tile \~russian Клавиша Tab переводит фокус к следующему тайлу */, NextByTab /** Focus passed to next tile by tab key */ = 0x2,
NextByArrowsHorizontal = 0x4 /** \~english Left and right arrows move focus \~russian Стрелки влево и вправо переводят фокус */, NextByArrowsHorizontal /** Focus passed to next tile by arrow keys left or right */ = 0x4,
NextByArrowsVertical = 0x8 /** \~english Up and down arrows move focus \~russian Стрелки вверх и вниз переводят фокус */, NextByArrowsVertical /** Focus passed to next tile by arrow keys up or down */ = 0x8,
NextByArrowsAll /** \~english Any arrow key moves focus \~russian Любая стрелка переводит фокус */ = NextByArrowsAll /** Focus passed to next tile by any arrow key */ = NextByArrowsHorizontal | NextByArrowsVertical,
NextByArrowsHorizontal | NextByArrowsVertical, FocusOnMouse /** Tile focused on mouse press */ = 0x10,
FocusOnMouse = 0x10 /** \~english Mouse press gives focus to the tile \~russian Нажатие мышью переводит фокус на тайл */, FocusOnWheel /** Tile focused on wheel */ = 0x20,
FocusOnWheel = 0x20 /** \~english Mouse wheel gives focus to the tile \~russian Колесо мыши переводит фокус на тайл */, FocusOnMouseOrWheel /** Tile focused on mouse press or wheel */ = FocusOnMouse | FocusOnWheel
FocusOnMouseOrWheel /** \~english Mouse press or wheel gives focus to the tile \~russian Нажатие мышью или колесо переводят фокус на
тайл */
= FocusOnMouse | FocusOnWheel
}; };
//! \~english Combination of \a CharFlag values.
//! \~russian Комбинация значений \a CharFlag.
typedef PIFlags<CharFlag> CharFlags; typedef PIFlags<CharFlag> CharFlags;
//! \~english Combination of \a FocusFlag values.
//! \~russian Комбинация значений \a FocusFlag.
typedef PIFlags<FocusFlag> FocusFlags; typedef PIFlags<FocusFlag> FocusFlags;
//! \~\brief
//! \~english Packed character formatting used by screen cells.
//! \~russian Упакованное описание оформления символа, используемое экранными ячейками.
union PIP_CONSOLE_EXPORT CellFormat { union PIP_CONSOLE_EXPORT CellFormat {
//! \~english Constructs a format from the raw packed value.
//! \~russian Создает формат из упакованного сырого значения.
CellFormat(ushort f = 0) { raw_format = f; } CellFormat(ushort f = 0) { raw_format = f; }
//! \~english Constructs a format from foreground color, background color, and character flags.
//! \~russian Создает формат из цвета символа, цвета фона и флагов оформления.
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;
flags = flags_; flags = flags_;
} }
//! \~english Raw packed representation of the format.
//! \~russian Сырое упакованное представление формата.
ushort raw_format; ushort raw_format;
struct { struct {
//! \~english Foreground color from \a Color.
//! \~russian Цвет символа из \a Color.
ushort color_char: 4; ushort color_char: 4;
//! \~english Background color from \a Color.
//! \~russian Цвет фона из \a Color.
ushort color_back: 4; ushort color_back: 4;
ushort flags : 8;
//! \~english Combination of \a CharFlag values.
//! \~russian Комбинация значений \a CharFlag.
ushort flags: 8;
}; };
//! \~english Returns \b true when two formats are identical.
//! \~russian Возвращает \b true, если два формата совпадают.
bool operator==(const CellFormat & c) const { return raw_format == c.raw_format; } bool operator==(const CellFormat & c) const { return raw_format == c.raw_format; }
//! \~english Returns \b true when two formats differ.
//! \~russian Возвращает \b true, если форматы различаются.
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 One character cell of the console screen.
//! \~russian Одна символьная ячейка консольного экрана.
struct PIP_CONSOLE_EXPORT Cell { struct PIP_CONSOLE_EXPORT Cell {
//! \~english Constructs a cell from a symbol and its format.
//! \~russian Создает ячейку из символа и его формата.
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) { Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {
symbol = c; symbol = c;
format = f; format = f;
} }
//! \~english Cell formatting.
//! \~russian Формат ячейки.
CellFormat format; CellFormat format;
//! \~english Character stored in the cell.
//! \~russian Символ, хранимый в ячейке.
PIChar symbol; PIChar symbol;
//! \~english Returns \b true when symbol and format match.
//! \~russian Возвращает \b true, если совпадают символ и формат.
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; }
//! \~english Returns \b true when symbol or format differs.
//! \~russian Возвращает \b true, если символ или формат различаются.
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; }
//! \~english Assigns a cell, preserving the current background when source background is \a Transparent.
//! \~russian Присваивает ячейку, сохраняя текущий фон, если у источника фон равен \a Transparent.
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) {
@@ -199,46 +129,18 @@ struct PIP_CONSOLE_EXPORT Cell {
} }
}; };
//! \~\brief
//! \~english User-defined event raised by a tile.
//! \~russian Пользовательское событие, поднимаемое тайлом.
struct PIP_CONSOLE_EXPORT TileEvent { struct PIP_CONSOLE_EXPORT TileEvent {
//! \~english Constructs an event with numeric type and optional payload.
//! \~russian Создает событие с числовым типом и необязательными данными.
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {} TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
//! \~english Event type chosen by the tile implementation.
//! \~russian Тип события, выбираемый реализацией тайла.
int type; int type;
//! \~english Optional event payload.
//! \~russian Необязательные данные события.
PIVariant data; PIVariant data;
}; };
//! \~\brief
//! \~english Base interface used by tiles to notify the owning screen about focus, removal, and custom events.
//! \~russian Базовый интерфейс, через который тайлы уведомляют владеющий экран о фокусе, удалении и пользовательских событиях.
class PIP_CONSOLE_EXPORT PIScreenBase { class PIP_CONSOLE_EXPORT PIScreenBase {
public: public:
//! \~english Constructs an empty screen bridge.
//! \~russian Создает пустой мост к экрану.
PIScreenBase() {} PIScreenBase() {}
//! \~english Destroys the screen bridge.
//! \~russian Уничтожает мост к экрану.
virtual ~PIScreenBase() {} virtual ~PIScreenBase() {}
//! \~english Called when a tile raises a custom event.
//! \~russian Вызывается, когда тайл поднимает пользовательское событие.
virtual void tileEventInternal(PIScreenTile *, TileEvent) {} virtual void tileEventInternal(PIScreenTile *, TileEvent) {}
//! \~english Called when a tile is removed from the screen tree.
//! \~russian Вызывается при удалении тайла из дерева экрана.
virtual void tileRemovedInternal(PIScreenTile *) {} virtual void tileRemovedInternal(PIScreenTile *) {}
//! \~english Called when a tile requests focus.
//! \~russian Вызывается, когда тайл запрашивает фокус.
virtual void tileSetFocusInternal(PIScreenTile *) {} virtual void tileSetFocusInternal(PIScreenTile *) {}
}; };

View File

@@ -1,8 +1,9 @@
//! \~\file piterminal.h /*! \file piterminal.h
//! \~\ingroup Console * \ingroup Console
//! \brief * \~\brief
//! \~english Virtual terminal * \~english Virtual terminal
//! \~russian Виртуальный терминал * \~russian Виртуальный терминал
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal
@@ -30,65 +31,26 @@
#include "piscreentypes.h" #include "piscreentypes.h"
//! \~\ingroup Console
//! \~\brief
//! \~english Virtual terminal that runs a shell and mirrors its screen into a cell buffer.
//! \~russian Виртуальный терминал, который запускает оболочку и отражает ее экран в буфер ячеек.
//! \details
//! \~english Provides terminal emulation for reading console input and output. Supports ANSI escape sequences for cursor movement, colors,
//! and text formatting.
//! \~russian Обеспечивает эмуляцию терминала для чтения ввода и вывода консоли. Поддерживает ANSI escape-последовательности для перемещения
//! курсора, цветов и форматирования текста.
class PIP_CONSOLE_EXPORT PITerminal: public PIThread { class PIP_CONSOLE_EXPORT PITerminal: public PIThread {
PIOBJECT_SUBCLASS(PITerminal, PIThread); PIOBJECT_SUBCLASS(PITerminal, PIThread);
public: public:
//! \~english Constructs %PITerminal. //! Constructs %PITerminal
//! \~russian Создает %PITerminal.
PITerminal(); PITerminal();
//! \~english Destroys the terminal and releases backend resources.
//! \~russian Уничтожает терминал и освобождает внутренние ресурсы.
~PITerminal(); ~PITerminal();
//! \~english Returns terminal width in columns.
//! \~russian Возвращает ширину терминала в столбцах.
int columns() const { return size_x; } int columns() const { return size_x; }
//! \~english Returns terminal height in rows.
//! \~russian Возвращает высоту терминала в строках.
int rows() const { return size_y; } int rows() const { return size_y; }
//! \~english Resizes the terminal viewport and backing cell buffer.
//! \~russian Изменяет размер области терминала и связанного буфера ячеек.
bool resize(int cols, int rows); bool resize(int cols, int rows);
//! \~english Sends raw byte data to the terminal input.
//! \~russian Отправляет необработанные байты во входной поток терминала.
void write(const PIByteArray & d); void write(const PIByteArray & d);
//! \~english Sends a special key with modifiers to the terminal.
//! \~russian Отправляет в терминал специальную клавишу с модификаторами.
void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m); void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m);
//! \~english Sends a keyboard event to the terminal.
//! \~russian Отправляет событие клавиатуры в терминал.
void write(PIKbdListener::KeyEvent ke); void write(PIKbdListener::KeyEvent ke);
//! \~english Returns the current terminal screen snapshot, including cursor blink state.
//! \~russian Возвращает текущий снимок экрана терминала с учетом состояния мигания курсора.
PIVector<PIVector<PIScreenTypes::Cell>> content(); PIVector<PIVector<PIScreenTypes::Cell>> content();
//! \~english Returns whether key code `k` is handled as a special terminal key.
//! \~russian Возвращает, обрабатывается ли код `k` как специальная клавиша терминала.
static bool isSpecialKey(int k); static bool isSpecialKey(int k);
//! \~english Initializes the terminal backend and starts the polling thread.
//! \~russian Инициализирует внутренний терминал и запускает поток опроса.
bool initialize(); bool initialize();
//! \~english Stops the terminal and destroys the internal terminal backend instance.
//! \~russian Останавливает терминал и уничтожает внутреннюю реализацию терминала.
void destroy(); void destroy();
private: private:

View File

@@ -1,6 +1,6 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \~\file picontainers.h //! \file picontainers.h
//! \brief //! \brief
//! \~english Base macros for generic containers //! \~english Base macros for generic containers
//! \~russian Базовые макросы для контейнеров //! \~russian Базовые макросы для контейнеров
@@ -74,14 +74,17 @@ public:
template<typename T> template<typename T>
class _PIContainerConstants { class _PIContainerConstants {
public: public:
// minimum elements for container
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
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
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;
@@ -109,6 +112,9 @@ public:
}; };
//! \brief
//! \~english Template reverse wrapper over any container
//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
template<typename C> template<typename C>
_PIReverseWrapper<C> PIReverseWrap(C & c) { _PIReverseWrapper<C> PIReverseWrap(C & c) {
return _PIReverseWrapper<C>(c); return _PIReverseWrapper<C>(c);

View File

@@ -18,8 +18,8 @@
*/ */
//! \defgroup Containers Containers //! \defgroup Containers Containers
//! \~\brief //! \~\brief
//! \~english Container classes and related helpers //! \~english Various standart containers realization
//! \~russian Классы контейнеров и связанные вспомогательные сущности //! \~russian Различные классы контейнеров
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module_Containers Building with CMake //! \~english \section cmake_module_Containers Building with CMake
@@ -58,8 +58,9 @@
//! \a PIVector2D | Линейный двумерный прямоугольный массив //! \a PIVector2D | Линейный двумерный прямоугольный массив
//! //!
//! //!
//! \~english \section stl_iterators STL-Style Iterators
//! \~russian \section stl_iterators Итераторы в стиле STL
//! \~english //! \~english
//! \section stl_iterators STL-Style Iterators
//! \brief They are compatible with Qt's and STL's generic algorithms and are optimized for speed. //! \brief They are compatible with Qt's and STL's generic algorithms and are optimized for speed.
//! \details //! \details
//! For each container class, there are two STL-style iterator types: //! For each container class, there are two STL-style iterator types:
@@ -113,7 +114,6 @@
//! can be used on the left side of the assignment operator. //! can be used on the left side of the assignment operator.
//! //!
//! \~russian //! \~russian
//! \section stl_iterators Итераторы в стиле STL
//! \brief Они совместимы с базовыми алгоритмами Qt и STL и оптимизированы по скорости. //! \brief Они совместимы с базовыми алгоритмами Qt и STL и оптимизированы по скорости.
//! \details //! \details
//! Для каждого контейнерного класса есть два типа итераторов в стиле STL: //! Для каждого контейнерного класса есть два типа итераторов в стиле STL:
@@ -167,14 +167,6 @@
//! Для неконстантных итераторов, возвращаемое значение унарного оператора `*` //! Для неконстантных итераторов, возвращаемое значение унарного оператора `*`
//! может быть использовано с левой стороны от оператора присваивания. //! может быть использовано с левой стороны от оператора присваивания.
//! //!
//! \~\file picontainersmodule.h
//! \~\ingroup Containers
//! \~\brief
//! \~english Umbrella header for the Containers module.
//! \~russian Общий заголовок модуля Containers.
//! \~\details
//! \~english Includes the primary public container headers.
//! \~russian Подключает основные публичные заголовки контейнеров.
//! //!
//! \authors //! \authors
//! \~english //! \~english

View File

@@ -1,6 +1,6 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \~\file pideque.h //! \file pideque.h
//! \brief //! \brief
//! \~english Declares \a PIDeque //! \~english Declares \a PIDeque
//! \~russian Объявление \a PIDeque //! \~russian Объявление \a PIDeque
@@ -184,7 +184,7 @@ public:
//! \endcode //! \endcode
inline PIDeque(size_t piv_size, std::function<T(size_t i)> f) { inline PIDeque(size_t piv_size, std::function<T(size_t i)> f) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
expand(piv_size, std::move(f)); expand(piv_size, f);
} }
//! \~english Move constructor. //! \~english Move constructor.
@@ -729,7 +729,7 @@ public:
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет. //! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a indexWhere() //! \~\sa \a indexWhere()
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const { inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
const ssize_t i = indexWhere(std::move(test), start); const ssize_t i = indexWhere(test, start);
if (i < 0) if (i < 0)
return def; return def;
else else
@@ -743,7 +743,7 @@ public:
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет. //! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a lastIndexWhere() //! \~\sa \a lastIndexWhere()
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const { inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
const ssize_t i = lastIndexWhere(std::move(test), start); const ssize_t i = lastIndexWhere(test, start);
if (i < 0) if (i < 0)
return def; return def;
else else
@@ -1265,7 +1265,7 @@ public:
deleteT(pid_data + pid_start + new_size, pid_size - new_size); deleteT(pid_data + pid_start + new_size, pid_size - new_size);
pid_size = new_size; pid_size = new_size;
} else if (new_size > pid_size) { } else if (new_size > pid_size) {
expand(new_size, std::move(f)); expand(new_size, f);
} }
return *this; return *this;
} }
@@ -1540,7 +1540,7 @@ public:
//! \endcode //! \endcode
//! \~\sa \a sort() //! \~\sa \a sort()
inline PIDeque<T> & sort(std::function<bool(const T & a, const T & b)> comp) { inline PIDeque<T> & sort(std::function<bool(const T & a, const T & b)> comp) {
std::stable_sort(begin(), end(), std::move(comp)); std::stable_sort(begin(), end(), comp);
return *this; return *this;
} }
@@ -1654,13 +1654,7 @@ public:
//! \endcode //! \endcode
//! \~\sa \a remove(), \a removeOne(), \a removeWhere() //! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) { inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
ssize_t j = -1; ssize_t j = indexWhere(test);
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
if (test(pid_data[i])) {
j = ssize_t(i) - pid_start;
break;
}
}
if (j != -1) { if (j != -1) {
for (size_t i = j + 1; i < pid_size; ++i) { for (size_t i = j + 1; i < pid_size; ++i) {
if (!test(pid_data[i + pid_start])) { if (!test(pid_data[i + pid_start])) {

View File

@@ -1,7 +1,7 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \~\file pimap.h //! \file pimap.h
//! \~\brief //! \brief
//! \~english Declares \a PIMap //! \~english Declares \a PIMap
//! \~russian Объявление \a PIMap //! \~russian Объявление \a PIMap
//! \~\authors //! \~\authors
@@ -52,23 +52,32 @@ class PIMapIteratorReverse;
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \class PIMap //! \class PIMap
//! \~\brief //! \brief
//! \~english Map of unique keys and associated values. //! \~english Associative array.
//! \~russian Словарь с уникальными ключами и связанными значениями. //! \~russian Словарь.
//! \~\} //! \~\}
//! \~\details //! \details
//! \~english //! \~english
//! Stores key/value pairs and keeps keys unique. //! A collection of key/value pairs, from which you retrieve a value using its associated key.
//! \a value() returns the value for a key or the provided default, //! There is a finite number of keys in the map, and each key has exactly one value associated with it.
//! while \a operator[] creates a default value for a missing key. //! \a value() returns value for key and leave map
//! Use \a keys() and \a values() to retrieve map contents, //! unchaged in any case. \a operator [] create entry in map if
//! and \a makeIterator() or \a makeReverseIterator() to traverse entries. //! there is no entry for given key. You can retrieve all
//! keys by method \a keys() and all values by methos \a values().
//! To iterate all entries use class PIMapIterator, or methods
//! \a makeIterator() and \a makeReverseIterator().
//! A key in the Map may only occur once.
//! \~russian //! \~russian
//! Хранит пары ключ/значение и поддерживает уникальность ключей. //! Словари, в принципе, похожи на обычные, используемые в повседневной жизни.
//! \a value() возвращает значение по ключу или значение по умолчанию, //! Они хранят элементы одного и того же типа, индексируемые ключевыми значениями.
//! а \a operator[] создает значение по умолчанию для отсутствующего ключа. //! Достоинство словаря в том, что он позволяет быстро получать значение,
//! Для получения содержимого используйте \a keys() и \a values(), //! ассоциированное с заданным ключом.
//! а для обхода элементов - \a makeIterator() или \a makeReverseIterator(). //! Ключи должны быть уникальными.
//! Элемент
//! В контейнеры этого типа заносятся элементы вместе с ключами,
//! по которым их можно найти, которыми могут выступать значения любого типа.
//! \a operator [] позволяет получить доступ к элементу по ключу,
//! и если такого эелемента не было, то он будет создан.
template<typename Key, typename T> template<typename Key, typename T>
class PIMap { class PIMap {
template<typename Key1, typename T1> template<typename Key1, typename T1>
@@ -231,11 +240,12 @@ 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, size()); } inline const_iterator end() const { return const_iterator(this, size()); }
//! \~english Returns a reverse iterator to the last map entry. //! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент. //! \~russian Обратный итератор на первый элемент.
inline reverse_iterator rbegin() { return reverse_iterator(this, size() - 1); } inline reverse_iterator rbegin() { return reverse_iterator(this, size() - 1); }
//! \~english Returns a reverse iterator to the position before the first map entry. //! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент, //! \~russian Обратный итератор на элемент,
//! следующий за последним элементом. //! следующий за последним элементом.
inline reverse_iterator rend() { return reverse_iterator(this, -1); } inline reverse_iterator rend() { return reverse_iterator(this, -1); }
@@ -255,13 +265,13 @@ public:
//! \relatesalso PIMapIteratorReverse //! \relatesalso PIMapIteratorReverse
inline PIMapIteratorReverse<Key, T> makeReverseIterator() { return PIMapIteratorReverse<Key, T>(*this); } inline PIMapIteratorReverse<Key, T> makeReverseIterator() { return PIMapIteratorReverse<Key, T>(*this); }
//! \~english Number of entries in the map. //! \~english Number of elements in the container.
//! \~russian Количество элементов в словаре. //! \~russian Количество элементов массива.
//! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve() //! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t size() const { return pim_content.size(); } inline size_t size() const { return pim_content.size(); }
//! \~english Number of entries in the map as a signed value. //! \~english Number of elements in the container as signed value.
//! \~russian Количество элементов в словаре в виде знакового числа. //! \~russian Количество элементов массива в виде знакового числа.
//! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve() //! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline int size_s() const { return pim_content.size_s(); } inline int size_s() const { return pim_content.size_s(); }
@@ -270,13 +280,19 @@ public:
//! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve() //! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t length() const { return pim_content.size(); } inline size_t length() const { return pim_content.size(); }
//! \~english Checks whether the map is empty. //! \~english Checks if the container has no elements.
//! \~russian Проверяет, пуст ли словарь. //! \~russian Проверяет пуст ли массив.
//! \~\return
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если массив пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve() //! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isEmpty() const { return (pim_content.size() == 0); } inline bool isEmpty() const { return (pim_content.size() == 0); }
//! \~english Checks whether the map contains entries. //! \~english Checks if the container has elements.
//! \~russian Проверяет, содержит ли словарь элементы. //! \~russian Проверяет не пуст ли массив.
//! \~\return
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если массив не пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve() //! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isNotEmpty() const { return (pim_content.size() > 0); } inline bool isNotEmpty() const { return (pim_content.size() > 0); }
@@ -288,7 +304,7 @@ public:
//! the function inserts a default-constructed value into the map with key `key`, //! the function inserts a default-constructed value into the map with key `key`,
//! and returns a reference to it. //! and returns a reference to it.
//! \~russian Если элемента с таким ключом `key` не существует, //! \~russian Если элемента с таким ключом `key` не существует,
//! то он будет создан конструктором по умолчанию и добавлен в словарь //! то он будет создан конструктором по умолчанию и добавлен в массив
//! по ключу `key`, а затем возвращена ссылка на этот новый элемент. //! по ключу `key`, а затем возвращена ссылка на этот новый элемент.
//! \~\code //! \~\code
//! PIMap <PIString, int> m; //! PIMap <PIString, int> m;
@@ -323,8 +339,8 @@ public:
return _value(i); return _value(i);
} }
//! \~english Removes entry with key `key` and returns its value. //! \~english Remove element with key `key` from the array and return it.
//! \~russian Удаляет элемент с ключом `key` и возвращает его значение. //! \~russian Удаляет элемент с ключом `key` из массива и возвращает его.
inline T take(const Key & key, const T & default_ = T()) { inline T take(const Key & key, const T & default_ = T()) {
bool f(false); bool f(false);
const ssize_t i = _find(key, f); const ssize_t i = _find(key, f);
@@ -334,8 +350,8 @@ public:
return ret; return ret;
} }
//! \~english Inserts all entries from `other`, overwriting existing keys. //! \~english Inserts all elements in array `other` to this array with overwrite.
//! \~russian Добавляет все элементы из `other`, перезаписывая существующие ключи. //! \~russian Вставляет все элементы `other` этот массив с перезаписью.
inline PIMap<Key, T> & operator<<(const PIMap<Key, T> & other) { inline PIMap<Key, T> & operator<<(const PIMap<Key, T> & other) {
#ifndef NDEBUG #ifndef NDEBUG
if (&other == this) { if (&other == this) {
@@ -359,24 +375,24 @@ public:
return *this; return *this;
} }
//! \~english Compares this map with `m`. //! \~english Compare operator with array `m`.
//! \~russian Сравнивает этот словарь с `m`. //! \~russian Оператор сравнения с массивом `m`.
inline bool operator==(const PIMap<Key, T> & m) const { return (pim_content == m.pim_content && pim_index == m.pim_index); } inline bool operator==(const PIMap<Key, T> & m) const { return (pim_content == m.pim_content && pim_index == m.pim_index); }
//! \~english Compares this map with `m`. //! \~english Compare operator with array `m`.
//! \~russian Сравнивает этот словарь с `m`. //! \~russian Оператор сравнения с массивом `m`.
inline bool operator!=(const PIMap<Key, T> & m) const { return (pim_content != m.pim_content || pim_index != m.pim_index); } inline bool operator!=(const PIMap<Key, T> & m) const { return (pim_content != m.pim_content || pim_index != m.pim_index); }
//! \~english Checks whether the map contains key `key`. //! \~english Tests if element with key `key` exists in the array.
//! \~russian Проверяет, содержит ли словарь ключ `key`. //! \~russian Проверяет наличие элемента с ключом `key` в массиве.
inline bool contains(const Key & key) const { inline bool contains(const Key & key) const {
bool f(false); bool f(false);
_find(key, f); _find(key, f);
return f; return f;
} }
//! \~english Checks whether the map contains value `value`. //! \~english Tests if element with value `value` exists in the array.
//! \~russian Проверяет, содержит ли словарь значение `value`. //! \~russian Проверяет наличие элемента со значением `value` в массиве.
inline bool containsValue(const T & value) const { return pim_content.contains(value); } inline bool containsValue(const T & value) const { return pim_content.contains(value); }
//! \~english Attempts to allocate memory for at least `new_size` elements. //! \~english Attempts to allocate memory for at least `new_size` elements.
@@ -387,8 +403,8 @@ public:
return *this; return *this;
} }
//! \~english Removes entry with key `key`. //! \~english Remove element with key `key` from the array.
//! \~russian Удаляет элемент с ключом `key`. //! \~russian Удаляет элемент с ключом `key` из массива.
inline PIMap<Key, T> & remove(const Key & key) { inline PIMap<Key, T> & remove(const Key & key) {
bool f(false); bool f(false);
const ssize_t i = _find(key, f); const ssize_t i = _find(key, f);
@@ -397,7 +413,7 @@ public:
} }
//! \~english Removes all entries //! \~english Remove all elements in the array
//! passes the test implemented by the provided function `test`. //! passes the test implemented by the provided function `test`.
//! \~russian Удаляет все элементы, удовлетворяющие условию, //! \~russian Удаляет все элементы, удовлетворяющие условию,
//! заданному в передаваемой функции `test`. //! заданному в передаваемой функции `test`.
@@ -417,8 +433,8 @@ public:
inline PIMap<Key, T> & erase(const Key & key) { return remove(key); } inline PIMap<Key, T> & erase(const Key & key) { return remove(key); }
//! \~english Clears the map. //! \~english Clear array, remove all elements.
//! \~russian Очищает словарь. //! \~russian Очищает массив, удаляет все элементы.
//! \~\details //! \~\details
//! \~\note //! \~\note
//! \~english Reserved memory will not be released. //! \~english Reserved memory will not be released.
@@ -430,8 +446,8 @@ public:
return *this; return *this;
} }
//! \~english Swaps this map with `other`. //! \~english Swaps array `v` other with this array.
//! \~russian Меняет местами этот словарь и `other`. //! \~russian Меняет местами массив `v` с этим массивом.
//! \~\details //! \~\details
//! \~english This operation is very fast and never fails. //! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев. //! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
@@ -440,8 +456,8 @@ public:
pim_index.swap(other.pim_index); pim_index.swap(other.pim_index);
} }
//! \~english Inserts value `value` for key `key`. //! \~english Inserts value `value` with key `key` in the array.
//! \~russian Вставляет значение `value` по ключу `key`. //! \~russian Вставляет значение `value` с ключом `key` в массив.
//! \~\details //! \~\details
//! \~english If an element with the key `key` already exists, it will be overwritten with the value `value`. //! \~english If an element with the key `key` already exists, it will be overwritten with the value `value`.
//! \~russian Если элемент с ключом `key` уже существует, то он будет перезаписан на значение `value`. //! \~russian Если элемент с ключом `key` уже существует, то он будет перезаписан на значение `value`.
@@ -469,8 +485,8 @@ public:
return *this; return *this;
} }
//! \~english Inserts entry `pair`. //! \~english Inserts value `pair` in the array.
//! \~russian Вставляет элемент `pair`. //! \~russian Вставляет пару `pair` в массив.
//! \~\details //! \~\details
//! \~english The first element of the pair is the key, and the second is the value. //! \~english The first element of the pair is the key, and the second is the value.
//! \~russian Первый элемент пары является ключом, а второй значением. //! \~russian Первый элемент пары является ключом, а второй значением.
@@ -510,8 +526,8 @@ public:
return _value(i); return _value(i);
} }
//! \~english Returns values of all map entries. //! \~english Returns an array of values of all elements
//! \~russian Возвращает значения всех элементов словаря. //! \~russian Возвращает массив значений всех эелметнов
inline PIVector<T> values() const { return pim_content; } inline PIVector<T> values() const { return pim_content; }
//! \~english Returns the key of the first element //! \~english Returns the key of the first element
@@ -528,8 +544,8 @@ public:
return default_; return default_;
} }
//! \~english Returns keys of all map entries. //! \~english Returns an array of keys of all elements
//! \~russian Возвращает ключи всех элементов словаря. //! \~russian Возвращает массив ключей всех элементов
inline PIVector<Key> keys() const { inline PIVector<Key> keys() const {
PIVector<Key> ret; PIVector<Key> ret;
ret.reserve(pim_index.size()); ret.reserve(pim_index.size());
@@ -539,8 +555,8 @@ public:
return ret; return ret;
} }
//! \~english Calls `f` for every map entry. //! \~english Execute function `void f(const Key & key, const T & value)` for every element in array.
//! \~russian Вызывает `f` для каждого элемента словаря. //! \~russian Выполняет функцию `void f(const Key & key, const T & value)` для каждого элемента массива.
inline void forEach(std::function<void(const Key & key, const T & value)> f) const { inline void forEach(std::function<void(const Key & key, const T & value)> f) const {
for (int i = 0; i < pim_index.size_s(); ++i) { for (int i = 0; i < pim_index.size_s(); ++i) {
const auto & mi(pim_index[i]); const auto & mi(pim_index[i]);
@@ -548,8 +564,10 @@ public:
} }
} }
//! \~english Creates a new \a PIMap from results of applying `f` to each map entry. //! \~english Сreates a new map PIMap<Key2, T2> populated with the results
//! \~russian Создает новый \a PIMap из результатов применения `f` к каждому элементу словаря. //! of calling a provided function `PIPair<Key2, T2> f(const Key & key, const T & value)` on every element in the calling array.
//! \~russian Создаёт новый словарь PIMap<Key2, T2> с результатом вызова указанной функции
//! `PIPair<Key2, T2> f(const Key & key, const T & value)` для каждого элемента массива.
template<typename Key2, typename T2> template<typename Key2, typename T2>
inline PIMap<Key2, T2> map(std::function<PIPair<Key2, T2>(const Key & key, const T & value)> f) const { inline PIMap<Key2, T2> map(std::function<PIPair<Key2, T2>(const Key & key, const T & value)> f) const {
PIMap<Key2, T2> ret; PIMap<Key2, T2> ret;
@@ -561,8 +579,10 @@ public:
return ret; return ret;
} }
//! \~english Creates a new \a PIVector from results of applying `f` to each map entry. //! \~english Сreates a new array PIVector<ST> populated with the results
//! \~russian Создает новый \a PIVector из результатов применения `f` к каждому элементу словаря. //! of calling a provided function `ST f(const Key & key, const T & value)` on every element in the calling array.
//! \~russian Создаёт новый массив PIVector<ST> с результатом вызова указанной функции
//! `ST f(const Key & key, const T & value)` для каждого элемента массива.
template<typename ST> template<typename ST>
inline PIVector<ST> map(std::function<ST(const Key & key, const T & value)> f) const { inline PIVector<ST> map(std::function<ST(const Key & key, const T & value)> f) const {
PIVector<ST> ret; PIVector<ST> ret;
@@ -574,9 +594,9 @@ public:
return ret; return ret;
} }
//! \~english Returns a new map with all entries //! \~english Returns a new array with all elements
//! that pass the test implemented by the provided function `bool test(const Key & key, const T & value)`. //! that pass the test implemented by the provided function `bool test(const Key & key, const T & value)`.
//! \~russian Возвращает новый словарь со всеми элементами, //! \~russian Возвращает новый массив со всеми элементами,
//! прошедшими проверку, задаваемую в передаваемой функции `bool test(const Key & key, const T & value)`. //! прошедшими проверку, задаваемую в передаваемой функции `bool test(const Key & key, const T & value)`.
inline PIMap<Key, T> filter(std::function<bool(const Key & key, const T & value)> test) const { inline PIMap<Key, T> filter(std::function<bool(const Key & key, const T & value)> test) const {
PIMap<Key, T> ret; PIMap<Key, T> ret;
@@ -668,17 +688,17 @@ private:
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \class PIMapIteratorConst //! \class PIMapIteratorConst
//! \~\brief //! \brief
//! \~english Java-style iterator for \a PIMap. //! \~english Java-style iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap. //! \~russian Итератор Java стиля для \a PIMap.
//! \~\} //! \~\}
//! \details //! \details
//! \~english //! \~english
//! Provides sequential read-only access to keys and values in \a PIMap. //! This class used to easy serial access keys and values in PIMap with read only permitions.
//! Use the constructor directly or call \a PIMap::makeIterator(). //! Use constructor to create iterator, or use \a PIMap::makeIterator()
//! \~russian //! \~russian
//! Используется для последовательного перебора ключей и значений \a PIMap только для чтения. //! Этот класс используется для удобного перебора ключей и значений всего словаря только для чтения.
//! Можно использовать конструктор или вызвать \a PIMap::makeIterator(). //! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeIterator().
//! \~ //! \~
//! \code //! \code
//! PIMap<int, PIString> m; //! PIMap<int, PIString> m;
@@ -738,17 +758,17 @@ private:
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \class PIMapIteratorConstReverse //! \class PIMapIteratorConstReverse
//! \~\brief //! \brief
//! \~english Java-style reverse iterator for \a PIMap. //! \~english Java-style reverse iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap в обратном порядке. //! \~russian Итератор Java стиля для \a PIMap в обратном порядке.
//! \~\} //! \~\}
//! \details //! \details
//! \~english //! \~english
//! Provides sequential reverse read-only access to keys and values in \a PIMap. //! This class used to easy serial reverse access keys and values in PIMap with read only permitions.
//! Use the constructor directly or call \a PIMap::makeReverseIterator(). //! Use constructor to create iterator, or use \a PIMap::makeReverseIterator().
//! \~russian //! \~russian
//! Используется для последовательного обратного перебора ключей и значений \a PIMap только для чтения. //! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке только для чтения.
//! Можно использовать конструктор или вызвать \a PIMap::makeReverseIterator(). //! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeReverseIterator().
//! \~ //! \~
//! \code //! \code
//! PIMap<int, PIString> m; //! PIMap<int, PIString> m;
@@ -807,17 +827,17 @@ private:
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \class PIMapIterator //! \class PIMapIterator
//! \~\brief //! \brief
//! \~english Java-style iterator for \a PIMap. //! \~english Java-style iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap. //! \~russian Итератор Java стиля для \a PIMap.
//! \~\} //! \~\}
//! \details //! \details
//! \~english //! \~english
//! Provides sequential access to keys and values in \a PIMap with write access to values. //! This class used to easy serial access keys and values in PIMap with write permitions.
//! Use the constructor directly or call \a PIMap::makeIterator(). //! Use constructor to create iterator, or use \a PIMap::makeIterator()
//! \~russian //! \~russian
//! Используется для последовательного перебора ключей и значений \a PIMap с доступом на запись. //! Этот класс используется для удобного перебора ключей и значений всего словаря с доступом на запись.
//! Можно использовать конструктор или вызвать \a PIMap::makeIterator(). //! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeIterator().
//! \~ //! \~
//! \code //! \code
//! PIMap<int, PIString> m; //! PIMap<int, PIString> m;
@@ -877,17 +897,17 @@ private:
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \class PIMapIteratorReverse //! \class PIMapIteratorReverse
//! \~\brief //! \brief
//! \~english Java-style reverse iterator for \a PIMap. //! \~english Java-style reverse iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap в обратном порядке. //! \~russian Итератор Java стиля для \a PIMap в обратном порядке.
//! \~\} //! \~\}
//! \details //! \details
//! \~english //! \~english
//! Provides sequential reverse access to keys and values in \a PIMap with write access to values. //! This class used to easy serial reverse access keys and values in PIMap with write permitions.
//! Use the constructor directly or call \a PIMap::makeReverseIterator(). //! Use constructor to create iterator, or use \a PIMap::makeReverseIterator().
//! \~russian //! \~russian
//! Используется для последовательного обратного перебора ключей и значений \a PIMap с доступом на запись. //! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке с доступом на запись.
//! Можно использовать конструктор или вызвать \a PIMap::makeReverseIterator(). //! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeReverseIterator().
//! \~ //! \~
//! \code //! \code
//! PIMap<int, PIString> m; //! PIMap<int, PIString> m;

View File

@@ -1,6 +1,6 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \~\file pipair.h //! \file pipair.h
//! \brief //! \brief
//! \~english Declares \a PIPair //! \~english Declares \a PIPair
//! \~russian Объявление \a PIPair //! \~russian Объявление \a PIPair

View File

@@ -1,6 +1,6 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \~\file piqueue.h //! \file piqueue.h
//! \brief //! \brief
//! \~english Declares \a PIQueue //! \~english Declares \a PIQueue
//! \~russian Объявление \a PIQueue //! \~russian Объявление \a PIQueue
@@ -40,76 +40,78 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \class PIQueue //! \class PIQueue
//! \~\brief //! \brief
//! \~english Queue container built on top of \a PIDeque. //! \~english A container class inherited from the \a PIDeque with queue functionality.
//! \~russian Контейнер очереди, построенный поверх \a PIDeque. //! \~russian Класс контейнера наследованый от \a PIDeque с функциональностью очереди.
//! \~\} //! \~\}
//! \details //! \details
//! \~english Stores elements in FIFO order and adds \a enqueue() and \a dequeue() to \a PIDeque. //! \~english The container is a array of elements organized according to the FIFO principle (first in, first out).
//! \~russian Хранит элементы в порядке FIFO и добавляет к \a PIDeque функции \a enqueue() и \a dequeue(). //! Adds \a enqueue() and \dequeue() functions to \a PIDeque.
//! \~russian Контейнер представляющий массив элементов, организованных по принципу FIFO (первым пришёл — первым вышел).
//! Добавляет к \a PIDeque функции \a enqueue() и \a dequeue().
//! \~\sa \a PIDeque //! \~\sa \a PIDeque
template<typename T> template<typename T>
class PIQueue: public PIDeque<T> { class PIQueue: public PIDeque<T> {
public: public:
//! \~english Constructs an empty queue. //! \~english Constructs an empty array.
//! \~russian Создает пустую очередь. //! \~russian Создает пустой массив.
PIQueue() {} PIQueue() {}
//! \~english Enqueues `v`. //! \~english Puts an element on the queue.
//! \~russian Добавляет `v` в очередь. //! \~russian Кладёт элемент в очередь.
PIDeque<T> & enqueue(const T & v) { PIDeque<T> & enqueue(const T & v) {
PIDeque<T>::push_front(v); PIDeque<T>::push_front(v);
return *this; return *this;
} }
//! \~english Moves `v` into the queue. //! \~english Move an element on the queue.
//! \~russian Перемещает `v` в очередь. //! \~russian Перемещает элемент в очередь.
PIDeque<T> & enqueue(T && v) { PIDeque<T> & enqueue(T && v) {
PIDeque<T>::push_front(std::move(v)); PIDeque<T>::push_front(std::move(v));
return *this; return *this;
} }
//! \~english Dequeues and returns the head element. //! \~english Retrieves and returns an element from the queue.
//! \~russian Извлекает и возвращает головной элемент очереди. //! \~russian Забирает и возвращает элемент из очереди.
//! \~\details //! \~\details
//! \note //! \note
//! \~english This function assumes that the queue is not empty. //! \~english This function assumes that the array isn't empty.
//! Otherwise behavior is undefined. //! Otherwise will be undefined behavior.
//! \~russian Эта функция предполагает, что очередь не пуста. //! \~russian Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T dequeue() { return PIDeque<T>::take_back(); } T dequeue() { return PIDeque<T>::take_back(); }
//! \~english Returns the head element. //! \~english Head element of the queue.
//! \~russian Возвращает головной элемент очереди. //! \~russian Головной (верхний) элемент очереди.
//! \~\details //! \~\details
//! \note //! \note
//! \~english Returns a reference to the head element. //! \~english Returns a reference to the head element of the queue.
//! This function assumes that the queue is not empty. //! This function assumes that the array isn't empty.
//! Otherwise behavior is undefined. //! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на головной элемент очереди. //! \~russian Возвращает ссылку на головной (верхний) элемент очереди.
//! Эта функция предполагает, что очередь не пуста. //! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T & head() { return PIDeque<T>::back(); } T & head() { return PIDeque<T>::back(); }
const T & head() const { return PIDeque<T>::back(); } const T & head() const { return PIDeque<T>::back(); }
//! \~english Returns the tail element. //! \~english Tail element of the queue.
//! \~russian Возвращает хвостовой элемент очереди. //! \~russian Хвостовой (нижний) элемент очереди.
//! \~\details //! \~\details
//! \~english Returns a reference to the tail element. //! \~english Returns a reference to the tail element of the queue.
//! This function assumes that the queue is not empty. //! This function assumes that the array isn't empty.
//! Otherwise behavior is undefined. //! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на хвостовой элемент очереди. //! \~russian Возвращает ссылку на хвостовой (нижний) элемент очереди.
//! Эта функция предполагает, что очередь не пуста. //! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
T & tail() { return PIDeque<T>::front(); } T & tail() { return PIDeque<T>::front(); }
const T & tail() const { return PIDeque<T>::front(); } const T & tail() const { return PIDeque<T>::front(); }
//! \~english Returns queue contents as \a PIVector. //! \~english Converts \a PIQueue to \a PIVector.
//! \~russian Возвращает содержимое очереди в виде \a PIVector. //! \~russian Преобразует \a PIQueue в \a PIVector.
PIVector<T> toVector() const { return PIVector<T>(PIDeque<T>::data(), PIDeque<T>::size()); } PIVector<T> toVector() const { return PIVector<T>(PIDeque<T>::data(), PIDeque<T>::size()); }
//! \~english Returns queue contents as \a PIDeque. //! \~english Converts \a PIQueue to \a PIDeque.
//! \~russian Возвращает содержимое очереди в виде \a PIDeque. //! \~russian Преобразует \a PIQueue в \a PIDeque.
PIDeque<T> toDeque() const { return PIDeque<T>(*this); } PIDeque<T> toDeque() const { return PIDeque<T>(*this); }
}; };

View File

@@ -1,10 +1,8 @@
//! \addtogroup Containers /*! \file piset.h
//! \{ * \brief Set container
//! \~\file piset.h *
//! \~\brief * This file declare PISet
//! \~english Declares \a PISet */
//! \~russian Объявление \a PISet
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Set container Set container
@@ -29,33 +27,13 @@
#include "pimap.h" #include "pimap.h"
//! \addtogroup Containers /*! \brief Set of any type
//! \{ * \details This class used to store collection of unique elements
//! \class PISet * of any type. You can only add values to set with \a operator<< or
//! \~\brief * with function \a insert(). You can discover if value already in
//! \~english Set of unique values. * set with \a operator[] or with function \a find(). These function
//! \~russian Множество уникальных значений. * has logarithmic complexity.
//! \~\} */
//! \~\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;
@@ -65,31 +43,26 @@ 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:
//! \~english Constructs an empty set. //! Contructs an empty set
//! \~russian Создает пустое множество.
PISet() {} PISet() {}
//! \~english Constructs a set containing `value`. //! Contructs 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); }
//! \~english Constructs a set containing `v0` and `v1`. //! Contructs set with 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);
} }
//! \~english Constructs a set containing `v0`, `v1` and `v2`. //! Contructs set with 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);
} }
//! \~english Constructs a set containing `v0`, `v1`, `v2` and `v3`. //! Contructs set with 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);
@@ -98,9 +71,6 @@ public:
} }
//! \~\brief
//! \~english Constant iterator over \a PISet elements.
//! \~russian Константный итератор по элементам \a PISet.
class const_iterator { class const_iterator {
friend class PISet<T>; friend class PISet<T>;
@@ -116,140 +86,75 @@ public:
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
//! \~english Constructs an invalid iterator.
//! \~russian Создает недействительный итератор.
inline const_iterator(): parent(0), pos(0) {} inline const_iterator(): parent(0), pos(0) {}
//! \~english Returns the current element.
//! \~russian Возвращает текущий элемент.
inline const T & operator*() const { return parent->pim_index[pos].key; } inline const T & operator*() const { return parent->pim_index[pos].key; }
//! \~english Provides access to the current element.
//! \~russian Предоставляет доступ к текущему элементу.
inline const T & operator->() const { return parent->pim_index[pos].key; } inline const T & operator->() const { return parent->pim_index[pos].key; }
//! \~english Moves iterator to the next element.
//! \~russian Перемещает итератор к следующему элементу.
inline const_iterator & operator++() { inline const_iterator & operator++() {
++pos; ++pos;
return *this; return *this;
} }
//! \~english Returns iterator before incrementing.
//! \~russian Возвращает итератор до увеличения.
inline const_iterator operator++(int) { inline const_iterator operator++(int) {
const auto tmp = *this; const auto tmp = *this;
++*this; ++*this;
return tmp; return tmp;
} }
//! \~english Moves iterator to the previous element.
//! \~russian Перемещает итератор к предыдущему элементу.
inline const_iterator & operator--() { inline const_iterator & operator--() {
--pos; --pos;
return *this; return *this;
} }
//! \~english Returns iterator before decrementing.
//! \~russian Возвращает итератор до уменьшения.
inline const_iterator operator--(int) { inline const_iterator operator--(int) {
const auto tmp = *this; const auto tmp = *this;
--*this; --*this;
return tmp; return tmp;
} }
//! \~english Adds offset of iterator `it`.
//! \~russian Добавляет смещение итератора `it`.
inline const_iterator & operator+=(const const_iterator & it) { inline const_iterator & operator+=(const const_iterator & it) {
pos += it.pos; pos += it.pos;
return *this; return *this;
} }
//! \~english Advances iterator by `p` elements.
//! \~russian Сдвигает итератор вперед на `p` элементов.
inline const_iterator & operator+=(size_t p) { inline const_iterator & operator+=(size_t p) {
pos += p; pos += p;
return *this; return *this;
} }
//! \~english Subtracts offset of iterator `it`.
//! \~russian Вычитает смещение итератора `it`.
inline const_iterator & operator-=(const const_iterator & it) { inline const_iterator & operator-=(const const_iterator & it) {
pos -= it.pos; pos -= it.pos;
return *this; return *this;
} }
//! \~english Moves iterator back by `p` elements.
//! \~russian Сдвигает итератор назад на `p` элементов.
inline const_iterator & operator-=(size_t p) { inline const_iterator & operator-=(size_t p) {
pos -= p; pos -= p;
return *this; return *this;
} }
//! \~english Returns iterator shifted back by `p`.
//! \~russian Возвращает итератор, сдвинутый назад на `p`.
friend inline const_iterator operator-(size_t p, const const_iterator & it) { return it - p; } friend inline const_iterator operator-(size_t p, const const_iterator & it) { return it - p; }
//! \~english Returns iterator shifted back by `p`.
//! \~russian Возвращает итератор, сдвинутый назад на `p`.
friend inline const_iterator operator-(const const_iterator & it, size_t p) { friend inline const_iterator operator-(const const_iterator & it, size_t p) {
auto tmp = it; auto tmp = it;
tmp -= p; tmp -= p;
return tmp; return tmp;
} }
//! \~english Returns distance between iterators.
//! \~russian Возвращает расстояние между итераторами.
friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; } friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; }
//! \~english Returns iterator shifted forward by `p`.
//! \~russian Возвращает итератор, сдвинутый вперед на `p`.
friend inline const_iterator operator+(size_t p, const const_iterator & it) { return it + p; } friend inline const_iterator operator+(size_t p, const const_iterator & it) { return it + p; }
//! \~english Returns iterator shifted forward by `p`.
//! \~russian Возвращает итератор, сдвинутый вперед на `p`.
friend inline const_iterator operator+(const const_iterator & it, size_t p) { friend inline const_iterator operator+(const const_iterator & it, size_t p) {
auto tmp = it; auto tmp = it;
tmp += p; tmp += p;
return tmp; return tmp;
} }
//! \~english Checks iterator equality.
//! \~russian Проверяет равенство итераторов.
inline bool operator==(const const_iterator & it) const { return (pos == it.pos); } inline bool operator==(const const_iterator & it) const { return (pos == it.pos); }
//! \~english Checks iterator inequality.
//! \~russian Проверяет неравенство итераторов.
inline bool operator!=(const const_iterator & it) const { return (pos != it.pos); } inline bool operator!=(const const_iterator & it) const { return (pos != it.pos); }
//! \~english Checks whether `it1` is before `it2`.
//! \~russian Проверяет, находится ли `it1` перед `it2`.
friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; } friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; }
//! \~english Checks whether `it1` is before or equal to `it2`.
//! \~russian Проверяет, находится ли `it1` перед `it2` или совпадает с ним.
friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; } friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; }
//! \~english Checks whether `it1` is after `it2`.
//! \~russian Проверяет, находится ли `it1` после `it2`.
friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; } friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; }
//! \~english Checks whether `it1` is after or equal to `it2`.
//! \~russian Проверяет, находится ли `it1` после `it2` или совпадает с ним.
friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; } friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; }
}; };
//! \~english Returns iterator to the first element.
//! \~russian Возвращает итератор на первый элемент.
inline const_iterator begin() const { return const_iterator(this, 0); } inline const_iterator begin() const { return const_iterator(this, 0); }
//! \~english Returns iterator following the last element.
//! \~russian Возвращает итератор на элемент, следующий за последним.
inline const_iterator end() const { return const_iterator(this, _CSet::size()); } inline const_iterator end() const { return const_iterator(this, _CSet::size()); }
//! \~english Constructs a set from vector `values`. //! Contructs set from vector of elements
//! \~russian Создает множество из вектора `values`.
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) {
@@ -257,8 +162,7 @@ public:
} }
} }
//! \~english Constructs a set from deque `values`. //! Contructs set from deque of elements
//! \~russian Создает множество из дека `values`.
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) {
@@ -268,83 +172,65 @@ public:
typedef T key_type; typedef T key_type;
//! \~english Inserts `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;
} }
//! \~english Moves `t` into the set.
//! \~russian Перемещает `t` в множество.
PISet<T> & operator<<(T && t) { PISet<T> & operator<<(T && t) {
_CSet::insert(std::move(t), 0); _CSet::insert(std::move(t), 0);
return *this; return *this;
} }
//! \~english Inserts all elements from `other`.
//! \~russian Добавляет все элементы из `other`.
PISet<T> & operator<<(const PISet<T> & other) { PISet<T> & operator<<(const PISet<T> & other) {
(*(_CSet *)this) << *((_CSet *)&other); (*(_CSet *)this) << *((_CSet *)&other);
return *this; return *this;
} }
//! \~english Tests whether element `t` exists in the set. //! \~english Tests if element `key` exists in the set.
//! \~russian Проверяет наличие элемента `t` в множестве. //! \~russian Проверяет наличие элемента `key` в массиве.
inline bool contains(const T & t) const { return _CSet::contains(t); } inline bool contains(const T & t) const { return _CSet::contains(t); }
//! \~english Checks whether element `t` exists in the set. //! Returns if element "t" exists in this set
//! \~russian Проверяет наличие элемента `t` в множестве.
bool operator[](const T & t) const { return _CSet::contains(t); } bool operator[](const T & t) const { return _CSet::contains(t); }
//! \~english Removes element `t` from the set. //! Returns if element "t" exists in this 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;
} }
//! \~english Unites the set with `v`. //! Unite set with "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;
} }
//! \~english Removes all elements present in `v`. //! Subtract set with "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;
} }
//! \~english Leaves only elements also present in `v`. //! Intersect set with "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;
} }
//! \~english Same as \a unite(). //! Unite set with "v"
//! \~russian Синоним \a unite().
PISet<T> & operator+=(const PISet<T> & v) { return unite(v); } PISet<T> & operator+=(const PISet<T> & v) { return unite(v); }
//! \~english Same as \a unite(). //! Unite set with "v"
//! \~russian Синоним \a unite().
PISet<T> & operator|=(const PISet<T> & v) { return unite(v); } PISet<T> & operator|=(const PISet<T> & v) { return unite(v); }
//! \~english Same as \a subtract(). //! Subtract set with "v"
//! \~russian Синоним \a subtract().
PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); } PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); }
//! \~english Same as \a intersect(). //! Intersect set with "v"
//! \~russian Синоним \a intersect().
PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); } PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); }
//! \~english Returns set contents as \a PIVector. //! Returns content of set as PIVector
//! \~russian Возвращает содержимое множества в виде \a PIVector.
PIVector<T> toVector() const { PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
for (const auto & i: *this) for (const auto & i: *this)
@@ -352,8 +238,7 @@ public:
return ret; return ret;
} }
//! \~english Returns set contents as \a PIDeque. //! Returns content of set as PIDeque
//! \~russian Возвращает содержимое множества в виде \a PIDeque.
PIDeque<T> toDeque() const { PIDeque<T> toDeque() const {
PIDeque<T> ret; PIDeque<T> ret;
for (const auto & i: *this) for (const auto & i: *this)
@@ -363,9 +248,7 @@ public:
}; };
//! \relatesalso PISet //! \relatesalso PISet \brief Returns unite of two sets
//! \~english Returns 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);
@@ -373,9 +256,7 @@ PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet //! \relatesalso PISet \brief Returns subtraction of two sets
//! \~english Returns 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);
@@ -383,9 +264,7 @@ PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet //! \relatesalso PISet \brief Returns unite of two sets
//! \~english Returns 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);
@@ -393,9 +272,7 @@ PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet //! \relatesalso PISet \brief Returns intersetion of two sets
//! \~english Returns 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);
@@ -404,9 +281,6 @@ PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
} }
//! \relatesalso PISet
//! \~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();

View File

@@ -1,6 +1,6 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \~\file pistack.h //! \file pistack.h
//! \brief //! \brief
//! \~english Declares \a PIStack //! \~english Declares \a PIStack
//! \~russian Объявление \a PIStack //! \~russian Объявление \a PIStack

View File

@@ -1,6 +1,6 @@
//! \addtogroup Containers //! \addtogroup Containers
//! \{ //! \{
//! \~\file pivector.h //! \file pivector.h
//! \brief //! \brief
//! \~english Declares \a PIVector //! \~english Declares \a PIVector
//! \~russian Объявление \a PIVector //! \~russian Объявление \a PIVector
@@ -184,7 +184,7 @@ public:
//! \endcode //! \endcode
inline PIVector(size_t size, std::function<T(size_t i)> f) { inline PIVector(size_t size, std::function<T(size_t i)> f) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
expand(size, std::move(f)); expand(size, f);
} }
//! \~english Move constructor. //! \~english Move constructor.
@@ -725,7 +725,7 @@ public:
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет. //! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a indexWhere() //! \~\sa \a indexWhere()
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const { inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
const ssize_t i = indexWhere(std::move(test), start); const ssize_t i = indexWhere(test, start);
if (i < 0) if (i < 0)
return def; return def;
else else
@@ -739,7 +739,7 @@ public:
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет. //! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a lastIndexWhere() //! \~\sa \a lastIndexWhere()
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const { inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
const ssize_t i = lastIndexWhere(std::move(test), start); const ssize_t i = lastIndexWhere(test, start);
if (i < 0) if (i < 0)
return def; return def;
else else
@@ -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(), \a contains() //! \~\sa \a every(), \a any(), \a entries(), \a forEach()
inline bool containsAll(const PIVector<T> & v, ssize_t start = 0) const { inline bool contains(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,24 +854,6 @@ 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
@@ -1267,7 +1249,7 @@ public:
deleteT(piv_data + new_size, piv_size - new_size); deleteT(piv_data + new_size, piv_size - new_size);
piv_size = new_size; piv_size = new_size;
} else if (new_size > piv_size) { } else if (new_size > piv_size) {
expand(new_size, std::move(f)); expand(new_size, f);
} }
return *this; return *this;
} }
@@ -1321,16 +1303,14 @@ 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(), size_t count = 1) { inline PIVector<T> & insert(size_t index, const T & e = T()) {
alloc(piv_size + count); alloc(piv_size + 1);
if (index < piv_size - count) { if (index < piv_size - 1) {
const size_t os = piv_size - index - count; const size_t os = piv_size - index - 1;
memmove(reinterpret_cast<void *>(piv_data + index + count), reinterpret_cast<const void *>(piv_data + index), os * sizeof(T)); memmove(reinterpret_cast<void *>(piv_data + index + 1), 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;
} }
@@ -1486,7 +1466,7 @@ public:
//! \endcode //! \endcode
//! \~\sa \a sort() //! \~\sa \a sort()
inline PIVector<T> & sort(std::function<bool(const T & a, const T & b)> comp) { inline PIVector<T> & sort(std::function<bool(const T & a, const T & b)> comp) {
std::stable_sort(begin(), end(), std::move(comp)); std::stable_sort(begin(), end(), comp);
return *this; return *this;
} }
@@ -1599,13 +1579,7 @@ public:
//! \endcode //! \endcode
//! \~\sa \a remove(), \a removeOne(), \a removeWhere() //! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIVector<T> & removeWhere(std::function<bool(const T & e)> test) { inline PIVector<T> & removeWhere(std::function<bool(const T & e)> test) {
ssize_t j = -1; ssize_t j = indexWhere(test);
for (size_t i = 0; i < piv_size; ++i) {
if (test(piv_data[i])) {
j = i;
break;
}
}
if (j != -1) { if (j != -1) {
for (size_t i = j + 1; i < piv_size; ++i) { for (size_t i = j + 1; i < piv_size; ++i) {
if (!test(piv_data[i])) { if (!test(piv_data[i])) {

View File

@@ -1,15 +1,8 @@
//! \addtogroup Containers /*! \file pivector2d.h
//! \{ * \brief 2D wrapper around PIVector
//! \~\file pivector2d.h *
//! \brief * This file declares PIVector
//! \~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
@@ -34,111 +27,29 @@
#include "pivector.h" #include "pivector.h"
//! \addtogroup Containers /*! \brief 2D array,
//! \{ * \details This class used to store 2D array of any type elements as plain vector.
//! \class PIVector2D * You can read/write any element via operators [][], first dimension - row, second - column.
//! \brief * The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc.
//! \~english 2D array container. * You can't add values to array, but you can modify any elements or create another PIVector2D.
//! \~russian Двумерный контейнер-массив. * PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> >
//! \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_) {
@@ -152,858 +63,219 @@ 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 RowConst; class Row {
class ColConst;
class Row;
class Col;
//! \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 {
friend class PIVector2D<T>; friend class PIVector2D<T>;
protected: private:
inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)), st_(p->cols_ * row), sz_(p->cols_) {} inline Row(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
const PIVector<T> * p_; st_ = p->cols_ * row;
const size_t st_, sz_; sz_ = p->cols_;
}
PIVector<T> * p_;
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_; }
inline T & operator[](size_t index) { return (*p_)[st_ + index]; }
//! \~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]; }
inline T * data(size_t index = 0) { return p_->data(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); }
inline Row & operator=(const Row & other) {
//! \~english Converts the row to a \a PIVector. if (p_ == other.p_ && st_ == other.st_) return *this;
//! \~russian Преобразует строку в \a PIVector. 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_); } 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 Col {
//! \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 {
friend class PIVector2D<T>; friend class PIVector2D<T>;
protected: private:
inline ColConst(const PIVector2D<T> * p, size_t col): p_(&(p->mat)), step_(p->cols_), col_(col), sz_(p->rows_) {} inline Col(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
const PIVector<T> * p_; step_ = p->cols_;
const size_t step_, col_, sz_; row_ = row;
sz_ = p->rows_;
}
PIVector<T> * p_;
size_t step_, row_, sz_;
public: public:
//! \~english Copy constructor from modifiable Col to read-only ColConst.
//! \~russian Конструктор копирования из модифицируемого класса Col в константный ColConst.
//! \~\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_; } inline size_t size() const { return sz_; }
inline T & operator[](size_t index) { return (*p_)[index * step_ + row_]; }
//! \~english Const access to the element at the given row index within the column. inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; }
//! \~russian Константный доступ к элементу по заданному индексу строки в столбце. inline T * data(size_t index = 0) { return p_->data(index * step_ + row_); }
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + col_]; } inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); }
inline Col & operator=(const Col & other) {
//! \~english Returns a const pointer to the column data starting at an optional row offset. if (p_ == other.p_ && row_ == other.row_) return *this;
//! \~russian Возвращает константный указатель на данные столбца, начиная с опционального смещения по строкам. const size_t sz = piMin<size_t>(sz_, other.sz_);
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + col_); } for (int i = 0; i < sz; ++i)
(*p_)[i * step_ + row_] = other[i];
//! \~english Converts the column to a \a PIVector. return *this;
//! \~russian Преобразует столбец в \a PIVector. }
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 { inline PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
ret.reserve(sz_); ret.reserve(sz_);
for (size_t i = 0; i < size(); i++) for (size_t i = 0; i < sz_; i++)
ret << (*p_)[i * step_ + col_]; ret << (*p_)[i * step_ + row_];
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 class RowConst {
//! \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>; friend class PIVector2D<T>;
private: private:
inline Row(PIVector2D<T> * p, size_t row): RowConst(p, row), p_(&(p->mat)) {} inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
PIVector<T> * p_; st_ = p->cols_ * row;
sz_ = p->cols_;
}
const PIVector<T> * p_;
size_t st_, sz_;
public: public:
using RowConst::operator[]; inline size_t size() const { return sz_; }
using RowConst::data; inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; }
using RowConst::size; inline const T * data(size_t index = 0) const { return p_->data(st_ + index); }
inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); }
//! \~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 ColConst {
//! \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>; friend class PIVector2D<T>;
private: private:
inline Col(PIVector2D<T> * p, size_t col): ColConst(p, col), p_(&(p->mat)) {} inline ColConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
PIVector<T> * p_; step_ = p->cols_;
row_ = row;
sz_ = p->rows_;
}
const PIVector<T> * p_;
size_t step_, row_, sz_;
public: public:
using ColConst::operator[]; inline size_t size() const { return p_->rows_; }
using ColConst::data; inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; }
using ColConst::size; inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); }
inline PIVector<T> toVector() const {
//! \~english Accesses the element at the given row index within the column. PIVector<T> ret;
//! \~russian Доступ к элементу по заданному индексу строки в столбце. ret.reserve(sz_);
//! \return Reference to the element. for (int i = 0; i < size(); i++)
inline T & operator[](size_t index) { return (*p_)[index * this->step_ + this->col_]; } ret << (*p_)[i * step_ + row_];
return ret;
//! \~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) {
//! \~english Replaces a row with the contents of a read-only RowConst object. const size_t sz = piMin<size_t>(cols_, other.sz_);
//! \~russian Заменяет строку содержимым объекта RowConst только для чтения. mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
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) {
//! \~english Appends a new row to the bottom of the array from another Row object. if (cols_ == 0) cols_ = other.sz_;
//! \~russian Добавляет новую строку в конец массива из другого объекта Row. const size_t sz = piMin<size_t>(cols_, other.sz_);
//! \details const size_t ps = mat.size();
//! \~english If the array was empty, its column count is set to the size of the source row. mat.resize(mat.size() + cols_);
//! Otherwise, only `min(cols(), other.size())` elements are copied; the rest of the new row is default-initialized. mat._copyRaw(mat.data(ps), other.data(), sz);
//! \~russian Если массив был пуст, количество столбцов устанавливается равным размеру исходной строки. rows_++;
//! В противном случае копируется только `min(cols(), other.size())` элементов; остальные элементы новой строки инициализируются по return *this;
//! умолчанию. }
//! \~\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_;
mat.append(other.toVector()); const size_t sz = piMin<size_t>(cols_, other.sz_);
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();
mat.append(other); const size_t sz = piMin<size_t>(cols_, other.size());
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()) {
if (rows == rows_ && cols == cols_) return *this; mat.resize(rows * cols_, f);
if (rows_ == 0 || cols_ == 0) {
mat.resize(rows * cols, f);
rows_ = rows; rows_ = rows;
const int cs = (cols - cols_);
if (cs < 0) {
for (size_t r = 0; r < rows; ++r) {
mat.remove(r * cols + cols, -cs);
}
}
mat.resize(rows * cols, f);
if (!mat.isEmpty()) {
if (cs > 0) {
for (size_t r = 0; r < rows_; ++r) {
for (int i = 0; i < cs; ++i)
mat.insert(r * cols + cols_, mat.take_back());
}
}
}
cols_ = cols; cols_ = cols;
return *this; return *this;
} }
if (rows != rows_ && cols == cols_) {
mat.resize(rows * cols_, f);
rows_ = rows;
return *this;
}
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);
}
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_);
@@ -1012,31 +284,18 @@ 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; }
//! \~english Swaps this 2D array with another. inline PIVector<T> & plainVector() { return mat; }
//! \~russian Меняет местами этот двумерный массив с другим.
//! \details inline const PIVector<T> & plainVector() const { return mat; }
//! \~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;
@@ -1045,352 +304,29 @@ 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();
} }
//! \~english Checks if the underlying flat vector contains the element `e`.
//! \~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(std::move(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_)};
}
//! \~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(std::move(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 Returns the last index (row, col) of `e` in the 2D array.
//! \~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(std::move(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(std::move(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(std::move(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;
}
//! \~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(std::move(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> template<typename ST>
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const { inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const {
return PIVector2D<ST>(rows_, cols_, mat.template map<ST>(std::move(f))); return PIVector2D<ST>(rows_, cols_, mat.map(f));
} }
//! \~english Applies a function (with row and col indices) to each element and returns a new 2D array. inline void forEach(std::function<void(const T &)> f) const { mat.forEach(f); }
//! \~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). inline PIVector2D<T> & forEach(std::function<void(T &)> f) {
//! \~russian Применяет функцию к каждой строке (с возможностью изменения). mat.forEach(f);
//! \~\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; 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>(std::move(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);
@@ -1410,6 +346,5 @@ inline PICout operator<<(PICout s, const PIVector2D<T> & v) {
return s; return s;
} }
//! \}
#endif // PIVECTOR2D_H #endif // PIVECTOR2D_H

View File

@@ -1,17 +1,17 @@
//! \addtogroup Core /*! \file pibase.h
//! \{ * \ingroup Core
//! \~\file pibase.h * \~\brief
//! \brief * \~english Base types and functions
//! \~english Base types and functions * \~russian Базовые типы и методы
//! \~russian Базовые типы и методы *
//! \details * \~\details
//! \~english * \~english
//! This file implements first layer above the system and * This file implements first layer above the system and
//! declares some basic useful functions * declares some basic useful functions
//! \~russian * \~russian
//! Этот файл реализует первый слой после системы и объявляет * Этот файл реализует первый слой после системы и объявляет
//! несколько базовых полезных методов * несколько базовых полезных методов
//! \~\} */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Base types and functions Base types and functions
@@ -245,9 +245,6 @@ 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);
@@ -285,9 +282,6 @@ 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);
@@ -515,87 +509,51 @@ inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
} }
//! \~\brief
//! \~english Generic hash function, returns 0 for unknown types
//! \~russian Хэш-функция общего назначения, возвращает 0 для неизвестных типов
template<typename T> template<typename T>
inline uint piHash(const T & v) { inline uint piHash(const T & v) {
return 0; return 0;
} }
//! \~\brief
//! \~english Hash function specialization for char type
//! \~russian Специализация хэш-функции для типа char
template<> template<>
inline uint piHash(const char & v) { inline uint piHash(const char & v) {
return (uint)v; return (uint)v;
} }
//! \~\brief
//! \~english Hash function specialization for uchar type
//! \~russian Специализация хэш-функции для типа uchar
template<> template<>
inline uint piHash(const uchar & v) { inline uint piHash(const uchar & v) {
return (uint)v; return (uint)v;
} }
//! \~\brief
//! \~english Hash function specialization for short type
//! \~russian Специализация хэш-функции для типа short
template<> template<>
inline uint piHash(const short & v) { inline uint piHash(const short & v) {
return (uint)v; return (uint)v;
} }
//! \~\brief
//! \~english Hash function specialization for ushort type
//! \~russian Специализация хэш-функции для типа ushort
template<> template<>
inline uint piHash(const ushort & v) { inline uint piHash(const ushort & v) {
return (uint)v; return (uint)v;
} }
//! \~\brief
//! \~english Hash function specialization for int type
//! \~russian Специализация хэш-функции для типа int
template<> template<>
inline uint piHash(const int & v) { inline uint piHash(const int & v) {
return (uint)v; return (uint)v;
} }
//! \~\brief
//! \~english Hash function specialization for uint type
//! \~russian Специализация хэш-функции для типа uint
template<> template<>
inline uint piHash(const uint & v) { inline uint piHash(const uint & v) {
return (uint)v; return (uint)v;
} }
//! \~\brief
//! \~english Hash function specialization for llong type using piHashData
//! \~russian Специализация хэш-функции для типа llong с использованием piHashData
template<> template<>
inline uint piHash(const llong & v) { inline uint piHash(const llong & v) {
return piHashData((const uchar *)&v, sizeof(v)); return piHashData((const uchar *)&v, sizeof(v));
} }
//! \~\brief
//! \~english Hash function specialization for ullong type using piHashData
//! \~russian Специализация хэш-функции для типа ullong с использованием piHashData
template<> template<>
inline uint piHash(const ullong & v) { inline uint piHash(const ullong & v) {
return piHashData((const uchar *)&v, sizeof(v)); return piHashData((const uchar *)&v, sizeof(v));
} }
//! \~\brief
//! \~english Hash function specialization for float type
//! \~russian Специализация хэш-функции для типа float
template<> template<>
inline uint piHash(const float & v) { inline uint piHash(const float & v) {
return (uint)v; return (uint)v;
} }
//! \~\brief
//! \~english Hash function specialization for double type using piHashData
//! \~russian Специализация хэш-функции для типа double с использованием piHashData
template<> template<>
inline uint piHash(const double & v) { inline uint piHash(const double & v) {
return piHashData((const uchar *)&v, sizeof(v)); return piHashData((const uchar *)&v, sizeof(v));
} }
//! \~\brief
//! \~english Hash function specialization for ldouble type using piHashData
//! \~russian Специализация хэш-функции для типа ldouble с использованием piHashData
template<> template<>
inline uint piHash(const ldouble & v) { inline uint piHash(const ldouble & v) {
return piHashData((const uchar *)&v, sizeof(v)); return piHashData((const uchar *)&v, sizeof(v));
@@ -726,12 +684,11 @@ inline bool piDeleteSafety(T *& pointer) {
//! \~english In this example "Error!" will be printed on every \b false function return. //! \~english In this example "Error!" will be printed on every \b false function return.
//! \~russian В данном примере будет выведен "Error!" при каждом \b false возврате из функции. //! \~russian В данном примере будет выведен "Error!" при каждом \b false возврате из функции.
class PIP_EXPORT PIScopeExitCall { class PIP_EXPORT PIScopeExitCall {
NO_COPY_CLASS(PIScopeExitCall)
public: public:
//! \~\brief //! \~\brief
//! \~english Constructor that takes a function to execute //! \~english Constructor that takes a function to execute
//! \~russian Конструктор, который принимает функцию для выполнения //! \~russian Конструктор, который принимает функцию для выполнения
explicit PIScopeExitCall(std::function<void()> f): func(std::move(f)) {} explicit PIScopeExitCall(std::function<void()> f): func(f) {}
//! \~\brief //! \~\brief
//! \~english Destructor that executes the function if it exists //! \~english Destructor that executes the function if it exists
@@ -759,6 +716,8 @@ public:
} }
private: private:
NO_COPY_CLASS(PIScopeExitCall)
std::function<void()> func; std::function<void()> func;
}; };
@@ -767,40 +726,26 @@ private:
//! \~english Inherit from this class to make your class non-trivially copyable. //! \~english Inherit from this class to make your class non-trivially copyable.
//! \~russian Наследуйтесь от этого класса чтобы сделать свой класс нетривиально копируемым. //! \~russian Наследуйтесь от этого класса чтобы сделать свой класс нетривиально копируемым.
struct PIP_EXPORT PINonTriviallyCopyable { struct PIP_EXPORT PINonTriviallyCopyable {
PINonTriviallyCopyable() = default; PINonTriviallyCopyable() noexcept = default;
PINonTriviallyCopyable(const PINonTriviallyCopyable &) = default; PINonTriviallyCopyable(const PINonTriviallyCopyable &) noexcept = default;
PINonTriviallyCopyable(PINonTriviallyCopyable &&) ; PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept;
PINonTriviallyCopyable & operator=(const PINonTriviallyCopyable &) = default; PINonTriviallyCopyable & operator=(const PINonTriviallyCopyable &) noexcept = default;
PINonTriviallyCopyable & operator=(PINonTriviallyCopyable &&) = default; PINonTriviallyCopyable & operator=(PINonTriviallyCopyable &&) noexcept = default;
~PINonTriviallyCopyable() = default; ~PINonTriviallyCopyable() = default;
}; };
inline PINonTriviallyCopyable::PINonTriviallyCopyable(PINonTriviallyCopyable &&) = default; inline PINonTriviallyCopyable::PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept = default;
//! \~\brief
//! \~english Template struct for extracting function type from callable objects
//! \~russian Шаблонная структура для извлечения типа функции из вызываемых объектов
template<typename T> template<typename T>
struct FunctionType { struct FunctionType {
using Type = void; using Type = void;
}; };
//! \~\brief
//! \~english Specialization for member function pointers
//! \~russian Специализация для указателей на члены класса
template<typename Ret, typename Class, typename... Args> template<typename Ret, typename Class, typename... Args>
struct FunctionType<Ret (Class::*)(Args...) const> { struct FunctionType<Ret (Class::*)(Args...) const> {
using Type = std::function<Ret(Args...)>; using Type = std::function<Ret(Args...)>;
}; };
//! \~\brief
//! \~english Convert lambda/functional object to std::function
//! \~russian Преобразует лямбду/функциональный объект в std::function
//! \~\details
//! \~english
//! Uses FunctionType template to extract the function signature from the callable object
//! \~russian
//! Использует шаблон FunctionType для извлечения сигнатуры функции из вызываемого объекта
template<typename L> template<typename L>
typename FunctionType<decltype(&L::operator())>::Type toStdFunction(L const & func) { typename FunctionType<decltype(&L::operator())>::Type toStdFunction(L const & func) {
return func; return func;

View File

@@ -1,17 +1,15 @@
//! \addtogroup Core /*! \file pibase_macros.h
//! \{ * \ingroup Core
//! \~\file pibase_macros.h * \~\brief
//! \brief * \~english Base macros
//! \~english Base macros * \~russian Базовые макросы
//! \~russian Базовые макросы *
//! \details * \~\details
//! \~english * \~english
//! This file declares basic useful macros for the PIP library including platform detection, * This file declares basic useful maros
//! compiler-specific configurations, and utility macros for private data handling. * \~russian
//! \~russian * Этот файл объявляет основные вспомогательные макросы
//! Этот файл объявляет основные вспомогательные макросы для библиотеки PIP, включая обнаружение платформы, */
//! конфигурации, специфичные для компилятора, и служебные макросы для работы с приватными данными.
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Base macros Base macros
@@ -52,118 +50,147 @@
#ifdef DOXYGEN #ifdef DOXYGEN
//! \~\brief
//! \~english Major value of PIP version //! \~english Major value of PIP version
//! \~russian Мажорная версия PIP //! \~russian Мажорная версия PIP
# define PIP_VERSION_MAJOR # define PIP_VERSION_MAJOR
//! \~\brief
//! \~english Minor value of PIP version //! \~english Minor value of PIP version
//! \~russian Минорная версия PIP //! \~russian Минорная версия PIP
# define PIP_VERSION_MINOR # define PIP_VERSION_MINOR
//! \~\brief
//! \~english Revision value of PIP version //! \~english Revision value of PIP version
//! \~russian Ревизия версии PIP //! \~russian Ревизия версии PIP
# define PIP_VERSION_REVISION # define PIP_VERSION_REVISION
//! \~\brief
//! \~english Suffix of PIP version //! \~english Suffix of PIP version
//! \~russian Суффикс версии PIP //! \~russian Суффикс версии PIP
# define PIP_VERSION_SUFFIX # define PIP_VERSION_SUFFIX
//! \~\brief
//! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision) //! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
//! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision) //! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision)
# define PIP_VERSION # define PIP_VERSION
//! \~\brief
//! \~english Macro is defined when compile-time debug is enabled //! \~english Macro is defined when compile-time debug is enabled
//! \~russian Макрос объявлен когда включена compile-time отладка //! \~russian Макрос объявлен когда включена compile-time отладка
# define PIP_DEBUG # define PIP_DEBUG
//! \~\brief
//! \~english Macro is defined when operation system is any Windows //! \~english Macro is defined when operation system is any Windows
//! \~russian Макрос объявлен когда операционная система Windows //! \~russian Макрос объявлен когда операционная система Windows
# define WINDOWS # define WINDOWS
//! \~\brief
//! \~english Macro is defined when operation system is QNX or Blackberry //! \~english Macro is defined when operation system is QNX or Blackberry
//! \~russian Макрос объявлен когда операционная система QNX или Blackberry //! \~russian Макрос объявлен когда операционная система QNX или Blackberry
# define QNX # define QNX
//! \~\brief
//! \~english Macro is defined when operation system is Blackberry //! \~english Macro is defined when operation system is Blackberry
//! \~russian Макрос объявлен когда операционная система Blackberry //! \~russian Макрос объявлен когда операционная система Blackberry
# define BLACKBERRY # define BLACKBERRY
//! \~\brief
//! \~english Macro is defined when operation system is FreeBSD //! \~english Macro is defined when operation system is FreeBSD
//! \~russian Макрос объявлен когда операционная система FreeBSD //! \~russian Макрос объявлен когда операционная система FreeBSD
# define FREE_BSD # define FREE_BSD
//! \~\brief
//! \~english Macro is defined when operation system is Mac OS //! \~english Macro is defined when operation system is Mac OS
//! \~russian Макрос объявлен когда операционная система Mac OS //! \~russian Макрос объявлен когда операционная система Mac OS
# define MAC_OS # define MAC_OS
//! \~\brief
//! \~english Macro is defined when operation system is Android //! \~english Macro is defined when operation system is Android
//! \~russian Макрос объявлен когда операционная система Android //! \~russian Макрос объявлен когда операционная система Android
# define ANDROID # define ANDROID
//! \~\brief
//! \~english Macro is defined when operation system is any Linux //! \~english Macro is defined when operation system is any Linux
//! \~russian Макрос объявлен когда операционная система Linux //! \~russian Макрос объявлен когда операционная система Linux
# define LINUX # define LINUX
//! \~\brief
//! \~english Macro is defined when operation system is FreeRTOS //! \~english Macro is defined when operation system is FreeRTOS
//! \~russian Макрос объявлен когда операционная система FreeRTOS //! \~russian Макрос объявлен когда операционная система FreeRTOS
# define FREERTOS # define FREERTOS
//! \~\brief
//! \~english Macro is defined when compiler is GCC or MinGW //! \~english Macro is defined when compiler is GCC or MinGW
//! \~russian Макрос объявлен когда компилятор GCC или MinGW //! \~russian Макрос объявлен когда компилятор GCC или MinGW
# define CC_GCC # define CC_GCC
//! \~\brief
//! \~english Macro is defined when PIP is decided that host is support language //! \~english Macro is defined when PIP is decided that host is support language
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию //! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
# define HAS_LOCALE # define HAS_LOCALE
//! \~\brief
//! \~english Macro is defined when PIP is building for embedded systems //! \~english Macro is defined when PIP is building for embedded systems
//! \~russian Макрос объявлен когда PIP собирается для встраиваемых систем //! \~russian Макрос объявлен когда PIP собирается для встраиваемых систем
# define MICRO_PIP # define MICRO_PIP
//! \~\brief
//! \~english Macro is defined when compiler is Visual Studio //! \~english Macro is defined when compiler is Visual Studio
//! \~russian Макрос объявлен когда компилятор Visual Studio //! \~russian Макрос объявлен когда компилятор Visual Studio
# define CC_VC # define CC_VC
//! \~\brief
//! \~english Macro is defined when compiler is AVR GCC //! \~english Macro is defined when compiler is AVR GCC
//! \~russian Макрос объявлен когда компилятор AVR GCC //! \~russian Макрос объявлен когда компилятор AVR GCC
# define CC_AVR_GCC # define CC_AVR_GCC
//! \~\brief
//! \~english Macro is defined when compiler is unknown //! \~english Macro is defined when compiler is unknown
//! \~russian Макрос объявлен когда компилятор неизвестен //! \~russian Макрос объявлен когда компилятор неизвестен
# define CC_OTHER # define CC_OTHER
//! \~\brief
//! \~english Macro to declare private section, "export" is optional //! \~english Macro to declare private section, "export" is optional
//! \~russian Макрос для объявления частной секции, "export" необязателен //! \~russian Макрос для объявления частной секции, "export" необязателен
# define PRIVATE_DECLARATION(export) # define PRIVATE_DECLARATION(export)
//! \~\brief
//! \~english Macro to start definition of private section //! \~english Macro to start definition of private section
//! \~russian Макрос для начала реализации частной секции //! \~russian Макрос для начала реализации частной секции
# define PRIVATE_DEFINITION_START(Class) # define PRIVATE_DEFINITION_START(Class)
//! \~\brief
//! \~english Macro to end definition of private section //! \~english Macro to end definition of private section
//! \~russian Макрос для окончания реализации частной секции //! \~russian Макрос для окончания реализации частной секции
# define PRIVATE_DEFINITION_END(Class) # define PRIVATE_DEFINITION_END(Class)
//! \~\brief
//! \~english Macro to access private section by pointer //! \~english Macro to access private section by pointer
//! \~russian Макрос для доступа к частной секции //! \~russian Макрос для доступа к частной секции
# define PRIVATE # define PRIVATE
//! \~english Macro to access private section by pointer without braces () //! \~\brief
//! \~english Macro to access private section by pointer without brakes ()
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок () //! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
# define PRIVATEWB # define PRIVATEWB
//! \~\brief
//! \~english Macro to start static initializer //! \~english Macro to start static initializer
//! \~russian Макрос для начала статической инициализации //! \~russian Макрос для начала статической инициализации
# define STATIC_INITIALIZER_BEGIN # define STATIC_INITIALIZER_BEGIN
//! \~\brief
//! \~english Macro to end static initializer //! \~english Macro to end static initializer
//! \~russian Макрос для окончания статической инициализации //! \~russian Макрос для окончания статической инициализации
# define STATIC_INITIALIZER_END # define STATIC_INITIALIZER_END
//! \~\brief
//! \~english Macro to remove class copy availability //! \~english Macro to remove class copy availability
//! \~russian Макрос для запрета копирования класса //! \~russian Макрос для запрета копирования класса
# define NO_COPY_CLASS(Class) # define NO_COPY_CLASS(Class)
//! \~\brief
//! \~english Macro to supress compiler warning about unused variable //! \~english Macro to supress compiler warning about unused variable
//! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной //! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной
# define NO_UNUSED(x) # define NO_UNUSED(x)
@@ -293,9 +320,6 @@ typedef long long ssize_t;
// Private data macros // Private data macros
#ifndef DOXYGEN #ifndef DOXYGEN
//! \~english Macro to declare private section, "export" is optional
//! \~russian Макрос для объявления частной секции, "export" необязателен
//! \~sa PRIVATE PRIVATEWB
# define PRIVATE_DECLARATION(e) \ # define PRIVATE_DECLARATION(e) \
struct __Private__; \ struct __Private__; \
friend struct __Private__; \ friend struct __Private__; \
@@ -308,20 +332,10 @@ typedef long long ssize_t;
}; \ }; \
__PrivateInitializer__ __privateinitializer__; __PrivateInitializer__ __privateinitializer__;
//! \~english Macro to start definition of private section
//! \~russian Макрос для начала реализации частной секции
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
# define PRIVATE_DEFINITION_START(c) struct c::__Private__ { # define PRIVATE_DEFINITION_START(c) struct c::__Private__ {
//! \~english Macro to end definition of private section without initialization
//! \~russian Макрос для окончания реализации частной секции без инициализации
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_START PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
# define PRIVATE_DEFINITION_END_NO_INITIALIZE(c) \ # define PRIVATE_DEFINITION_END_NO_INITIALIZE(c) \
} \ } \
; ;
//! \~english Macro to initialize private section
//! \~russian Макрос для инициализации частной секции
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_START PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE PRIVATEWB
# define PRIVATE_DEFINITION_INITIALIZE(c) \ # define PRIVATE_DEFINITION_INITIALIZE(c) \
c::__PrivateInitializer__::__PrivateInitializer__() { \ c::__PrivateInitializer__::__PrivateInitializer__() { \
p = new c::__Private__(); \ p = new c::__Private__(); \
@@ -337,51 +351,31 @@ typedef long long ssize_t;
p = new c::__Private__(); \ p = new c::__Private__(); \
return *this; \ return *this; \
} }
//! \~english Macro to end definition of private section with initialization
//! \~russian Макрос для окончания реализации частной секции с инициализацией
//! \~sa PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE_DEFINITION_START PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
# define PRIVATE_DEFINITION_END(c) \ # define PRIVATE_DEFINITION_END(c) \
PRIVATE_DEFINITION_END_NO_INITIALIZE \ PRIVATE_DEFINITION_END_NO_INITIALIZE \
(c) PRIVATE_DEFINITION_INITIALIZE(c) (c) PRIVATE_DEFINITION_INITIALIZE(c)
//! \~english Macro to access private section by pointer
//! \~russian Макрос для доступа к частной секции
//! \~sa PRIVATEWB
# define PRIVATE (__privateinitializer__.p)
//! \~english Macro to access private section by pointer without braces () # define PRIVATE (__privateinitializer__.p)
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
//! \~sa PRIVATE
# define PRIVATEWB __privateinitializer__.p # define PRIVATEWB __privateinitializer__.p
#endif // DOXYGEN #endif // DOXYGEN
//! \~english Macro to remove class copy availability
//! \~russian Макрос для запрета копирования класса
#define NO_COPY_CLASS(name) \ #define NO_COPY_CLASS(name) \
name(const name &) = delete; \ name(const name &) = delete; \
name & operator=(const name &) = delete; name & operator=(const name &) = delete;
//! \~english Counter macro for unique identifier generation
//! \~russian Макрос счетчика для генерации уникальных идентификаторов
#define _PIP_ADD_COUNTER_WS(a, cnt, line) a##cnt##_##line #define _PIP_ADD_COUNTER_WS(a, cnt, line) a##cnt##_##line
#define _PIP_ADD_COUNTER_WF(a, cnt, line) _PIP_ADD_COUNTER_WS(a, cnt, line) #define _PIP_ADD_COUNTER_WF(a, cnt, line) _PIP_ADD_COUNTER_WS(a, cnt, line)
#define _PIP_ADD_COUNTER(a) _PIP_ADD_COUNTER_WF(a, __COUNTER__, __LINE__) #define _PIP_ADD_COUNTER(a) _PIP_ADD_COUNTER_WF(a, __COUNTER__, __LINE__)
//! \~english Macro to start static initializer
//! \~russian Макрос для начала статической инициализации
//! \~sa STATIC_INITIALIZER_END
#define STATIC_INITIALIZER_BEGIN \ #define STATIC_INITIALIZER_BEGIN \
class { \ class { \
class _Initializer_ { \ class _Initializer_ { \
public: \ public: \
_Initializer_() { _Initializer_() {
//! \~english Macro to end static initializer
//! \~russian Макрос для окончания статической инициализации
//! \~sa STATIC_INITIALIZER_BEGIN
#define STATIC_INITIALIZER_END \ #define STATIC_INITIALIZER_END \
} \ } \
} \ } \
@@ -390,12 +384,12 @@ typedef long long ssize_t;
_PIP_ADD_COUNTER(_pip_initializer_); _PIP_ADD_COUNTER(_pip_initializer_);
//! \~\brief
//! \~english Minimal sleep in milliseconds for internal PIP using //! \~english Minimal sleep in milliseconds for internal PIP using
//! \~russian Минимальное значание задержки в милисекундах для внутреннего использования в библиотеке PIP //! \~russian Минимальное значание задержки в милисекундах для внутреннего использования в библиотеке PIP
//! \~\details //! \~\details
//! \~english Using in \a piMinSleep(), \a PIThread, \a PITimer::Pool. By default 1ms. //! \~english Using in \a piMinSleep(), \a PIThread, \a PITimer::Pool. By default 1ms.
//! \~russian Используется в \a piMinSleep(), \a PIThread, \a PITimer::Pool. По умолчанию равна 1мс. //! \~russian Используется в \a piMinSleep(), \a PIThread, \a PITimer::Pool. По умолчанию равна 1мс.
//! \~\sa PIP_MIN_MSLEEP
#ifndef PIP_MIN_MSLEEP #ifndef PIP_MIN_MSLEEP
# ifndef MICRO_PIP # ifndef MICRO_PIP
# define PIP_MIN_MSLEEP 1. # define PIP_MIN_MSLEEP 1.
@@ -405,26 +399,19 @@ typedef long long ssize_t;
#endif #endif
//! \~\brief
//! \~english Macro used for infinite loop //! \~english Macro used for infinite loop
//! \~russian Макрос для бесконечного цикла //! \~russian Макрос для бесконечного цикла
//! \~\details
//! \~english Expands to \c for(;;) infinite loop construct
//! \~russian Раскрывается в конструкцию бесконечного цикла \c for(;;)
#define FOREVER for (;;) #define FOREVER for (;;)
//! \~\brief
//! \~english Macro used for infinite wait //! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания //! \~russian Макрос для бесконечного ожидания
//! \~\details
//! \~english Expands to infinite loop with periodic sleep calls for CPU-friendly waiting
//! \~russian Раскрывается в бесконечный цикл с периодическими вызовами sleep для экономии ресурсов CPU
#define FOREVER_WAIT FOREVER piMinSleep(); #define FOREVER_WAIT FOREVER piMinSleep();
//! \~\brief
//! \~english Macro used for infinite wait //! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания //! \~russian Макрос для бесконечного ожидания
//! \~\details
//! \~english Expands to infinite loop with periodic sleep calls for CPU-friendly waiting
//! \~russian Раскрывается в бесконечный цикл с периодическими вызовами sleep для экономии ресурсов CPU
//! \~\sa FOREVER_WAIT
#define WAIT_FOREVER FOREVER piMinSleep(); #define WAIT_FOREVER FOREVER piMinSleep();

View File

@@ -1,13 +1,9 @@
//! \addtogroup Core /*! \file picollection.h
//! \{ * \ingroup Core
//! \~\file picollection.h * \~\brief
//! \brief * \~english Unique classes collection
//! \~english Unique classes collection * \~russian Коллекция уникальных классов
//! \~russian Коллекция уникальных классов */
//! \details
//! \~english Helper module to collect and retrieve classes into groups using macros for automatic registration.
//! \~russian Модуль-помощник для сбора и получения классов в группы с помощью макросов для автоматической регистрации.
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network Peer - named I/O ethernet node, forming self-organized peering network
@@ -34,10 +30,10 @@
#ifdef DOXYGEN #ifdef DOXYGEN
//! \relatesalso PICollection //! \~\relatesalso PICollection
//! \~\brief //! \~\brief
//! \~english Adds existing object to group "group". //! \~english Add existing element "object" in group with name "group"
//! \~russian Добавляет существующий объект в группу "group". //! \~russian Добавляет существующий элемент "object" в группу с именем "group"
//! \~\details //! \~\details
//! \~english //! \~english
//! If this is no group with name "group" it will be created. //! If this is no group with name "group" it will be created.
@@ -50,21 +46,21 @@
//! то ничего не изменится. \n "object" должен быть наследником \a PIObject. //! то ничего не изменится. \n "object" должен быть наследником \a PIObject.
# define ADD_TO_COLLECTION(group, object) # define ADD_TO_COLLECTION(group, object)
//! \relatesalso PICollection //! \~\relatesalso PICollection
//! \~\brief //! \~\brief
//! \~english Adds existing object to group "group" and assigns name "name". //! \~english Add existing element "object" in group with name "group" and set its name to "name"
//! \~russian Добавляет существующий объект в группу "group" и присваивает ему имя "name". //! \~russian Добавляет существующий элемент "object" в группу с именем "group" и присваивает объекту имя "name"
//! \~\details //! \~\details
//! \~english //! \~english
//! Similar to \a ADD_TO_COLLECTION(group, object), but also sets object name. //! Similar to \a ADD_TO_COLLECTION(group, object) but set object name to "name"
//! \~russian //! \~russian
//! Аналогично \a ADD_TO_COLLECTION(group, object), но дополнительно задает имя объекта. //! Аналогично \a ADD_TO_COLLECTION(group, object), но присваивает имя объекту "name"
# define ADD_TO_COLLECTION_WITH_NAME(group, object, name) # define ADD_TO_COLLECTION_WITH_NAME(group, object, name)
//! \relatesalso PICollection //! \~\relatesalso PICollection
//! \~\brief //! \~\brief
//! \~english Creates and adds new object of class "class" to group "group". //! \~english Add new element of class "class" in group with name "group"
//! \~russian Создает и добавляет новый объект класса "class" в группу "group". //! \~russian Добавляет новый элемент класса "class" в группу с именем "group"
//! \~\details //! \~\details
//! \~english //! \~english
//! If this is no group with name "group" it will be created. //! If this is no group with name "group" it will be created.
@@ -77,17 +73,15 @@
//! то ничего не изменится. \n "class" должен быть любым классом, наследным от \a PIObject. //! то ничего не изменится. \n "class" должен быть любым классом, наследным от \a PIObject.
# define ADD_NEW_TO_COLLECTION(group, class) # define ADD_NEW_TO_COLLECTION(group, class)
//! \relatesalso PICollection //! \~\relatesalso PICollection
//! \~\brief //! \~\brief
//! \~english Creates and adds new object of class "class" to group "group" //! \~english Add new element of class "class" in group with name "group" and set its name to "name"
//! and assigns name "name". //! \~russian Добавляет новый элемент класса "class" в группу с именем "group" и присваивает объекту имя "name"
//! \~russian Создает и добавляет новый объект класса "class" в группу "group"
//! и присваивает ему имя "name".
//! \~\details //! \~\details
//! \~english //! \~english
//! Similar to \a ADD_NEW_TO_COLLECTION(group, class), but also sets object name. //! Similar to \a ADD_NEW_TO_COLLECTION(group, class) but set object name to "name"
//! \~russian //! \~russian
//! Аналогично \a ADD_NEW_TO_COLLECTION(group, class), но дополнительно задает имя объекта. //! Аналогично \a ADD_NEW_TO_COLLECTION(group, class), но присваивает имя объекту "name"
# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) # define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name)
#else #else
@@ -106,40 +100,28 @@
#endif #endif
//! \~\ingroup Core //! \ingroup Core
//! \~\brief //! \~\brief
//! \~english Global collection of %PIObject-based instances grouped by name. //! \~english Helper to collect and retrieve classes to groups.
//! \~russian Глобальная коллекция экземпляров на базе %PIObject, сгруппированных по имени. //! \~russian Помощник для создания и получения классов в группы.
class PIP_EXPORT PICollection { class PIP_EXPORT PICollection {
friend class __PICollectionInitializer; friend class __PICollectionInitializer;
public: public:
//! \~english Constructs collection helper.
//! \~russian Создает вспомогательный объект коллекции.
PICollection() { ; } PICollection() { ; }
//! \~english Returns names of all existing groups. //! \~english Returns all existing groups by their names
//! \~russian Возвращает имена всех существующих групп. //! \~russian Возвращает имена всех групп
static PIStringList groups(); static PIStringList groups();
//! \~english Returns all elements stored in group "group". //! \~english Returns all elements of group "group"
//! \~russian Возвращает все элементы, хранящиеся в группе "group". //! \~russian Возвращает все элементы группы "group"
static PIVector<const PIObject *> groupElements(const PIString & group); static PIVector<const PIObject *> groupElements(const PIString & group);
//! \~english Adds object to group "group" if that group has no object of the
//! same runtime class.
//! \~russian Добавляет объект в группу "group", если в группе еще нет объекта
//! того же класса времени выполнения.
static bool addToGroup(const PIString & group, const PIObject * element); static bool addToGroup(const PIString & group, const PIObject * element);
//! \~\ingroup Core
//! \~\brief
//! \~english Helper that registers object in collection during static initialization.
//! \~russian Вспомогательный класс, регистрирующий объект в коллекции при статической инициализации.
class PIP_EXPORT CollectionAdder { class PIP_EXPORT CollectionAdder {
public: public:
//! \~english Registers object in group and optionally assigns object name.
//! \~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

@@ -1,13 +1,3 @@
/*! \file picoremodule.h
* \ingroup Core
* \~\brief
* \~english Umbrella header for the Core module
* \~russian Агрегирующий заголовок модуля Core
*
* \~\details
* \~english Includes the public chunk stream, collection, JSON, object, property storage, and time headers.
* \~russian Подключает публичные заголовки потоков чанков, коллекций, JSON, объектов, хранилища свойств и времени.
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -44,12 +34,10 @@
//! \~russian \par Общее //! \~russian \par Общее
//! //!
//! \~english //! \~english
//! These headers provide platform abstraction, common macros, utility functions //! These files provides platform abstraction, useful macros, methods and classes
//! and base classes.
//! //!
//! \~russian //! \~russian
//! Эти заголовки предоставляют абстракцию платформы, общие макросы, //! Эти файлы обеспечивают абстракцию операционной системы, полезные макросы, методы и классы
//! вспомогательные функции и базовые классы.
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -1,10 +1,9 @@
//! \addtogroup Core /*! \file picout.h
//! \{ * \ingroup Core
//! \~\file picout.h * \~\brief
//! \brief * \~english Universal output to console class
//! \~english Universal output to console class * \~russian Универсальный вывод в консоль
//! \~russian Универсальный вывод в консоль */
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Universal output to console class Universal output to console class
@@ -117,8 +116,8 @@ enum PICoutFormat {
Dec /*! \~english Decimal representation of integers \~russian Десятичное представление для целых чисел */ = 0x04, Dec /*! \~english Decimal representation of integers \~russian Десятичное представление для целых чисел */ = 0x04,
Hex /*! \~english Hexadecimal representation of integers \~russian Шестнадцатеричное представление для целых чисел */ = 0x08, Hex /*! \~english Hexadecimal representation of integers \~russian Шестнадцатеричное представление для целых чисел */ = 0x08,
Bold /*! \~english Bold \~russian Жирный */ = 0x10, Bold /*! \~english Bold \~russian Жирный */ = 0x10,
Faint /*! \~english Faint \~russian Тусклый */ = 0x20, Faint /*! \~english \~russian */ = 0x20,
Italic /*! \~english Italic \~russian Курсив */ = 0x40, Italic /*! \~english \~russian */ = 0x40,
Underline /*! \~english Underline \~russian Подчеркнутый */ = 0x80, Underline /*! \~english Underline \~russian Подчеркнутый */ = 0x80,
Blink /*! \~english Blink \~russian Мигающий */ = 0x100, Blink /*! \~english Blink \~russian Мигающий */ = 0x100,
Black /*! \~english Black font \~russian Чёрный */ = 0x400, Black /*! \~english Black font \~russian Чёрный */ = 0x400,
@@ -154,15 +153,10 @@ enum class PICoutStdStream {
}; };
//! \~\ingroup Core //! \ingroup Core
//! \~\brief //! \~\brief
//! \~english Universal output to console class. //! \~english Universal output to console class.
//! \~russian Универсальный вывод в консоль. //! \~russian Универсальный вывод в консоль.
//! \details
//! \~english This class provides a universal output interface with support for various data types, formatting options, and multiple output
//! devices (console, buffer).
//! \~russian Данный класс предоставляет универсальный интерфейс вывода с поддержкой различных типов данных, опций форматирования и
//! нескольких устройств вывода (консоль, буфер).
class PIP_EXPORT PICout { class PIP_EXPORT PICout {
public: public:
//! \~english Default constructor with default features (AddSpaces and AddNewLine) //! \~english Default constructor with default features (AddSpaces and AddNewLine)
@@ -184,16 +178,10 @@ public:
public: public:
//! \~english Singleton access to %PICout::Notifier //! \~english Singleton access to %PICout::Notifier
//! \~russian Синглтон класса %PICout::Notifier //! \~russian Синглтон класса %PICout::Notifier
//! \details
//! \~english Returns the singleton instance of the Notifier class used for emitting PICout events.
//! \~russian Возвращает синглтон-экземпляр класса Notifier, используемого для посылки событий PICout.
static Notifier * instance(); static Notifier * instance();
//! \~english Object that emit events from %PICout //! \~english Object that emit events from %PICout
//! \~russian Объект, который посылает события от %PICout //! \~russian Объект, который посылает события от %PICout
//! \details
//! \~english Returns the PIObject instance that emits events when PICout with external buffer is destroyed.
//! \~russian Возвращает экземпляр PIObject, который посылает события при уничтожении PICout с внешним буфером.
static PIObject * object(); static PIObject * object();
private: private:
@@ -246,51 +234,26 @@ public:
//! \~english Output operator for <tt>"int"</tt> values //! \~english Output operator for <tt>"int"</tt> values
//! \~russian Оператор вывода для <tt>"int"</tt> значений //! \~russian Оператор вывода для <tt>"int"</tt> значений
//! \details
//! \~english Outputs an integer value to the configured stream with optional format (binary, octal, decimal, hexadecimal).
//! \~russian Выводит целочисленное значение в настроенный поток с опциональным форматированием (binary, octal, decimal, hexadecimal).
PICout & operator<<(int v); PICout & operator<<(int v);
//! \~english Output operator for <tt>"unsigned int"</tt> values //! \~english Output operator for <tt>"unsigned int"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned int"</tt> значений //! \~russian Оператор вывода для <tt>"unsigned int"</tt> значений
//! \details
//! \~english Outputs an unsigned integer value to the configured stream with optional format (binary, octal, decimal, hexadecimal).
//! \~russian Выводит беззнаковое целочисленное значение в настроенный поток с опциональным форматированием (binary, octal, decimal,
//! hexadecimal).
PICout & operator<<(uint v); PICout & operator<<(uint v);
//! \~english Output operator for <tt>"long"</tt> values //! \~english Output operator for <tt>"long"</tt> values
//! \~russian Оператор вывода для <tt>"long"</tt> значений //! \~russian Оператор вывода для <tt>"long"</tt> значений
//! \details
//! \~english Outputs a long integer value to the configured stream with optional format (binary, octal, decimal, hexadecimal).
//! \~russian Выводит длинное целочисленное значение в настроенный поток с опциональным форматированием (binary, octal, decimal,
//! hexadecimal).
PICout & operator<<(long v); PICout & operator<<(long v);
//! \~english Output operator for <tt>"unsigned long"</tt> values //! \~english Output operator for <tt>"unsigned long"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned long"</tt> значений //! \~russian Оператор вывода для <tt>"unsigned long"</tt> значений
//! \details
//! \~english Outputs an unsigned long integer value to the configured stream with optional format (binary, octal, decimal,
//! hexadecimal).
//! \~russian Выводит беззнаковое длинное целочисленное значение в настроенный поток с опциональным форматированием (binary, octal,
//! decimal, hexadecimal).
PICout & operator<<(ulong v); PICout & operator<<(ulong v);
//! \~english Output operator for <tt>"long long"</tt> values //! \~english Output operator for <tt>"long long"</tt> values
//! \~russian Оператор вывода для <tt>"long long"</tt> значений //! \~russian Оператор вывода для <tt>"long long"</tt> значений
//! \details
//! \~english Outputs a long long integer value to the configured stream with optional format (binary, octal, decimal, hexadecimal).
//! \~russian Выводит длинное long long целочисленное значение в настроенный поток с опциональным форматированием (binary, octal,
//! decimal, hexadecimal).
PICout & operator<<(llong v); PICout & operator<<(llong v);
//! \~english Output operator for <tt>"unsigned long long"</tt> values //! \~english Output operator for <tt>"unsigned long long"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned long long"</tt> значений //! \~russian Оператор вывода для <tt>"unsigned long long"</tt> значений
//! \details
//! \~english Outputs an unsigned long long integer value to the configured stream with optional format (binary, octal, decimal,
//! hexadecimal).
//! \~russian Выводит беззнаковое длинное long long целочисленное значение в настроенный поток с опциональным форматированием (binary,
//! octal, decimal, hexadecimal).
PICout & operator<<(ullong v); PICout & operator<<(ullong v);
//! \~english Output operator for <tt>"float"</tt> values //! \~english Output operator for <tt>"float"</tt> values
@@ -307,16 +270,10 @@ public:
//! \~english Output operator for pointers //! \~english Output operator for pointers
//! \~russian Оператор вывода для указателей //! \~russian Оператор вывода для указателей
//! \details
//! \~english Outputs a pointer address to the configured stream in hexadecimal format.
//! \~russian Выводит адрес указателя в настроенный поток в шестнадцатеричном формате.
PICout & operator<<(const void * v); PICout & operator<<(const void * v);
//! \~english Output operator for PIObject and ancestors //! \~english Output operator for PIObject and ancestors
//! \~russian Оператор вывода для PIObject и наследников //! \~russian Оператор вывода для PIObject и наследников
//! \details
//! \~english Outputs a PIObject or its descendants to the configured stream, including class name and object name.
//! \~russian Выводит PIObject или его наследников в настроенный поток, включая имя класса и имя объекта.
PICout & operator<<(const PIObject * v); PICout & operator<<(const PIObject * v);
//! \~english Output operator for \a PICoutSpecialChar values //! \~english Output operator for \a PICoutSpecialChar values
@@ -325,18 +282,10 @@ public:
//! \~english Output operator for \a PIFlags<PICoutFormat> values //! \~english Output operator for \a PIFlags<PICoutFormat> values
//! \~russian Оператор вывода для \a PIFlags<PICoutFormat> //! \~russian Оператор вывода для \a PIFlags<PICoutFormat>
//! \details
//! \~english Sets output format flags (binary, octal, decimal, hexadecimal, bold, colors) for subsequent integer output.
//! \~russian Устанавливает флаги форматирования вывода (binary, octal, decimal, hexadecimal, bold, colors) для последующего вывода
//! целых чисел.
PICout & operator<<(PIFlags<PICoutManipulators::PICoutFormat> v); PICout & operator<<(PIFlags<PICoutManipulators::PICoutFormat> v);
//! \~english Output operator for \a PICoutFormat values //! \~english Output operator for \a PICoutFormat values
//! \~russian Оператор вывода для \a PICoutFormat //! \~russian Оператор вывода для \a PICoutFormat
//! \details
//! \~english Sets output format flag (binary, octal, decimal, hexadecimal, bold, colors) for subsequent integer output.
//! \~russian Устанавливает флаг форматирования вывода (binary, octal, decimal, hexadecimal, bold, colors) для последующего вывода целых
//! чисел.
PICout & operator<<(PICoutManipulators::PICoutFormat v); PICout & operator<<(PICoutManipulators::PICoutFormat v);
//! \~english Do some action //! \~english Do some action
@@ -352,72 +301,45 @@ public:
PICout & setControls(PICoutManipulators::PICoutControls c); PICout & setControls(PICoutManipulators::PICoutControls c);
//! \~english Exec \a saveControls() and set control flags to "c" //! \~english Exec \a saveControls() and set control flags to "c"
//! \~russian Выполнить \a saveControls() и установить флаги "c" //! \~russian Иыполнить \a saveControls() и Установить флаги "c"
PICout & saveAndSetControls(PICoutManipulators::PICoutControls c); PICout & saveAndSetControls(PICoutManipulators::PICoutControls c);
//! \~english Save control flags to internal stack //! \~english Save control flags to internal stack
//! \~russian Сохраняет состояние флагов во внутренний стек //! \~russian Сохраняет состояние флагов во внутренний стек
//! \details //! \~\sa \a restoreControl()
//! \~english Saves the current control flags to an internal stack for later restoration using restoreControls().
//! \~russian Сохраняет текущие флаги управления во внутренний стек для последующего восстановления с помощью restoreControls().
//! \~\sa \a restoreControls()
PICout & saveControls(); PICout & saveControls();
//! \~english Restore control flags from internal stack //! \~english Restore control flags from internal stack
//! \~russian Восстанавливает состояние флагов из внутреннего стека //! \~russian Восстанавливает состояние флагов из внутреннего стека
//! \details //! \~\sa \a saveControl()
//! \~english Restores the control flags from the internal stack that were previously saved using saveControls().
//! \~russian Восстанавливает флаги управления из внутреннего стека, которые были ранее сохранены с помощью saveControls().
//! \~\sa \a saveControls()
PICout & restoreControls(); PICout & restoreControls();
//! \~english Conditional put space character to output //! \~english Conditional put space character to output
//! \~russian Условно добавляет пробел //! \~russian Условно добавляет пробел
//! \details
//! \~english Conditionally adds a space character to the output if the AddSpaces control flag is enabled.
//! \~russian Условно добавляет пробел в вывод, если включен флаг управления AddSpaces.
PICout & space(); PICout & space();
//! \~english Conditional put quote character to output //! \~english Conditional put quote character to output
//! \~russian Условно добавляет кавычки //! \~russian Условно добавляет кавычки
//! \details
//! \~english Conditionally adds quote characters to the output if the AddQuotes control flag is enabled.
//! \~russian Условно добавляет кавычки в вывод, если включен флаг управления AddQuotes.
PICout & quote(); PICout & quote();
//! \~english Conditional put new line character to output //! \~english Conditional put new line character to output
//! \~russian Условно добавляет новую строку //! \~russian Условно добавляет новую строку
//! \details
//! \~english Conditionally adds a newline character to the output if the AddNewLine control flag is enabled.
//! \~russian Условно добавляет символ новой строки в вывод, если включен флаг управления AddNewLine.
PICout & newLine(); PICout & newLine();
//! \~english Write char //! \~english Write char
//! \~russian Пишет символ //! \~russian Пишет символ
//! \details
//! \~english Writes a single character directly to the output stream without any formatting.
//! \~russian Записывает один символ непосредственно в поток вывода без какого-либо форматирования.
PICout & write(char c); PICout & write(char c);
//! \~english Write raw data //! \~english Write raw data
//! \~russian Пишет сырые символы //! \~russian Пишет сырые символы
//! \details
//! \~english Writes raw C-style string data directly to the output stream without any formatting.
//! \~russian Записывает сырые данные C-строки непосредственно в поток вывода без какого-либо форматирования.
PICout & write(const char * str); PICout & write(const char * str);
//! \~english Write raw data //! \~english Write raw data
//! \~russian Пишет сырые символы //! \~russian Пишет сырые символы
//! \details
//! \~english Writes raw data of specified length directly to the output stream without any formatting.
//! \~russian Записывает сырые данные указанной длины непосредственно в поток вывода без какого-либо форматирования.
PICout & write(const char * str, int len); PICout & write(const char * str, int len);
//! \~english Write raw \a PIString //! \~english Write raw \a PIString
//! \~russian Пишет сырой \a PIString //! \~russian Пишет сырой \a PIString
//! \details
//! \~english Writes raw PIString data directly to the output stream without any formatting.
//! \~russian Записывает сырые данные PIString непосредственно в поток вывода без какого-либо форматирования.
PICout & write(const PIString & s); PICout & write(const PIString & s);
//! \~english Output \a PIString to stdout //! \~english Output \a PIString to stdout
@@ -464,19 +386,11 @@ public:
//! \~english Construct with external buffer. //! \~english Construct with external buffer.
//! \~russian Конструктор с внешним буфером. //! \~russian Конструктор с внешним буфером.
//! \details
//! \~english Creates a PICout instance that outputs to an external PIString buffer with specified control flags.
//! \~russian Создает экземпляр PICout, который выводит данные во внешний буфер PIString с указанными флагами управления.
static PICout withExternalBuffer(PIString * buffer, static PICout withExternalBuffer(PIString * buffer,
PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces); PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces);
//! \~english Construct with external buffer and ID "id". See \a Notifier for details //! \~english Construct with external buffer and ID "id". See \a Notifier for details
//! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier //! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier
//! \details
//! \~english Creates a PICout instance with external buffer and notification ID. When the last copy is destroyed, it emits a finished()
//! event via Notifier.
//! \~russian Создает экземпляр PICout с внешним буфером и идентификатором уведомления. При уничтожении последней копии посылается
//! событие finished() через Notifier.
static PICout withExternalBufferAndID(PIString * buffer, static PICout withExternalBufferAndID(PIString * buffer,
int id, int id,
PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls); PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls);

View File

@@ -1,8 +1,8 @@
/*! \file piincludes.h /*! \file piincludes.h
* \ingroup Core * \ingroup Core
* \~\brief * \~\brief
* \~english Core includes and low-level helper functions * \~english Minimal PIP includes
* \~russian Базовые включения и низкоуровневые вспомогательные функции * \~russian Минимально-необходимые инклюды PIP
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -50,42 +50,27 @@ class PIWaitEvent;
struct lconv; struct lconv;
//! \~\ingroup Core
//! \~\brief
//! \~english Pointer to current C locale numeric settings
//! \~russian Указатель на текущие числовые настройки C locale
extern PIP_EXPORT lconv * currentLocale; extern PIP_EXPORT lconv * currentLocale;
//! \~\ingroup Core //! \ingroup Core
//! \~\brief //! \brief
//! \~english Returns readable description of the last system error in format //! \~english Return readable error description in format "code <number> - <description>"
//! "code <number> - <description>" //! \~russian Возвращает читаемое описание ошибки в формате "code <номер> - <описание>"
//! \~russian Возвращает читаемое описание последней системной ошибки в формате
//! "code <номер> - <описание>"
PIP_EXPORT PIString errorString(); PIP_EXPORT PIString errorString();
//! \~\ingroup Core //! \ingroup Core
//! \~\brief //! \brief
//! \~english Clears the last system error //! \~english Reset last error
//! \~russian Сбрасывает последнюю системную ошибку //! \~russian Сброс последней ошибки
PIP_EXPORT void errorClear(); PIP_EXPORT void errorClear();
//! \~\ingroup Core
//! \~\brief
//! \~english Seeds the global pseudo-random generator
//! \~russian Инициализирует глобальный генератор псевдослучайных чисел
PIP_EXPORT void randomize(); PIP_EXPORT void randomize();
//! \~\ingroup Core
//! \~\brief
//! \~english Returns next value from the global pseudo-random generator
//! \~russian Возвращает следующее значение глобального генератора псевдослучайных чисел
PIP_EXPORT int randomi(); PIP_EXPORT int randomi();
//! \~\ingroup Core //! \ingroup Core
//! \~\brief //! \brief
//! \~english Returns readable PIP version string //! \~english Return readable version of PIP
//! \~russian Возвращает строку версии PIP //! \~russian Возвращает читаемую версию PIP
PIP_EXPORT PIString PIPVersion(); PIP_EXPORT PIString PIPVersion();
#endif // PIINCLUDES_H #endif // PIINCLUDES_H

View File

@@ -1,12 +1,9 @@
//! \~\ingroup Core /*! \file piinit.h
//! \~\file piinit.h * \ingroup Core
//! \~\brief * \~\brief
//! \~english Library initialization * \~english Library initialization
//! \~russian Инициализация библиотеки * \~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
@@ -39,6 +36,7 @@
class PIFile; class PIFile;
class PIStringList; class PIStringList;
class PIP_EXPORT __PIInit_Initializer__ { class PIP_EXPORT __PIInit_Initializer__ {
public: public:
__PIInit_Initializer__(); __PIInit_Initializer__();
@@ -49,10 +47,7 @@ public:
static __PIInit_Initializer__ __piinit_initializer__; static __PIInit_Initializer__ __piinit_initializer__;
//! \~\ingroup Core
//! \~\brief
//! \~english Library initialization singleton and build information access point.
//! \~russian Синглтон инициализации библиотеки и точка доступа к сведениям о сборке.
class PIP_EXPORT PIInit { class PIP_EXPORT PIInit {
friend class __PIInit_Initializer__; friend class __PIInit_Initializer__;
friend class PIFile; friend class PIFile;
@@ -60,9 +55,9 @@ class PIP_EXPORT PIInit {
public: public:
~PIInit(); ~PIInit();
//! \~\ingroup Core //! \ingroup Core
//! \~english Build options enabled in the current PIP library //! \~english Build options which PIP library was built
//! \~russian Опции, включенные в текущей сборке библиотеки PIP //! \~russian Опции, с которыми был собран PIP
enum BuildOption { enum BuildOption {
boICU /*! \~english Unicode support by ICU \~russian Поддержка юникода через ICU */ = 0x01, boICU /*! \~english Unicode support by ICU \~russian Поддержка юникода через ICU */ = 0x01,
boUSB /*! \~english USB support \~russian Поддержка USB */ = 0x02, boUSB /*! \~english USB support \~russian Поддержка USB */ = 0x02,
@@ -74,19 +69,16 @@ 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 current global %PIInit instance.
//! \~russian Возвращает текущий глобальный экземпляр %PIInit.
static PIInit * instance() { return __PIInit_Initializer__::__instance__; } static PIInit * instance() { return __PIInit_Initializer__::__instance__; }
//! \~\ingroup Core //! \ingroup Core
//! \~english Returns whether build option was enabled //! \~english Returns if build option was enabled
//! \~russian Возвращает, была ли опция включена при сборке //! \~russian Возвращает была ли включена опция при сборке
static bool isBuildOptionEnabled(BuildOption o); static bool isBuildOptionEnabled(BuildOption o);
//! \~\ingroup Core //! \ingroup Core
//! \~english Returns enabled build options as string list //! \~english Returns build options as stringlist
//! \~russian Возвращает включенные опции сборки в виде списка строк //! \~russian Возвращает опции сборки как список строк
static PIStringList buildOptions(); static PIStringList buildOptions();
private: private:

View File

@@ -1,15 +1,9 @@
//! \~\ingroup Core /*! \file pimemoryblock.h
* \ingroup Core
//! \~\file pimemoryblock.h * \~\brief
//! \brief * \~english Base types and functions
//! \~english Memory block helper struct for data storage and binary stream operations * \~russian Базовые типы и методы
//! \~russian Вспомогательная структура памяти для хранения данных и операций с двоичным потоком */
//! \details
//! \~english The PIMemoryBlock struct provides a lightweight wrapper to store and restore custom blocks of data to/from PIBinaryStream. It
//! holds a pointer to data and its size in bytes.
//! \~russian Структура PIMemoryBlock предоставляет легковесный wrapper для сохранения и извлечения произвольных блоков данных в/из
//! PIBinaryStream. Она содержит указатель на данные и их размер в байтах.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Base types and functions Base types and functions
@@ -33,52 +27,49 @@
#define PIMEMORYBLOCK_H #define PIMEMORYBLOCK_H
//! \ingroup Core
//! \~\brief //! \include pimemoryblock.h
//! \~english Helper struct to store and restore custom blocks of data to/from PIBinaryStream //! \brief
//! \~russian Вспомогательная структура для сохранения и извлечения произвольных блоков данных в/из PIBinaryStream //! \~english Help struct to store/restore custom blocks of data to/from PIBinaryStream
//! \~russian Вспомогательная структура для сохранения/извлечения произвольного блока данных в/из PIBinaryStream
struct PIMemoryBlock { struct PIMemoryBlock {
public: public:
//! \~english Constructs empty memory block. //! \~english Constructs data block
//! \~russian Создает пустой блок памяти. //! \~russian Создает блок данных
PIMemoryBlock() {} PIMemoryBlock() {}
//! \~english Constructs memory block from pointer and size. //! \~english Constructs data block
//! \~russian Создает блок памяти из указателя и размера. //! \~russian Создает блок данных
PIMemoryBlock(const void * data_, const int size_) { PIMemoryBlock(const void * data_, const int size_) {
d = const_cast<void *>(data_); d = const_cast<void *>(data_);
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 Copy 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;
return *this; return *this;
} }
//! \~english Returns pointer to block data. //! \~english Pointer to data
//! \~russian Возвращает указатель на данные блока. //! \~russian Указатель на данные
void * data() { return d; } void * data() { return d; }
//! \~english Returns pointer to block data. //! \~english Pointer to data
//! \~russian Возвращает указатель на данные блока. //! \~russian Указатель на данные
const void * data() const { return d; } const void * data() const { return d; }
//! \~english Returns block size in bytes. //! \~english Size of data in bytes
//! \~russian Возвращает размер блока в байтах. //! \~russian Размер данных в байтах
int size() const { return s; } int size() const { return s; }
//! \~english Returns `true` when the block stores a non-null pointer. //! \~english Returns if this block points to nothing
//! \~russian Возвращает `true`, когда блок хранит ненулевой указатель. //! \~russian Возвращает пустой ли указатель на данные
bool isNull() const { return d; } bool isNull() const { return d; }
private: private:
@@ -86,10 +77,8 @@ private:
int s = 0; int s = 0;
}; };
//! \~\ingroup Core //! \~english Returns PIMemoryBlock from pointer to variable "ptr" with type "T"
//! \~\brief //! \~russian Возвращает PIMemoryBlock из указателя "ptr" типа "T"
//! \~english Creates %PIMemoryBlock for object pointed by "ptr".
//! \~russian Создает %PIMemoryBlock для объекта, на который указывает "ptr".
template<typename T> template<typename T>
PIMemoryBlock createMemoryBlock(const T * ptr) { PIMemoryBlock createMemoryBlock(const T * ptr) {
return PIMemoryBlock(ptr, sizeof(T)); return PIMemoryBlock(ptr, sizeof(T));

View File

@@ -21,6 +21,7 @@
#include "piconditionvar.h" #include "piconditionvar.h"
#include "pithread.h" #include "pithread.h"
#include "pitime.h"
#ifndef MICRO_PIP #ifndef MICRO_PIP
# include "pifile.h" # include "pifile.h"
# include "piiostream.h" # include "piiostream.h"

View File

@@ -1,8 +1,9 @@
//! \~\ingroup Core /*! \file piobject.h
//! \~\file piobject.h * \ingroup Core
//! \~\brief * \~\brief
//! \~english Base object class providing event -> handler mechanism * \~english Base object
//! \~russian Базовый класс объектов, обеспечивающий механизм событий -> обработчиков * \~russian Базовый класс
*/
/* /*
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
@@ -33,26 +34,10 @@
#include "pivariant.h" #include "pivariant.h"
#include "pivariantsimple.h" #include "pivariantsimple.h"
//! \~\ingroup Core //! \ingroup Core
//! \~\brief //! \~\brief
//! \~english Base class for objects that declare events, event handlers and registered methods. //! \~english This is base class for any classes which use events -> handlers mechanism.
//! \~russian Базовый класс для объектов, которые объявляют события, обработчики событий и зарегистрированные методы. //! \~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.
//! %PIObject stores named properties, keeps connection state and exposes a
//! small metaobject table used by \a CONNECTU(), \a execute() and related APIs.
//! Queued delivery runs on the performer object and requires explicit draining
//! through \a callQueuedEvents() or \a maybeCallQueuedEvents().
//! \~russian
//! PIObject является базовым классом для всех классов PIP, которым необходима событийная коммуникация.
//! Он обеспечивает механизм сигналов-слотов, систему свойств и управление жизненным циклом объектов.
//! %PIObject хранит именованные свойства, состояние соединений и небольшую
//! метаобъектную таблицу, которую используют \a CONNECTU(), \a execute() и
//! связанные методы. Отложенная доставка выполняется на объекте-исполнителе и
//! требует явного опустошения очереди через \a callQueuedEvents() или
//! \a maybeCallQueuedEvents().
class PIP_EXPORT PIObject { class PIP_EXPORT PIObject {
#ifndef MICRO_PIP #ifndef MICRO_PIP
friend class PIObjectManager; friend class PIObjectManager;
@@ -65,18 +50,16 @@ class PIP_EXPORT PIObject {
public: public:
NO_COPY_CLASS(PIObject); NO_COPY_CLASS(PIObject);
//! \~english Constructs an object and initializes its \c name property. //! \~english Contructs %PIObject with name "name"
//! \~russian Создает объект и инициализирует его свойство \c name. //! \~russian Создает %PIObject с именем "name"
explicit PIObject(const PIString & name = PIString()); explicit PIObject(const PIString & name = PIString());
//! \~english Destroys the object, raises \a deleted() and disconnects it from the event graph.
//! \~russian Уничтожает объект, вызывает \a deleted() и отключает его от событийного графа.
virtual ~PIObject(); virtual ~PIObject();
//! \~\ingroup Core //! \ingroup Core
//! \~\brief //! \~\brief
//! \~english Handle of one connection between a source object and a destination object or functor. //! \~english Helper class for obtain info about if connection successful and disconnect single connection.
//! \~russian Дескриптор одного соединения между объектом-источником и объектом-приемником либо функтором. //! \~russian Вспомогательный класс для получения информации об успешности соединения и возможности его разрыва.
class PIP_EXPORT Connection { class PIP_EXPORT Connection {
friend class PIObject; friend class PIObject;
Connection(void * sl, Connection(void * sl,
@@ -110,31 +93,28 @@ public:
int args_count; int args_count;
public: public:
//! \~english Constructs an invalid connection handle. //! \~english Contructs invalid %Connection
//! \~russian Создает недействительный дескриптор соединения. //! \~russian Создает недействительный %Connection
Connection(); Connection();
//! \~english Returns \c true when the connection was created successfully. //! \~english Returns if %Connection is valid
//! \~russian Возвращает \c true, если соединение было успешно создано. //! \~russian Возвращает успешен ли %Connection
bool isValid() const { return signal; } bool isValid() const { return signal; }
//! \~english Returns the source object that emits the event. //! \~english Returns source object
//! \~russian Возвращает объект-источник, который испускает событие. //! \~russian Возвращает объект-источник
PIObject * sourceObject() const { return src_o; } PIObject * sourceObject() const { return src_o; }
//! \~english Returns the destination object, or \c nullptr for a lambda connection. //! \~english Returns destination object or "nullptr" if this is lambda connection
//! \~russian Возвращает объект-приемник, либо \c nullptr для соединения с лямбда-функцией. //! \~russian Возвращает объект-приемник или "nullptr" если это соединение на лямбда-функцию
PIObject * destinationObject() const { return dest_o; } PIObject * destinationObject() const { return dest_o; }
//! \~english Returns the performer object, or \c nullptr for direct delivery. //! \~english Returns performer object or "nullptr" if this is non-queued connection
//! \~russian Возвращает объект-исполнитель, либо \c nullptr для прямой доставки. //! \~russian Возвращает объект-исполнитель или "nullptr" если это соединение не отложенное
//! \~\details
//! \~english Queued delivery runs only when the performer drains its queue.
//! \~russian Отложенная доставка выполняется только когда исполнитель обрабатывает свою очередь.
PIObject * performerObject() const { return performer; } PIObject * performerObject() const { return performer; }
//! \~english Disconnects this single connection. //! \~english Disconnect this %Connection, returns if operation successful
//! \~russian Разрывает только это соединение. //! \~russian Разрывает этот %Connection, возвращает успешен ли разрыв
bool disconnect() const; bool disconnect() const;
}; };
@@ -142,16 +122,14 @@ private:
uint _signature_; uint _signature_;
public: public:
//! \~english Returns the \c name property of this object. //! \~english Returns object name
//! \~russian Возвращает свойство \c name этого объекта. //! \~russian Возвращает имя объекта
PIString name() const { return property("name").toString(); } PIString name() const { return property("name").toString(); }
//! \~english Returns the registered class name of this object. //! \~english Returns object class name
//! \~russian Возвращает зарегистрированное имя класса этого объекта. //! \~russian Возвращает имя класса объекта
virtual const char * className() const { return "PIObject"; } virtual const char * className() const { return "PIObject"; }
//! \~english Returns the hash of \a className().
//! \~russian Возвращает хэш от \a className().
virtual uint classNameID() const { virtual uint classNameID() const {
static uint ret = PIStringAscii("PIObject").hash(); static uint ret = PIStringAscii("PIObject").hash();
return ret; return ret;
@@ -163,87 +141,51 @@ public:
return ret; return ret;
} }
//! \~english Returns the registered parent class name, or an empty string for the root. //! \~english Returns parent class name
//! \~russian Возвращает зарегистрированное имя родительского класса, либо пустую строку для корня. //! \~russian Возвращает имя родительского класса
virtual const char * parentClassName() const { return ""; } virtual const char * parentClassName() const { return ""; }
//! \~english Returns whether \a piCoutObj output is enabled for this object. //! \~english Return if \a piCoutObj of this object is active
//! \~russian Возвращает, включен ли вывод \a piCoutObj для этого объекта. //! \~russian Возвращает включен ли вывод \a piCoutObj для этого объекта
bool debug() const { return property("debug").toBool(); } bool debug() const { return property("debug").toBool(); }
//! \~english Sets the \c name property of this object. //! \~english Set object name
//! \~russian Устанавливает свойство \c name этого объекта. //! \~russian Устанавливает имя объекта
void setName(const PIString & name) { setProperty("name", name); } void setName(const PIString & name) { setProperty("name", name); }
//! \~english Enables or disables \a piCoutObj output for this object. //! \~english Set object \a piCoutObj active
//! \~russian Включает или отключает вывод \a piCoutObj для этого объекта. //! \~russian Включает или отключает вывод \a piCoutObj для этого объекта
void setDebug(bool debug) { setProperty("debug", debug); } void setDebug(bool debug) { setProperty("debug", debug); }
//! \~english Returns the property with name "name". //! \~english Returns property with name "name"
//! \~russian Возвращает свойство объекта по имени "name". //! \~russian Возвращает свойство объекта по имени "name"
PIVariant property(const char * name) const { return properties_.value(piHashData((const uchar *)name, strlen(name))); } PIVariant property(const char * name) const { return properties_.value(piHashData((const uchar *)name, strlen(name))); }
//! \~english Sets the property "name" to "value" and creates it if needed. //! \~english Set property with name "name" to "value". If there is no such property in object it will be added
//! \~russian Устанавливает свойство "name" в значение "value" и создаёт его при необходимости. //! \~russian Устанавливает у объекта свойство по имени "name" в "value". Если такого свойства нет, оно добавляется
//! \~\details
//! \~english Calls \a propertyChanged() after updating the stored value.
//! \~russian После обновления сохранённого значения вызывает \a propertyChanged().
void setProperty(const char * name, const PIVariant & value) { void setProperty(const char * name, const PIVariant & value) {
properties_[piHashData((const uchar *)name, strlen(name))] = value; properties_[piHashData((const uchar *)name, strlen(name))] = value;
propertyChanged(name); propertyChanged(name);
} }
//! \~english Returns whether the property "name" exists. //! \~english Returns if property with name "name" exists
//! \~russian Возвращает, существует ли свойство "name". //! \~russian Возвращает присутствует ли свойство по имени "name"
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))); }
//! \~english Enables or disables the internal object mutex during handler execution.
//! \~russian Включает или отключает внутренний мьютекс объекта во время выполнения обработчиков.
//! \~\details
//! \~english This flag affects direct and queued handler invocation for this object, but does not describe full thread-safety of the
//! class.
//! \~russian Этот флаг влияет на прямой и отложенный вызов обработчиков для данного объекта, но не описывает полную потокобезопасность
//! класса.
void setThreadSafe(bool yes) { thread_safe_ = yes; } void setThreadSafe(bool yes) { thread_safe_ = yes; }
//! \~english Returns whether the internal object mutex is enabled for handler execution.
//! \~russian Возвращает, включен ли внутренний мьютекс объекта для выполнения обработчиков.
bool isThreadSafe() const { return thread_safe_; } bool isThreadSafe() const { return thread_safe_; }
//! \~english Executes a registered method or handler method by name with the supplied arguments.
//! \~russian Выполняет зарегистрированный метод или метод-обработчик по имени с переданными аргументами.
//! \~\details
//! \~english
//! This helper works only with the registered-method table built from
//! \a EVENT_HANDLER*() and \a EVENT*() declarations. It does not provide
//! arbitrary reflection or complex overload resolution: the implementation
//! selects a suitable registered method by name and argument count.
//! \~russian
//! Этот вспомогательный метод работает только с таблицей зарегистрированных
//! методов, построенной из объявлений \a EVENT_HANDLER*() и \a EVENT*().
//! Он не предоставляет произвольную рефлексию и сложное разрешение
//! перегрузок: реализация выбирает подходящий зарегистрированный метод по
//! имени и числу аргументов.
bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl); bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl);
//! \~english Overload of \a execute() for a method without arguments.
//! \~russian Перегрузка \a execute() для метода без аргументов.
bool execute(const PIString & method) { return execute(method, PIVector<PIVariantSimple>()); } bool execute(const PIString & method) { return execute(method, PIVector<PIVariantSimple>()); }
//! \~english Overload of \a execute() for one argument.
//! \~russian Перегрузка \a execute() для одного аргумента.
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 Overload of \a execute() for two arguments.
//! \~russian Перегрузка \a execute() для двух аргументов.
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 Overload of \a execute() for three arguments.
//! \~russian Перегрузка \a execute() для трёх аргументов.
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 Overload of \a execute() for four arguments.
//! \~russian Перегрузка \a execute() для четырёх аргументов.
bool execute(const PIString & method, bool execute(const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
const PIVariantSimple & v1, const PIVariantSimple & v1,
@@ -252,36 +194,16 @@ public:
return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Queues execution of a registered method on the performer object.
//! \~russian Ставит выполнение зарегистрированного метода в очередь объекта-исполнителя.
//! \~\details
//! \~english
//! Delivery happens only when "performer" later calls \a callQueuedEvents()
//! or \a maybeCallQueuedEvents(). Argument values are transported through
//! \a PIVariantSimple, so queued arguments should be representable there.
//! \~russian
//! Доставка происходит только когда "performer" позже вызывает
//! \a callQueuedEvents() или \a maybeCallQueuedEvents(). Значения аргументов
//! передаются через \a PIVariantSimple, поэтому аргументы очереди должны в
//! нём представляться.
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl); bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl);
//! \~english Overload of \a executeQueued() for a method without arguments.
//! \~russian Перегрузка \a executeQueued() для метода без аргументов.
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 Overload of \a executeQueued() for one argument.
//! \~russian Перегрузка \a executeQueued() для одного аргумента.
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 Overload of \a executeQueued() for two arguments.
//! \~russian Перегрузка \a executeQueued() для двух аргументов.
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 Overload of \a executeQueued() for three arguments.
//! \~russian Перегрузка \a executeQueued() для трёх аргументов.
bool executeQueued(PIObject * performer, bool executeQueued(PIObject * performer,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -289,8 +211,6 @@ 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 Overload of \a executeQueued() for four arguments.
//! \~russian Перегрузка \a executeQueued() для четырёх аргументов.
bool executeQueued(PIObject * performer, bool executeQueued(PIObject * performer,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -300,30 +220,18 @@ public:
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Static convenience wrapper for \a execute().
//! \~russian Статическая удобная обёртка над \a execute().
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 Static overload of \a execute() without arguments.
//! \~russian Статическая перегрузка \a execute() без аргументов.
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 Static overload of \a execute() for one argument.
//! \~russian Статическая перегрузка \a execute() для одного аргумента.
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 Static overload of \a execute() for two arguments.
//! \~russian Статическая перегрузка \a execute() для двух аргументов.
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 Static overload of \a execute() for three arguments.
//! \~russian Статическая перегрузка \a execute() для трёх аргументов.
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 Static overload of \a execute() for four arguments.
//! \~russian Статическая перегрузка \a execute() для четырёх аргументов.
static bool execute(PIObject * o, static bool execute(PIObject * o,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -333,29 +241,19 @@ public:
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Static convenience wrapper for \a executeQueued().
//! \~russian Статическая удобная обёртка над \a executeQueued().
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 Static overload of \a executeQueued() without arguments.
//! \~russian Статическая перегрузка \a executeQueued() без аргументов.
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 Static overload of \a executeQueued() for one argument.
//! \~russian Статическая перегрузка \a executeQueued() для одного аргумента.
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 Static overload of \a executeQueued() for two arguments.
//! \~russian Статическая перегрузка \a executeQueued() для двух аргументов.
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 Static overload of \a executeQueued() for three arguments.
//! \~russian Статическая перегрузка \a executeQueued() для трёх аргументов.
static bool executeQueued(PIObject * o, static bool executeQueued(PIObject * o,
PIObject * performer, PIObject * performer,
const PIString & method, const PIString & method,
@@ -364,8 +262,6 @@ 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 Static overload of \a executeQueued() for four arguments.
//! \~russian Статическая перегрузка \a executeQueued() для четырёх аргументов.
static bool executeQueued(PIObject * o, static bool executeQueued(PIObject * o,
PIObject * performer, PIObject * performer,
const PIString & method, const PIString & method,
@@ -376,37 +272,22 @@ 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 diagnostics to the project output stream.
//! \~russian Выводит диагностическую информацию об объекте в проектный поток вывода.
void dump(const PIString & line_prefix = PIString()) const; void dump(const PIString & line_prefix = PIString()) const;
//! \~english Returns the registered inheritance scope of this object, including its own class. //! \~english Returns subclass scope of this object (including this class name)
//! \~russian Возвращает зарегистрированную цепочку наследования объекта, включая его собственный класс. //! \~russian Возвращает цепочку наследования объекта (вместе с классом самого объекта)
PIStringList scopeList() const; PIStringList scopeList() const;
//! \~english Returns full signatures of all registered event and handler methods for this class scope.
//! \~russian Возвращает полные сигнатуры всех зарегистрированных событий и обработчиков для области этого класса.
PIStringList methodsEH() const; PIStringList methodsEH() const;
//! \~english Returns whether a registered event or handler method with this name exists.
//! \~russian Возвращает, существует ли зарегистрированное событие или обработчик с таким именем.
bool isMethodEHContains(const PIString & name) const; bool isMethodEHContains(const PIString & name) const;
//! \~english Returns the comma-separated argument type list of a registered method.
//! \~russian Возвращает список типов аргументов зарегистрированного метода через запятую.
PIString methodEHArguments(const PIString & name) const; PIString methodEHArguments(const PIString & name) const;
//! \~english Returns the full registered signature of a method.
//! \~russian Возвращает полную зарегистрированную сигнатуру метода.
PIString methodEHFullFormat(const PIString & name) const; PIString methodEHFullFormat(const PIString & name) const;
//! \~english Returns the registered method name for the specified entry-point address.
//! \~russian Возвращает имя зарегистрированного метода для указанного адреса точки входа.
PIString methodEHFromAddr(const void * addr) const; PIString methodEHFromAddr(const void * addr) const;
//! \~english Low-level direct connection helper behind the legacy \c CONNECT* macros. // / Direct connect
//! \~russian Низкоуровневый помощник прямого соединения, лежащий под устаревшими макросами \c CONNECT*.
static PIObject::Connection static PIObject::Connection
piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc); piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
//! \~english Low-level name-based connection helper behind \a CONNECTU() and \a CONNECTU_QUEUED().
//! \~russian Низкоуровневый помощник соединения по имени, лежащий под \a CONNECTU() и \a CONNECTU_QUEUED().
static PIObject::Connection piConnectU(PIObject * src, static PIObject::Connection piConnectU(PIObject * src,
const PIString & sig, const PIString & sig,
PIObject * dest_o, PIObject * dest_o,
@@ -414,8 +295,6 @@ public:
const PIString & hname, const PIString & hname,
const char * loc, const char * loc,
PIObject * performer = 0); PIObject * performer = 0);
//! \~english Low-level helper that connects an event to a lambda or functor wrapper.
//! \~russian Низкоуровневый помощник, который соединяет событие с лямбдой или обёрткой функтора.
static PIObject::Connection piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc); static PIObject::Connection piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc);
template<typename PIINPUT, typename... PITYPES> template<typename PIINPUT, typename... PITYPES>
static std::function<void()> * __newFunctor(void (*stat_handler)(void *, PITYPES...), PIINPUT functor) { static std::function<void()> * __newFunctor(void (*stat_handler)(void *, PITYPES...), PIINPUT functor) {
@@ -423,33 +302,33 @@ public:
} }
//! \~english Disconnects this source object from a specific destination handler for event "sig". //! \~english Disconnect object from all connections with event name "sig", connected to destination object "dest" and handler "ev_h"
//! \~russian Разрывает соединения этого объекта-источника с конкретным обработчиком объекта-приемника для события "sig". //! \~russian Разрывает все соединения от события "sig" к объекту "dest" и обработчику "ev_h"
void piDisconnect(const PIString & sig, PIObject * dest, void * ev_h) { piDisconnect(this, sig, dest, ev_h); } void piDisconnect(const PIString & sig, PIObject * dest, void * ev_h) { piDisconnect(this, sig, dest, ev_h); }
//! \~english Disconnects this source object from all connections of event "sig" to destination object "dest". //! \~english Disconnect object from all connections with event name "sig", connected to destination object "dest"
//! \~russian Разрывает все соединения этого объекта-источника от события "sig" к объекту-приемнику "dest". //! \~russian Разрывает все соединения от события "sig" к объекту "dest"
void piDisconnect(const PIString & sig, PIObject * dest) { piDisconnect(this, sig, dest); } void piDisconnect(const PIString & sig, PIObject * dest) { piDisconnect(this, sig, dest); }
//! \~english Disconnects this source object from all connections of event "sig". //! \~english Disconnect object from all connections with event name "sig"
//! \~russian Разрывает все соединения этого объекта-источника от события "sig". //! \~russian Разрывает все соединения от события "sig"
void piDisconnect(const PIString & sig) { piDisconnect(this, sig); } void piDisconnect(const PIString & sig) { piDisconnect(this, sig); }
//! \~english Disconnects source object "src" from a specific destination handler for event "sig". //! \~english Disconnect object "src" from all connections with event name "sig", connected to destination object "dest" and handler
//! \~russian Разрывает соединения объекта-источника "src" с конкретным обработчиком объекта-приемника для события "sig". //! "ev_h"
//! \~russian Разрывает все соединения от события "sig" объекта "src" к объекту "dest" и обработчику "ev_h"
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h); static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h);
//! \~english Disconnects source object "src" from all connections of event "sig" to destination object "dest". //! \~english Disconnect object "src" from all connections with event name "sig", connected to destination object "dest"
//! \~russian Разрывает все соединения объекта-источника "src" от события "sig" к объекту-приемнику "dest". //! \~russian Разрывает все соединения от события "sig" объекта "src" к объекту "dest"
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest); static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest);
//! \~english Disconnects source object "src" from all connections of event "sig". //! \~english Disconnect object "src" from all connections with event name "sig"
//! \~russian Разрывает все соединения объекта-источника "src" от события "sig". //! \~russian Разрывает все соединения от события "sig" объекта "src"
static void piDisconnect(PIObject * src, const PIString & sig); static void piDisconnect(PIObject * src, const PIString & sig);
//! \~english Internal event delivery helper for registered events without arguments. // / Raise events
//! \~russian Внутренний помощник доставки для зарегистрированных событий без аргументов.
static void raiseEvent(PIObject * sender, const uint eventID) { static void raiseEvent(PIObject * sender, const uint eventID) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection i(sender->connections[j]); Connection i(sender->connections[j]);
@@ -478,8 +357,6 @@ public:
} }
} }
//! \~english Internal event delivery helper for registered events with one argument.
//! \~russian Внутренний помощник доставки для зарегистрированных событий с одним аргументом.
template<typename T0> template<typename T0>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) { static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
@@ -513,8 +390,6 @@ public:
if (!sender->isPIObject()) break; if (!sender->isPIObject()) break;
} }
} }
//! \~english Internal event delivery helper for registered events with two arguments.
//! \~russian Внутренний помощник доставки для зарегистрированных событий с двумя аргументами.
template<typename T0, typename T1> template<typename T0, typename T1>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1()) { static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1()) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
@@ -550,8 +425,6 @@ public:
if (!sender->isPIObject()) break; if (!sender->isPIObject()) break;
} }
} }
//! \~english Internal event delivery helper for registered events with three arguments.
//! \~russian Внутренний помощник доставки для зарегистрированных событий с тремя аргументами.
template<typename T0, typename T1, typename T2> template<typename T0, typename T1, typename T2>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
for (int j = 0; j < sender->connections.size_s(); ++j) { for (int j = 0; j < sender->connections.size_s(); ++j) {
@@ -589,8 +462,6 @@ public:
if (!sender->isPIObject()) break; if (!sender->isPIObject()) break;
} }
} }
//! \~english Internal event delivery helper for registered events with four arguments.
//! \~russian Внутренний помощник доставки для зарегистрированных событий с четырьмя аргументами.
template<typename T0, typename T1, typename T2, typename T3> template<typename T0, typename T1, typename T2, typename T3>
static void raiseEvent(PIObject * sender, static void raiseEvent(PIObject * sender,
const uint eventID, const uint eventID,
@@ -636,8 +507,7 @@ public:
} }
} }
//! \~english Returns the first live object with name "name", or \c nullptr. //! Returns PIObject* with name "name" or 0, if there is no object found
//! \~russian Возвращает первый живой объект с именем "name", либо \c nullptr.
static PIObject * findByName(const PIString & name) { static PIObject * findByName(const PIString & name) {
PIMutexLocker _ml(mutexObjects()); PIMutexLocker _ml(mutexObjects());
for (auto * i: PIObject::objects()) { for (auto * i: PIObject::objects()) {
@@ -647,12 +517,12 @@ public:
return nullptr; return nullptr;
} }
//! \~english Returns whether this pointer still refers to a live %PIObject instance. //! \~english Returns if this is valid %PIObject (check signature)
//! \~russian Возвращает, указывает ли этот указатель на ещё существующий экземпляр %PIObject. //! \~russian Возвращает действительный ли это %PIObject (проверяет подпись)
bool isPIObject() const { return isPIObject(this); } bool isPIObject() const { return isPIObject(this); }
//! \~english Returns whether this object belongs to class "T" or one of its registered descendants. //! \~english Returns if this is valid %PIObject subclass "T" (check signature and classname)
//! \~russian Возвращает, принадлежит ли этот объект классу "T" или одному из его зарегистрированных потомков. //! \~russian Возвращает действительный ли это наследник %PIObject типа "T" (проверяет подпись и имя класса)
template<typename T> template<typename T>
bool isTypeOf() const { bool isTypeOf() const {
if (!isPIObject()) return false; if (!isPIObject()) return false;
@@ -660,35 +530,30 @@ public:
return __meta_data()[classNameID()].scope_id.contains(T::__classNameIDS()); return __meta_data()[classNameID()].scope_id.contains(T::__classNameIDS());
} }
//! \~english Returns this object cast to "T" when \a isTypeOf<T>() succeeds, otherwise \c nullptr. //! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr"
//! \~russian Возвращает этот объект, приведённый к типу "T", если \a isTypeOf<T>() успешно, иначе \c nullptr. //! \~russian Возвращает преобразование к типу T если это действительный наследник типа "T" (проверяет через \a isTypeOf()), или
//! "nullptr"
template<typename T> template<typename T>
T * cast() const { T * cast() const {
if (!isTypeOf<T>()) return (T *)nullptr; if (!isTypeOf<T>()) return (T *)nullptr;
return (T *)this; return (T *)this;
} }
//! \~english Returns whether "o" points to a live %PIObject instance. //! \~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 Overload of \a isPIObject() for an untyped pointer.
//! \~russian Перегрузка \a isPIObject() для нетипизированного указателя.
static bool isPIObject(const void * o) { return isPIObject((PIObject *)o); } static bool isPIObject(const void * o) { return isPIObject((PIObject *)o); }
//! \~english Returns whether "o" belongs to class "T" or one of its registered descendants. //! \~english Returns if "o" is valid %PIObject subclass "T" (check signature and classname)
//! \~russian Возвращает, принадлежит ли "o" классу "T" или одному из его зарегистрированных потомков. //! \~russian Возвращает действительный ли "o" наследник %PIObject типа "T" (проверяет подпись и имя класса)
template<typename T> template<typename T>
static bool isTypeOf(const PIObject * o) { static bool isTypeOf(const PIObject * o) {
return o->isTypeOf<T>(); return o->isTypeOf<T>();
} }
//! \~english Overload of \a isTypeOf() for an untyped pointer.
//! \~russian Перегрузка \a isTypeOf() для нетипизированного указателя.
template<typename T> template<typename T>
static bool isTypeOf(const void * o) { static bool isTypeOf(const void * o) {
return isTypeOf<T>((PIObject *)o); return isTypeOf<T>((PIObject *)o);
} }
//! \~english Simplifies a C++ type spelling for registered-method metadata.
//! \~russian Упрощает запись типа C++ для метаданных зарегистрированных методов.
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 {
@@ -724,32 +589,36 @@ public:
}; };
typedef PIPair<const void *, __MetaFunc> __EHPair; typedef PIPair<const void *, __MetaFunc> __EHPair;
//! \~english Executes all queued deliveries posted to this performer object. //! \~english Execute all posted events from CONNECTU_QUEUED connections
//! \~russian Выполняет все отложенные доставки, поставленные в очередь этому объекту-исполнителю. //! \~russian Выполнить все отложенные события от CONNECTU_QUEUED соединений
void callQueuedEvents(); void callQueuedEvents();
//! \~\brief //! \~english
//! \~english Executes queued deliveries only when this object was used as a performer. //! \brief Check if any CONNECTU_QUEUED connections to this object and execute them
//! \~russian Выполняет отложенные доставки только если этот объект использовался как исполнитель. //! \details This function is more optimized than \a callQueuedEvents() for objects that doesn`t
//! \~\details //! appears as \"performer\" target at CONNECTU_QUEUED
//! \~english This helper is cheaper than unconditional \a callQueuedEvents() for objects that are rarely used as performer targets. //! \~russian
//! \~russian Этот помощник дешевле, чем безусловный \a callQueuedEvents(), для объектов, которые редко используются как исполнители. //! \brief Если было хотя бы одно CONNECTU_QUEUED соединение с исполнителем this, то выполнить события
//! \details Этот метод более оптимален, чем \a callQueuedEvents(), для объектов, которые не были в роли
//! \"performer\" в макросе CONNECTU_QUEUED
bool maybeCallQueuedEvents() { bool maybeCallQueuedEvents() {
if (proc_event_queue) callQueuedEvents(); if (proc_event_queue) callQueuedEvents();
return proc_event_queue; return proc_event_queue;
} }
//! \~english Schedules the object for deferred deletion. //! \~english Mark object to delete
//! \~russian Планирует отложенное удаление объекта. //! \~russian Пометить объект на удаление
void deleteLater(); void deleteLater();
EVENT1(deleted, PIObject *, o);
//! \events //! \events
//! \{ //! \{
//! \fn void deleted(PIObject * o) //! \fn void deleted(PIObject * o)
//! \brief //! \brief
//! \~english Raised immediately before object destruction. //! \~english Raise before object delete
//! \~russian Вызывается непосредственно перед уничтожением объекта. //! \~russian Вызывается перед удалением объекта
//! \~\warning //! \~\warning
//! \~english //! \~english
//! This event raised from destructor, so use only "o" numeric value, //! This event raised from destructor, so use only "o" numeric value,
@@ -757,23 +626,19 @@ public:
//! \~russian //! \~russian
//! Это событие вызывается из деструктора, поэтому используйте //! Это событие вызывается из деструктора, поэтому используйте
//! только численное значение "o", не надо кастовать его в другие типы! //! только численное значение "o", не надо кастовать его в другие типы!
EVENT1(deleted, PIObject *, o);
//! \} //! \}
static PIMutex & __meta_mutex(); static PIMutex & __meta_mutex();
static PIMap<uint, __MetaData> & __meta_data(); static PIMap<uint, __MetaData> & __meta_data(); // [hash(classname)]=__MetaData
protected: protected:
//! \~english Returns the source object that raised the current event. //! \~english Returns %PIObject* which has raised an event. This value is correct only in definition of some event handler
//! \~russian Возвращает объект-источник, который вызвал текущее событие. //! \~russian Возвращает %PIObject* который вызвал это событие. Значение допустимо только из методов обработчиков событий
//! \~\details
//! \~english This value is valid only while an event handler is running.
//! \~russian Это значение корректно только пока выполняется обработчик события.
PIObject * emitter() const { return emitter_; } PIObject * emitter() const { return emitter_; }
//! \~english Virtual method called after property "name" has been changed by \a setProperty(). //! \~english Virtual function executes after property with name "name" has been changed
//! \~russian Виртуальный метод, вызываемый после изменения свойства "name" через \a setProperty(). //! \~russian Виртуальная функция, вызывается после изменения любого свойства.
virtual void propertyChanged(const char * name) {} virtual void propertyChanged(const char * name) {}
private: private:
@@ -837,15 +702,8 @@ private:
}; };
#ifndef MICRO_PIP #ifndef MICRO_PIP
//! \~english Dumps application-level %PIObject diagnostics.
//! \~russian Выводит диагностическую информацию уровня приложения для %PIObject.
PIP_EXPORT void dumpApplication(bool with_objects = true); PIP_EXPORT void dumpApplication(bool with_objects = true);
//! \~english Dumps application-level %PIObject diagnostics to file "path".
//! \~russian Выводит диагностическую информацию уровня приложения для %PIObject в файл "path".
PIP_EXPORT bool dumpApplicationToFile(const PIString & path, bool with_objects = true); PIP_EXPORT bool dumpApplicationToFile(const PIString & path, bool with_objects = true);
#endif #endif
#endif // PIOBJECT_H #endif // PIOBJECT_H

View File

@@ -1,17 +1,9 @@
//! \~\ingroup Core /*! \file piobject_macros.h
//! \~\file piobject_macros.h * \ingroup Core
//! \~\brief * \~\brief
//! \~english PIObject macros for event system and object introspection * \~english PIObject macros
//! \~russian Макросы PIObject для событийной системы и интроспекции объектов * \~russian Макросы PIObject
//! \~\details */
//! \~english
//! This file declares the macro layer used by %PIObject-based classes:
//! class registration, event declaration, event handler declaration,
//! connection helpers and event raising helpers.
//! \~russian
//! Этот файл объявляет макросный слой для классов на базе %PIObject:
//! регистрацию класса, объявление событий, объявление обработчиков,
//! макросы соединения и макросы вызова событий.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Macros for PIObject Macros for PIObject
@@ -40,47 +32,47 @@
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Put this macro inside a direct %PIObject subclass definition to enable registered events, event handlers and class metadata. //! \~english You should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output
//! \~russian Поместите этот макрос внутрь объявления прямого наследника %PIObject, чтобы включить регистрацию событий, обработчиков и //! \~russian Необходимо использовать этот макрос после объявления класса для использования событийной системы и корректного вывода
//! метаданных класса. //! piCoutObj
# define PIOBJECT(name) # define PIOBJECT(name)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Put this macro inside a %PIObject subclass definition to inherit registered methods and class scope from "parent". //! \~english You should use this macro after class declaration to use EVENT and EVENT_HANDLER of parent class, and \a scopeList()
//! \~russian Поместите этот макрос внутрь объявления наследника %PIObject, чтобы унаследовать зарегистрированные методы и цепочку //! \~russian
//! классов от "parent".
# define PIOBJECT_SUBCLASS(name, parent) # define PIOBJECT_SUBCLASS(name, parent)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a registered event handler method with signature `ret name()`. //! \~english Declare event handler with name \"name\" and return type \"ret\", ret name()
//! \~russian Объявляет зарегистрированный метод-обработчик событий с сигнатурой `ret name()`. //! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name()
# define EVENT_HANDLER0(ret, name) ret name() # define EVENT_HANDLER0(ret, name) ret name()
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a registered event handler method with one argument. //! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0)
//! \~russian Объявляет зарегистрированный метод-обработчик событий с одним аргументом. //! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0)
# define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0) # define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a registered event handler method with two arguments. //! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1)
//! \~russian Объявляет зарегистрированный метод-обработчик событий с двумя аргументами. //! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1)
# define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1) # define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a registered event handler method with three arguments. //! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2)
//! \~russian Объявляет зарегистрированный метод-обработчик событий с тремя аргументами. //! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1, type2 var2)
# define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2) # define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a registered event handler method with four arguments. //! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
//! \~russian Объявляет зарегистрированный метод-обработчик событий с четырьмя аргументами. //! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1, type2 var2,
//! type3 var3)
# define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \ # define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \
ret name(type0 var0, type1 var1, type2 var2, type3 var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3)
@@ -93,32 +85,36 @@
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a virtual registered event handler method with signature `virtual ret name()`. //! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name()
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с сигнатурой `virtual ret name()`. //! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name()
# define EVENT_VHANDLER0(ret, name) virtual ret name() # define EVENT_VHANDLER0(ret, name) virtual ret name()
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a virtual registered event handler method with one argument. //! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0)
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с одним аргументом. //! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0)
# define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0) # define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a virtual registered event handler method with two arguments. //! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1)
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с двумя аргументами. //! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1
//! var1)
# define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1) # define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a virtual registered event handler method with three arguments. //! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с тремя аргументами. //! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1
//! var1, type2 var2)
# define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2) # define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare a virtual registered event handler method with four arguments. //! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2,
//! \~russian Объявляет виртуальный зарегистрированный метод-обработчик с четырьмя аргументами. //! type3 var3)
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1
//! var1, type2 var2, type3 var3)
# define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \ # define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) \
virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
@@ -131,32 +127,32 @@
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare an event method with no arguments. //! \~english Declare event with name \"name\", void name();
//! \~russian Объявляет метод-событие без аргументов. //! \~russian Объявляет событие с именем \"name\", void name();
# define EVENT0(name) void name(); # define EVENT0(name) void name();
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare an event method with one argument. //! \~english Declare event with name \"name\", void name(type0 var0);
//! \~russian Объявляет метод-событие с одним аргументом. //! \~russian Объявляет событие с именем \"name\", void name(type0 var0);
# define EVENT1(name, type0, var0) void name(type0 var0); # define EVENT1(name, type0, var0) void name(type0 var0);
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare an event method with two arguments. //! \~english Declare event with name \"name\", void name(type0 var0, type1 var1);
//! \~russian Объявляет метод-событие с двумя аргументами. //! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1);
# define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1); # define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1);
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare an event method with three arguments. //! \~english Declare event with name \"name\", void name(type0 var0, type1 var1, type2 var2);
//! \~russian Объявляет метод-событие с тремя аргументами. //! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1, type2 var2);
# define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2); # define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2);
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Declare an event method with four arguments. //! \~english Declare event with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
//! \~russian Объявляет метод-событие с четырьмя аргументами. //! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
# define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3); # define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -166,26 +162,10 @@
# define EVENT EVENT0 # define EVENT EVENT0
//! \relatesalso PIObject
//! \~\brief
//! \~english Compatibility helper that raises event "event" on source object "src".
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" у объекта-источника "src".
# define RAISE_EVENT0(src, event) # define RAISE_EVENT0(src, event)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with one argument.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с одним аргументом.
# define RAISE_EVENT1(src, event, v0) # define RAISE_EVENT1(src, event, v0)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with two arguments.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с двумя аргументами.
# define RAISE_EVENT2(src, event, v0, v1) # define RAISE_EVENT2(src, event, v0, v1)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with three arguments.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с тремя аргументами.
# define RAISE_EVENT3(src, event, v0, v1, v2) # define RAISE_EVENT3(src, event, v0, v1, v2)
//! \relatesalso PIObject
//! \~english Compatibility helper that raises event "event" with four arguments.
//! \~russian Совместимый вспомогательный макрос, вызывающий событие "event" с четырьмя аргументами.
# define RAISE_EVENT4(src, event, v0, v1, v2, v3) # define RAISE_EVENT4(src, event, v0, v1, v2, v3)
# define RAISE_EVENT RAISE_EVENT0 # define RAISE_EVENT RAISE_EVENT0
@@ -196,11 +176,11 @@
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\". //! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\".
//! \~\details //! \~\details
//! \~english //! \~english
//! \"handler\" can accept a prefix of \"event\" arguments. //! \"handler\" can handle subset arguments of \"event\".
//! This macro resolves registered methods by name at run time and returns \a PIObject::Connection. //! Returns \a PIObject::Connection
//! \~russian //! \~russian
//! \"handler\" может принимать только начальную часть аргументов \"event\". //! \"handler\" может принимать не все аргументы от \"event\".
//! Макрос ищет зарегистрированные методы по имени во время выполнения и возвращает \a PIObject::Connection. //! Возвращает \a PIObject::Connection
# define CONNECTU(src, event, dest, handler) # define CONNECTU(src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -209,19 +189,17 @@
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\". //! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\".
//! \~\details //! \~\details
//! \~english //! \~english
//! \"handler\" can accept a prefix of \"event\" arguments. //! \"handler\" can handle subset arguments of \"event\".
//! Delivery is queued on the performer object and runs only when that object calls //! Event handler will be executed by \"performer\" when \a PIObject::callQueuedEvents() called.
//! \a PIObject::callQueuedEvents() or \a PIObject::maybeCallQueuedEvents().
//! All argument types should be registered by \a REGISTER_VARIANT() macro, but many //! All argument types should be registered by \a REGISTER_VARIANT() macro, but many
//! common and PIP types already done. //! common and PIP types already done.
//! Returns \a PIObject::Connection. //! Returns \a PIObject::Connection
//! \~russian //! \~russian
//! \"handler\" может принимать только начальную часть аргументов \"event\". //! \"handler\" может принимать не все аргументы от \"event\".
//! Доставка ставится в очередь объекта \"performer\" и выполняется только когда этот объект //! Обработчик будет вызван объектом \"performer\" при вызове \a PIObject::callQueuedEvents().
//! вызывает \a PIObject::callQueuedEvents() или \a PIObject::maybeCallQueuedEvents().
//! Все типы аргументов должны быть зарегистрированы с помощью макроса \a REGISTER_VARIANT(), //! Все типы аргументов должны быть зарегистрированы с помощью макроса \a REGISTER_VARIANT(),
//! однако многие стандартные и PIP типы уже там. //! однако многие стандартные и PIP типы уже там.
//! Возвращает \a PIObject::Connection. //! Возвращает \a PIObject::Connection
# define CONNECTU_QUEUED(src, event, dest, handler, performer) # define CONNECTU_QUEUED(src, event, dest, handler, performer)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -230,13 +208,13 @@
//! \~russian Соединяет событие \"event\" объекта \"src\" к лямбда-функции \"functor\". //! \~russian Соединяет событие \"event\" объекта \"src\" к лямбда-функции \"functor\".
//! \~\details //! \~\details
//! \~english //! \~english
//! \"event\" and \"functor\" must have the same argument list. //! \"event\" and \"functor\" must has equal argument lists.
//! Wrap \"functor\" in () when the lambda expression is complex. //! You should parentness \"functor\" with () if this is complex lambda.
//! Returns \a PIObject::Connection. //! Returns \a PIObject::Connection
//! \~russian //! \~russian
//! \"event\" и \"functor\" должны иметь одинаковый список аргументов. //! \"event\" и \"functor\" должны иметь одинаковые аргументы.
//! В случае сложной лямбда-функции оберните её в (). //! В случае сложной лямбда-функции оберните её ().
//! Возвращает \a PIObject::Connection. //! Возвращает \a PIObject::Connection
# define CONNECTL(src, event, functor) # define CONNECTL(src, event, functor)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -244,11 +222,12 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper that connects an event to a registered handler with compile-time signature spelling. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! \~russian Устаревший совместимый макрос, который соединяет событие с зарегистрированным обработчиком через явное указание сигнатуры. //! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details //! \~\details
//! \~english Prefer \a CONNECTU() for new code. //! Returns PIObject::Connection
//! \~russian Для нового кода предпочитайте \a CONNECTU().
# define CONNECT0(ret, src, event, dest, handler) # define CONNECT0(ret, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -256,8 +235,12 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper for a one-argument registered event or handler. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с одним аргументом. //! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
# define CONNECT1(ret, type0, src, event, dest, handler) # define CONNECT1(ret, type0, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -265,8 +248,12 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper for a two-argument registered event or handler. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с двумя аргументами. //! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
# define CONNECT2(ret, type0, type1, src, event, dest, handler) # define CONNECT2(ret, type0, type1, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -274,8 +261,12 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper for a three-argument registered event or handler. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с тремя аргументами. //! check of event and handler exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
# define CONNECT3(ret, type0, type1, type2, src, event, dest, handler) # define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -283,8 +274,12 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper for a four-argument registered event or handler. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with
//! \~russian Устаревший совместимый макрос для зарегистрированного события или обработчика с четырьмя аргументами. //! check of event and handler exists.
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" с проверкой наличия события и обработчика.
//! \~\details
//! Returns PIObject::Connection
# define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) # define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -302,8 +297,10 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper that skips source method verification. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода. //! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT0(ret, src, event, dest, handler) # define WEAK_CONNECT0(ret, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -311,8 +308,10 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for one argument. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с одним аргументом. //! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT1(ret, type0, src, event, dest, handler) # define WEAK_CONNECT1(ret, type0, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -320,8 +319,10 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for two arguments. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с двумя аргументами. //! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler) # define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -329,8 +330,10 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for three arguments. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с тремя аргументами. //! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler) # define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -338,8 +341,10 @@
//! \~english Use \a CONNECTU() instead //! \~english Use \a CONNECTU() instead
//! \~russian Используйте \a CONNECTU() //! \~russian Используйте \a CONNECTU()
//! \~\brief //! \~\brief
//! \~english Legacy compatibility helper that skips source method verification for four arguments. //! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without
//! \~russian Устаревший совместимый макрос, который пропускает проверку исходного метода для случая с четырьмя аргументами. //! check of event exists
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\" без проверки наличия события и обработчика.
# define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) # define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -354,32 +359,37 @@
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Disconnect a registered event from a registered event handler. //! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian Разрывает соединение зарегистрированного события с зарегистрированным обработчиком. //! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT0(ret, src, event, dest, handler) # define DISCONNECT0(ret, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Disconnect a one-argument registered event from a registered event handler. //! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian Разрывает соединение зарегистрированного события с одним аргументом и зарегистрированного обработчика. //! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT1(ret, type0, src, event, dest, handler) # define DISCONNECT1(ret, type0, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Disconnect a two-argument registered event from a registered event handler. //! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian Разрывает соединение зарегистрированного события с двумя аргументами и зарегистрированного обработчика. //! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT2(ret, type0, type1, src, event, dest, handler) # define DISCONNECT2(ret, type0, type1, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Disconnect a three-argument registered event from a registered event handler. //! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian Разрывает соединение зарегистрированного события с тремя аргументами и зарегистрированного обработчика. //! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler) # define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Disconnect a four-argument registered event from a registered event handler. //! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
//! \~russian Разрывает соединение зарегистрированного события с четырьмя аргументами и зарегистрированного обработчика. //! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта
//! \"dest\"
# define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) # define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
//! \relatesalso PIObject //! \relatesalso PIObject
@@ -391,8 +401,8 @@
//! \relatesalso PIObject //! \relatesalso PIObject
//! \~\brief //! \~\brief
//! \~english Low-level helper that expands to the registered handler entry point. //! \~english Returns pointer to events handler \"handler\"
//! \~russian Низкоуровневый вспомогательный макрос, который разворачивается в точку входа зарегистрированного обработчика. //! \~russian Возвращает указатель на обработчик события \"handler\"
# define HANDLER(handler) # define HANDLER(handler)

View File

@@ -18,18 +18,19 @@
*/ */
#include "piwaitevent_p.h" #include "piwaitevent_p.h"
#ifdef WINDOWS #ifndef MICRO_PIP
# ifdef WINDOWS
// # ifdef _WIN32_WINNT // # ifdef _WIN32_WINNT
// # undef _WIN32_WINNT // # undef _WIN32_WINNT
// # define _WIN32_WINNT 0x0600 // # define _WIN32_WINNT 0x0600
// # endif // # endif
# include <synchapi.h> # include <synchapi.h>
#else # else
# include <errno.h> # include <errno.h>
# include <fcntl.h> # include <fcntl.h>
# include <sys/ioctl.h> # include <sys/ioctl.h>
#endif # endif
#include "pistring.h" # include "pistring.h"
PIWaitEvent::~PIWaitEvent() { PIWaitEvent::~PIWaitEvent() {
@@ -39,12 +40,12 @@ PIWaitEvent::~PIWaitEvent() {
void PIWaitEvent::create() { void PIWaitEvent::create() {
destroy(); destroy();
#ifdef WINDOWS # ifdef WINDOWS
event = CreateEventA(NULL, TRUE, FALSE, NULL); event = CreateEventA(NULL, TRUE, FALSE, NULL);
if (!event) { if (!event) {
piCout << "Error with CreateEventA:" << errorString(); piCout << "Error with CreateEventA:" << errorString();
} }
#else # else
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
piZeroMemory(fds[i]); piZeroMemory(fds[i]);
if (::pipe(pipe_fd) < 0) { if (::pipe(pipe_fd) < 0) {
@@ -53,34 +54,34 @@ void PIWaitEvent::create() {
fcntl(pipe_fd[ReadEnd], F_SETFL, O_NONBLOCK); fcntl(pipe_fd[ReadEnd], F_SETFL, O_NONBLOCK);
fcntl(pipe_fd[WriteEnd], F_SETFL, O_NONBLOCK); fcntl(pipe_fd[WriteEnd], F_SETFL, O_NONBLOCK);
} }
#endif # endif
} }
void PIWaitEvent::destroy() { void PIWaitEvent::destroy() {
#ifdef WINDOWS # ifdef WINDOWS
if (event) { if (event) {
CloseHandle(event); CloseHandle(event);
event = NULL; event = NULL;
} }
#else # else
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
if (pipe_fd[i] != 0) { if (pipe_fd[i] != 0) {
::close(pipe_fd[i]); ::close(pipe_fd[i]);
pipe_fd[i] = 0; pipe_fd[i] = 0;
} }
} }
#endif # endif
} }
bool PIWaitEvent::wait(int fd, CheckRole role) { bool PIWaitEvent::wait(int fd, CheckRole role) {
if (!isCreate()) return false; if (!isCreate()) return false;
#ifdef WINDOWS # ifdef WINDOWS
DWORD ret = WaitForSingleObjectEx(event, INFINITE, TRUE); DWORD ret = WaitForSingleObjectEx(event, INFINITE, TRUE);
ResetEvent(event); ResetEvent(event);
if (ret == WAIT_IO_COMPLETION || ret == WAIT_FAILED) return false; if (ret == WAIT_IO_COMPLETION || ret == WAIT_FAILED) return false;
#else # else
if (fd == -1) return false; if (fd == -1) return false;
int nfds = piMaxi(pipe_fd[ReadEnd], fd) + 1; int nfds = piMaxi(pipe_fd[ReadEnd], fd) + 1;
int fd_index = role; int fd_index = role;
@@ -97,18 +98,18 @@ bool PIWaitEvent::wait(int fd, CheckRole role) {
if (sr == EBADF || sr == EINTR) return false; if (sr == EBADF || sr == EINTR) return false;
if (FD_ISSET(fd, &(fds[CheckExeption]))) return true; if (FD_ISSET(fd, &(fds[CheckExeption]))) return true;
return FD_ISSET(fd, &(fds[fd_index])); return FD_ISSET(fd, &(fds[fd_index]));
#endif # endif
return true; return true;
} }
bool PIWaitEvent::sleep(int us) { bool PIWaitEvent::sleep(int us) {
if (!isCreate()) return false; if (!isCreate()) return false;
#ifdef WINDOWS # ifdef WINDOWS
DWORD ret = WaitForSingleObjectEx(event, us / 1000, TRUE); DWORD ret = WaitForSingleObjectEx(event, us / 1000, TRUE);
ResetEvent(event); ResetEvent(event);
return ret == WAIT_TIMEOUT; return ret == WAIT_TIMEOUT;
#else # else
int nfds = pipe_fd[ReadEnd] + 1; int nfds = pipe_fd[ReadEnd] + 1;
FD_ZERO(&(fds[CheckRead])); FD_ZERO(&(fds[CheckRead]));
FD_SET(pipe_fd[ReadEnd], &(fds[CheckRead])); FD_SET(pipe_fd[ReadEnd], &(fds[CheckRead]));
@@ -120,34 +121,36 @@ bool PIWaitEvent::sleep(int us) {
while (::read(pipe_fd[ReadEnd], &buf, sizeof(buf)) > 0) while (::read(pipe_fd[ReadEnd], &buf, sizeof(buf)) > 0)
; ;
return ret == 0; return ret == 0;
#endif # endif
} }
void PIWaitEvent::interrupt() { void PIWaitEvent::interrupt() {
if (!isCreate()) return; if (!isCreate()) return;
#ifdef WINDOWS # ifdef WINDOWS
SetEvent(event); SetEvent(event);
#else # else
auto _r = ::write(pipe_fd[WriteEnd], "", 1); auto _r = ::write(pipe_fd[WriteEnd], "", 1);
NO_UNUSED(_r); NO_UNUSED(_r);
#endif # endif
} }
bool PIWaitEvent::isCreate() const { bool PIWaitEvent::isCreate() const {
#ifdef WINDOWS # ifdef WINDOWS
return event; return event;
#else # else
return pipe_fd[ReadEnd] != 0; return pipe_fd[ReadEnd] != 0;
#endif # endif
} }
void * PIWaitEvent::getEvent() const { void * PIWaitEvent::getEvent() const {
#ifdef WINDOWS # ifdef WINDOWS
return event; return event;
#else # else
return nullptr; return nullptr;
#endif # endif
} }
#endif // MICRO_PIP

View File

@@ -20,7 +20,9 @@
#ifndef PIWAITEVENT_P_H #ifndef PIWAITEVENT_P_H
#define PIWAITEVENT_P_H #define PIWAITEVENT_P_H
#include "pibase.h" #ifndef MICRO_PIP
# include "pibase.h"
// clang-format off // clang-format off
#ifdef WINDOWS #ifdef WINDOWS
# include <stdarg.h> # include <stdarg.h>
@@ -52,17 +54,18 @@ public:
void * getEvent() const; // WINDOWS only void * getEvent() const; // WINDOWS only
private: private:
#ifdef WINDOWS # ifdef WINDOWS
void * event = nullptr; void * event = nullptr;
#else # else
int pipe_fd[2] = {0, 0}; int pipe_fd[2] = {0, 0};
fd_set fds[3]; fd_set fds[3];
enum { enum {
ReadEnd = 0, ReadEnd = 0,
WriteEnd = 1 WriteEnd = 1
}; };
#endif # endif
}; };
#endif // MICRO_PIP
#endif // PIWAITEVENT_P_H #endif // PIWAITEVENT_P_H

View File

@@ -1,8 +1,9 @@
//! \~\file piauth.h /*! \file piauth.h
//! \~\ingroup Crypt * \ingroup Crypt
//! \~\brief * \~\brief
//! \~english Authentication API * \~english Authentication API
//! \~russian API аутентификации * \~russian API аутентификации
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PIP Authentication API PIP Authentication API
@@ -30,110 +31,72 @@
#include "pip_crypt_export.h" #include "pip_crypt_export.h"
//! \~\ingroup Crypt
//! \~\brief
//! \~english Peer authentication state machine with signed key exchange.
//! \~russian Машина состояний аутентификации узлов с подписанным обменом ключами.
class PIP_CRYPT_EXPORT PIAuth: public PIObject { class PIP_CRYPT_EXPORT PIAuth: public PIObject {
PIOBJECT(PIAuth) PIOBJECT(PIAuth)
public: public:
//! \~english Handshake state.
//! \~russian Состояние рукопожатия.
enum State { enum State {
NotConnected /** \~english No active authentication session. \~russian Активной сессии аутентификации нет. */, NotConnected,
AuthProbe /** \~english Initial probe stage with signed peer introduction. \~russian Начальный этап с подписанным представлением AuthProbe,
узла. */ PassRequest,
, AuthReply,
PassRequest /** \~english Password verification stage for unknown peers. \~russian Этап проверки пароля для неизвестных узлов. */, KeyExchange,
AuthReply /** \~english Reply with client authentication data. \~russian Ответ с данными аутентификации клиента. */, Connected
KeyExchange /** \~english Session key exchange stage. \~russian Этап обмена сеансовым ключом. */,
Connected /** \~english Authentication finished and session key is established. \~russian Аутентификация завершена и сеансовый ключ
установлен. */
}; };
//! Create PIAuth with your digital sign
//! \~english Creates an authentication endpoint from a signing secret key.
//! \~russian Создает конечную точку аутентификации из секретного ключа подписи.
PIAuth(const PIByteArray & sign); PIAuth(const PIByteArray & sign);
//! Set server info data for client authorize event
//! \~english Sets application-defined info exchanged during authorization.
//! \~russian Задает прикладные данные, передаваемые во время авторизации.
void setInfoData(const PIByteArray & info) { custom_info = info; } void setInfoData(const PIByteArray & info) { custom_info = info; }
//! \~english Sets the server password used for password-based peer validation. //! Set server password for check
//! \~russian Устанавливает пароль сервера, используемый для проверки узла по паролю.
void setServerPassword(const PIString & ps); void setServerPassword(const PIString & ps);
//! \~english Replaces the list of trusted peer signing public keys. //! Set list of trusted clients/servers public digital sign keys
//! \~russian Заменяет список доверенных открытых ключей подписи удаленных узлов.
void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) { auth_pkeys = pkeys; } void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) { auth_pkeys = pkeys; }
//! \~english Returns the list of trusted peer signing public keys. //! Get list of trusted clients/servers public digital sign keys
//! \~russian Возвращает список доверенных открытых ключей подписи удаленных узлов.
PIVector<PIByteArray> getAuthorizedPublicKeys() { return auth_pkeys; } PIVector<PIByteArray> getAuthorizedPublicKeys() { return auth_pkeys; }
//! \~english Returns the public signing key derived from the local secret key. //! Get your digital sign public key
//! \~russian Возвращает открытый ключ подписи, полученный из локального секретного ключа.
PIByteArray getSignPublicKey() { return sign_pk; } PIByteArray getSignPublicKey() { return sign_pk; }
//! \~english Stops the current authorization session and clears transient keys. //! Stop authorization
//! \~russian Останавливает текущую сессию авторизации и очищает временные ключи.
void stop(); void stop();
//! \~english Starts the handshake in client mode. //! Start authorization as client
//! \~russian Запускает рукопожатие в режиме клиента.
void startClient(); void startClient();
//! \~english Starts the handshake in server mode and returns the first packet for the client. //! Start authorization as server, return first server message for client
//! \~russian Запускает рукопожатие в режиме сервера и возвращает первый пакет для клиента.
PIByteArray startServer(); PIByteArray startServer();
//! \~english Processes an incoming handshake packet, updates the state and writes the reply back to \a ba. //! Process reseived message both for client and server, return current state and new message writed in "ba"
//! \~russian Обрабатывает входящий пакет рукопожатия, обновляет состояние и записывает ответ обратно в \a ba.
State receive(PIByteArray & ba); State receive(PIByteArray & ba);
//! \~english Returns the session secret key after the state becomes \a Connected. //! Get session secret key, return key only when Connected state
//! \~russian Возвращает сеансовый секретный ключ после перехода в состояние \a Connected.
PIByteArray getSecretKey(); PIByteArray getSecretKey();
//! \~english Generates a signing secret key from \a seed. //! Generate digital sign from seed
//! \~russian Генерирует секретный ключ подписи из \a seed.
static PIByteArray generateSign(const PIByteArray & seed); static PIByteArray generateSign(const PIByteArray & seed);
//! \events //! Disconneted event
//! \{
//! \fn void disconnected(PIString reason)
//! \~english Raised when the handshake is aborted or an established session is dropped.
//! \~russian Вызывается при прерывании рукопожатия или разрыве установленной сессии.
EVENT1(disconnected, PIString, reason); EVENT1(disconnected, PIString, reason);
//! \fn void connected(PIString info) //! Conneted event
//! \~english Raised after the peer reaches state \a Connected.
//! \~russian Вызывается после перехода узла в состояние \a Connected.
EVENT1(connected, PIString, info); EVENT1(connected, PIString, info);
//! \fn void authorize(PIByteArray info, bool * ok) //! Client event for authorize new server
//! \~english Client-side callback used to approve an unknown server and optionally trust its signing key.
//! \~russian Клиентский вызов для подтверждения неизвестного сервера и, при необходимости, доверия его ключу подписи.
EVENT2(authorize, PIByteArray, info, bool *, ok); EVENT2(authorize, PIByteArray, info, bool *, ok);
//! \fn void passwordRequest(PIString * pass) //! Client event for input server password
//! \~english Client-side callback requesting the server password.
//! \~russian Клиентский вызов для запроса пароля сервера.
EVENT1(passwordRequest, PIString *, pass); EVENT1(passwordRequest, PIString *, pass);
//! \fn void passwordCheck(bool result) //! Server event on check client password
//! \~english Server-side callback reporting the result of client password validation.
//! \~russian Серверный вызов, сообщающий результат проверки пароля клиента.
EVENT1(passwordCheck, bool, result); EVENT1(passwordCheck, bool, result);
//! \}
private: private:
enum Role { enum Role {
Client, Client,

View File

@@ -1,8 +1,9 @@
//! \~\ingroup Crypt /*! \file picrypt.h
//! \~\file picrypt.h * \ingroup Crypt
//! \brief * \~\brief
//! \~english Cryptographic using libsodium * \~english Cryptographic using libsodium
//! \~russian Шифрование с помощью libsodium * \~russian Шифрование с помощью libsodium
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Cryptographic class using lib Sodium Cryptographic class using lib Sodium
@@ -28,136 +29,154 @@
#include "pip_crypt_export.h" #include "pip_crypt_export.h"
#include "pistring.h" #include "pistring.h"
//! \~\ingroup Crypt //! \ingroup Crypt
//! \~\brief //! \~\brief
//! \~english Class for encrypting and decrypting data. //! \~english Class for encrypting and decrypting data.
//! \~russian Класс для шифрования и дешифрования данных. //! \~russian Класс для шифрования и дешифрования данных.
//! \details
//! \~english Class providing cryptographic operations using the libsodium library, including encryption, decryption, hashing, and digital
//! signatures. It supports both instance-based and static method-based operations.
//! \~russian Класс, предоставляющий криптографические операции с использованием библиотеки libsodium, включая шифрование, дешифрование,
//! хэширование и цифровые подписи. Поддерживаются операции как на основе экземпляра класса, так и на основе статических методов.
//! \note
//! \~english Requires libsodium library initialization. All methods are thread-safe when using different keys.
//! \~russian Требуется инициализация библиотеки libsodium. Все методы потокобезопасны при использовании различных ключей.
class PIP_CRYPT_EXPORT PICrypt { class PIP_CRYPT_EXPORT PICrypt {
public: public:
//! \~english Constructor that generates a random key. //! \~\brief
//! \~russian Конструктор, генерирующий случайный ключ. //! \~english Constructor that generates a random key
//! \~russian Конструктор, генерирующий случайный ключ
PICrypt(); PICrypt();
//! \~english Destructor.
//! \~russian Деструктор.
~PICrypt(); ~PICrypt();
//! \~english Set key to "key", key size must be a \a sizeKey(). //! \~\brief
//! \~russian Установить ключ "key", размер ключа должен быть равен \a sizeKey(). //! \~english Set key to "key", key size must be a \a sizeKey()
//! \~russian Установить ключ "key", размер ключа должен быть равен \a sizeKey()
bool setKey(const PIByteArray & key); bool setKey(const PIByteArray & key);
//! \~english Generate and set key from keyphrase "secret". //! \~\brief
//! \~russian Генерировать и установить ключ из ключевой фразы "secret". //! \~english Generate and set key from keyphrase "secret"
//! \~russian Генерировать и установить ключ из ключевой фразы "secret"
bool setKey(const PIString & secret); bool setKey(const PIString & secret);
//! \~english Returns current key. //! \~\brief
//! \~russian Возвращает текущий ключ. //! \~english Returns current key
//! \~russian Возвращает текущий ключ
PIByteArray key() { return key_; } PIByteArray key() { return key_; }
//! \~english Encrypt given data "data", result size will be increased by \a sizeCrypt(). //! \~\brief
//! \~russian Зашифровать данные "data", размер результата увеличится на \a sizeCrypt(). //! \~english Encrypt given data "data", result size will be increased by \a sizeCrypt()
//! \~russian Зашифровать данные "data", размер результата увеличится на \a sizeCrypt()
PIByteArray crypt(const PIByteArray & data); PIByteArray crypt(const PIByteArray & data);
//! \~english Decrypt given data "crypt_data". //! \~\brief
//! \~russian Расшифровать данные "crypt_data". //! \~english Decrypt given data "crypt_data"
//! \~russian Расшифровать данные "crypt_data"
PIByteArray decrypt(const PIByteArray & crypt_data, bool * ok = 0); PIByteArray decrypt(const PIByteArray & crypt_data, bool * ok = 0);
//! \~english Encrypt given data "data" with key "key", result size will be increased by \a sizeCrypt(). //! \~\brief
//! \~russian Зашифровать данные "data" ключом "key", размер результата увеличится на \a sizeCrypt(). //! \~english Encrypt given data "data" with key "key", result size will be increased by \a sizeCrypt()
//! \~russian Зашифровать данные "data" ключом "key", размер результата увеличится на \a sizeCrypt()
static PIByteArray crypt(const PIByteArray & data, PIByteArray key); static PIByteArray crypt(const PIByteArray & data, PIByteArray key);
//! \~english Decrypt given data "crypt_data" with key "key". //! \~\brief
//! \~russian Расшифровать данные "crypt_data" ключом "key". //! \~english Decrypt given data "crypt_data" with key "key"
//! \~russian Расшифровать данные "crypt_data" ключом "key"
static PIByteArray decrypt(const PIByteArray & crypt_data, PIByteArray key, bool * ok = 0); static PIByteArray decrypt(const PIByteArray & crypt_data, PIByteArray key, bool * ok = 0);
//! \~english Generate hash from keyphrase "secret", may be used as a key for encryption. //! \~\brief
//! \~russian Генерировать хэш из ключевой фразы "secret", может использоваться в качестве ключа для шифрования. //! \~english Generate hash from keyphrase "secret", may be used as a key for encryption
//! \~russian Генерировать хэш из ключевой фразы "secret", может использоваться в качестве ключа для шифрования
static PIByteArray hash(PIString secret); static PIByteArray hash(PIString secret);
//! \~english Generate hash from bytearray. //! \~\brief
//! \~russian Генерировать хэш из массива байт. //! \~english Generate hash from bytearray
//! \~russian Генерировать хэш из массива байт
static PIByteArray hash(const PIByteArray & data); static PIByteArray hash(const PIByteArray & data);
//! \~english Generate hash from bytearray using provided key. //! \~\brief
//! \~russian Генерировать хэш из массива байт с использованием предоставленного ключа. //! \~english Generate hash from bytearray
//! \~russian Генерировать хэш из массива байт
static PIByteArray hash(const PIByteArray & data, const unsigned char * key, size_t keylen); static PIByteArray hash(const PIByteArray & data, const unsigned char * key, size_t keylen);
//! \~english Returns hash size. //! \~\brief
//! \~russian Возвращает размер хэша. //! \~english Returns hash size
//! \~russian Возвращает размер хэша
static size_t sizeHash(); static size_t sizeHash();
//! \~english Generate short hash from string "s", may be used for hash table. //! \~\brief
//! \~russian Генерировать короткий хэш из строки "s", может использоваться для хэш-таблиц. //! \~english Generate short hash from string "s", may be used for hash table
//! \~russian Генерировать короткий хэш из строки "s", может использоваться для хэш-таблиц
static ullong shorthash(const PIString & s, PIByteArray key = PIByteArray()); static ullong shorthash(const PIString & s, PIByteArray key = PIByteArray());
//! \~english Generate random key. //! \~\brief
//! \~russian Генерировать случайный ключ. //! \~english Generate random key
//! \~russian Генерировать случайный ключ
static PIByteArray generateKey(); static PIByteArray generateKey();
//! \~english Generate random buffer. //! \~\brief
//! \~russian Генерировать случайный буфер. //! \~english Generate random buffer
//! \~russian Генерировать случайный буфер
static PIByteArray generateRandomBuff(int size); static PIByteArray generateRandomBuff(int size);
//! \~english Returns key size. //! \~\brief
//! \~russian Возвращает размер ключа. //! \~english Returns key size
//! \~russian Возвращает размер ключа
static size_t sizeKey(); static size_t sizeKey();
//! \~english Returns size which be added to data size in encryption process. //! \~\brief
//! \~russian Возвращает размер, который будет добавлен к размеру данных в процессе шифрования. //! \~english Returns size which be added to data size in encryption process
//! \~russian Возвращает размер, который будет добавлен к размеру данных в процессе шифрования
static size_t sizeCrypt(); static size_t sizeCrypt();
//! \~english Function randomly generates a secret key and a corresponding public key for digital signature. //! \~\brief
//! \~russian Функция случайным образом генерирует секретный ключ и соответствующий ему открытый ключ для цифровой подписи. //! \~english Function randomly generates a secret key and a corresponding public key for digital signature
//! \~russian Функция случайным образом генерирует секретный ключ и соответствующий ему открытый ключ для цифровой подписи
static bool generateSignKeys(PIByteArray & public_key, PIByteArray & secret_key); static bool generateSignKeys(PIByteArray & public_key, PIByteArray & secret_key);
//! \~english Function generates a secret key from input data and a corresponding public key for digital signature. //! \~\brief
//! \~russian Функция генерирует секретный ключ из входных данных и соответствующий ему открытый ключ для цифровой подписи. //! \~english Function generates a secret key from input data and a corresponding public key for digital signature
//! \~russian Функция генерирует секретный ключ из входных данных и соответствующий ему открытый ключ для цифровой подписи
static bool generateSignKeys(PIByteArray & public_key, PIByteArray & secret_key, const PIByteArray & seed); static bool generateSignKeys(PIByteArray & public_key, PIByteArray & secret_key, const PIByteArray & seed);
//! \~english Function extract sign public key from sing secret key. //! \~\brief
//! \~russian Функция извлекает открытый ключ для подписи из секретного ключа для подписи. //! \~english Function extract sign public key from sing secret key
//! \~russian Функция извлекает открытый ключ для подписи из секретного ключа для подписи
static PIByteArray extractSignPublicKey(const PIByteArray & secret_key); static PIByteArray extractSignPublicKey(const PIByteArray & secret_key);
//! \~english Calculate digital signature for data. //! \~\brief
//! \~russian Вычислить цифровую подпись для данных. //! \~english Calculate digital signature for data
//! \~russian Вычислить цифровую подпись для данных
PIByteArray signMessage(const PIByteArray & data, const PIByteArray & secret_key); PIByteArray signMessage(const PIByteArray & data, const PIByteArray & secret_key);
//! \~english Verify digital signature of signed message. //! \~\brief
//! \~russian Проверить цифровую подпись подписанного сообщения. //! \~english Verify digital signature of signed message
//! \~russian Проверить цифровую подпись подписанного сообщения
bool verifySign(const PIByteArray & data, const PIByteArray & signature, const PIByteArray & public_key); bool verifySign(const PIByteArray & data, const PIByteArray & signature, const PIByteArray & public_key);
//! \~english Function randomly generates a secret key and a corresponding public key for authenticated encryption. //! \~\brief
//! \~english Function randomly generates a secret key and a corresponding public key for authenticated encryption
//! \~russian Функция случайным образом генерирует секретный ключ и соответствующий ему открытый ключ для аутентифицированного //! \~russian Функция случайным образом генерирует секретный ключ и соответствующий ему открытый ключ для аутентифицированного
//! шифрования. //! шифрования
static bool generateKeypair(PIByteArray & public_key, PIByteArray & secret_key); static bool generateKeypair(PIByteArray & public_key, PIByteArray & secret_key);
//! \~english Function generates a secret key from input data and a corresponding public key for authenticated encryption. //! \~\brief
//! \~english Function generates a secret key from input data and a corresponding public key for authenticated encryption
//! \~russian Функция генерирует секретный ключ из входных данных и соответствующий ему открытый ключ для аутентифицированного //! \~russian Функция генерирует секретный ключ из входных данных и соответствующий ему открытый ключ для аутентифицированного
//! шифрования. //! шифрования
static bool generateKeypair(PIByteArray & public_key, PIByteArray & secret_key, const PIByteArray & seed); static bool generateKeypair(PIByteArray & public_key, PIByteArray & secret_key, const PIByteArray & seed);
//! \~english Encrypt given data "data". //! \~\brief
//! \~russian Зашифровать данные "data". //! \~english Encrypt given data "data"
//! \~russian Зашифровать данные "data"
PIByteArray crypt(const PIByteArray & data, const PIByteArray & public_key, const PIByteArray & secret_key); PIByteArray crypt(const PIByteArray & data, const PIByteArray & public_key, const PIByteArray & secret_key);
//! \~english Decrypt given data "crypt_data". //! \~\brief
//! \~russian Расшифровать данные "crypt_data". //! \~english Decrypt given data "crypt_data"
//! \~russian Расшифровать данные "crypt_data"
PIByteArray decrypt(const PIByteArray & crypt_data, const PIByteArray & public_key, const PIByteArray & secret_key, bool * ok = 0); PIByteArray decrypt(const PIByteArray & crypt_data, const PIByteArray & public_key, const PIByteArray & secret_key, bool * ok = 0);
//! \~english Generate password hash from "password". //! \~\brief
//! \~russian Генерировать хэш пароля из "password". //! \~english Generate password hash from "password"
//! \~russian Генерировать хэш пароля из "password"
static PIByteArray passwordHash(PIString password, const PIByteArray & seed); static PIByteArray passwordHash(PIString password, const PIByteArray & seed);
//! \~english Returns libsodium version. //! \~\brief
//! \~russian Возвращает версию libsodium. //! \~english Returns libsodium version
//! \~russian Возвращает версию libsodium
static PIString version(); static PIString version();

View File

@@ -1,13 +1,3 @@
/*! \file picryptmodule.h
* \ingroup Crypt
* \~\brief
* \~english Umbrella header for the Crypt module
* \~russian Зонтичный заголовок модуля Crypt
*
* \~\details
* \~english Includes the public cryptographic and authentication headers.
* \~russian Подключает публичные заголовки шифрования и аутентификации.
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes

View File

@@ -1,8 +1,15 @@
//! \~\file pidigest.h /*! \file pidigest.h
//! \~\ingroup Digest * \ingroup Core
//! \~\brief * \~\brief
//! \~english Digest calculation helpers * \~english Digest algorithms
//! \~russian Вспомогательные методы вычисления хэш-сумм * \~russian Алгоритмы хэш-сумм
*
* \~\details
* \~english
* This file implements several common-usage hash algorithms
* \~russian
* Этот файл реализует несколько распространенных алгоритмов хэширования
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Digest algorithms Digest algorithms
@@ -28,72 +35,47 @@
#include "pibytearray.h" #include "pibytearray.h"
#include "piconstchars.h" #include "piconstchars.h"
//! \class PIDigest
//! \~\ingroup Digest
//! \~\brief
//! \~english One-shot digest API for supported algorithms.
//! \~russian Одношаговый API хэширования для поддерживаемых алгоритмов.
class PIP_EXPORT PIDigest { class PIP_EXPORT PIDigest {
public: public:
//! \~english Supported digest algorithms.
//! \~russian Поддерживаемые алгоритмы хэширования.
enum class Type { enum class Type {
SHA1 /** \~english SHA-1 \~russian SHA-1 */, SHA1,
SHA2_224 /** \~english SHA-2 with 224-bit digest \~russian SHA-2 с дайджестом 224 бита */, SHA2_224,
SHA2_256 /** \~english SHA-2 with 256-bit digest \~russian SHA-2 с дайджестом 256 бит */, SHA2_256,
SHA2_384 /** \~english SHA-2 with 384-bit digest \~russian SHA-2 с дайджестом 384 бита */, SHA2_384,
SHA2_512 /** \~english SHA-2 with 512-bit digest \~russian SHA-2 с дайджестом 512 бит */, SHA2_512,
SHA2_512_224 /** \~english SHA-512/224 \~russian SHA-512/224 */, SHA2_512_224,
SHA2_512_256 /** \~english SHA-512/256 \~russian SHA-512/256 */, SHA2_512_256,
MD2 /** \~english MD2 \~russian MD2 */, MD2,
MD4 /** \~english MD4 \~russian MD4 */, MD4,
MD5 /** \~english MD5 \~russian MD5 */, MD5,
BLAKE2s_128 /** \~english BLAKE2s with 128-bit digest \~russian BLAKE2s с дайджестом 128 бит */, BLAKE2s_128,
BLAKE2s_160 /** \~english BLAKE2s with 160-bit digest \~russian BLAKE2s с дайджестом 160 бит */, BLAKE2s_160,
BLAKE2s_224 /** \~english BLAKE2s with 224-bit digest \~russian BLAKE2s с дайджестом 224 бита */, BLAKE2s_224,
BLAKE2s_256 /** \~english BLAKE2s with 256-bit digest \~russian BLAKE2s с дайджестом 256 бит */, BLAKE2s_256,
BLAKE2b_128 /** \~english BLAKE2b with 128-bit digest \~russian BLAKE2b с дайджестом 128 бит */, BLAKE2b_128,
BLAKE2b_160 /** \~english BLAKE2b with 160-bit digest \~russian BLAKE2b с дайджестом 160 бит */, BLAKE2b_160,
BLAKE2b_224 /** \~english BLAKE2b with 224-bit digest \~russian BLAKE2b с дайджестом 224 бита */, BLAKE2b_224,
BLAKE2b_256 /** \~english BLAKE2b with 256-bit digest \~russian BLAKE2b с дайджестом 256 бит */, BLAKE2b_256,
BLAKE2b_384 /** \~english BLAKE2b with 384-bit digest \~russian BLAKE2b с дайджестом 384 бита */, BLAKE2b_384,
BLAKE2b_512 /** \~english BLAKE2b with 512-bit digest \~russian BLAKE2b с дайджестом 512 бит */, BLAKE2b_512,
SipHash_2_4_64 /** \~english SipHash-2-4 with 64-bit output \~russian SipHash-2-4 с выходом 64 бита */, SipHash_2_4_64,
SipHash_2_4_128 /** \~english SipHash-2-4 with 128-bit output \~russian SipHash-2-4 с выходом 128 бит */, SipHash_2_4_128,
HalfSipHash_2_4_32 /** \~english HalfSipHash-2-4 with 32-bit output \~russian HalfSipHash-2-4 с выходом 32 бита */, HalfSipHash_2_4_32,
HalfSipHash_2_4_64 /** \~english HalfSipHash-2-4 with 64-bit output \~russian HalfSipHash-2-4 с выходом 64 бита */, HalfSipHash_2_4_64,
Count /** \~english Number of supported algorithms \~russian Количество поддерживаемых алгоритмов */ Count,
}; };
//! \~english Returns digest length in bytes for algorithm "type".
//! \~russian Возвращает длину дайджеста в байтах для алгоритма "type".
static int hashLength(Type type); static int hashLength(Type type);
//! \~english Returns internal block length in bytes for algorithm "type".
//! \~russian Возвращает внутреннюю длину блока в байтах для алгоритма "type".
static int blockLength(Type type); static int blockLength(Type type);
//! \~english Returns stable algorithm name for "type".
//! \~russian Возвращает стабильное имя алгоритма для "type".
static PIConstChars typeName(Type type); static PIConstChars typeName(Type type);
//! \~english Calculates digest of message "msg" with algorithm "type".
//! \~russian Вычисляет хэш сообщения "msg" алгоритмом "type".
static PIByteArray calculate(const PIByteArray & msg, Type type); static PIByteArray calculate(const PIByteArray & msg, Type type);
//! \~english Calculates keyed digest for algorithms with native key support, otherwise returns empty array.
//! \~russian Вычисляет keyed digest для алгоритмов с нативной поддержкой ключа, иначе возвращает пустой массив.
static PIByteArray calculateWithKey(const PIByteArray & msg, const PIByteArray & key, Type type); static PIByteArray calculateWithKey(const PIByteArray & msg, const PIByteArray & key, Type type);
//! \~english Calculates HMAC for message "msg" and key "key" with algorithm "type".
//! \~russian Вычисляет HMAC для сообщения "msg" и ключа "key" алгоритмом "type".
static PIByteArray HMAC(const PIByteArray & msg, const PIByteArray & key, PIDigest::Type type); static PIByteArray HMAC(const PIByteArray & msg, const PIByteArray & key, PIDigest::Type type);
}; };

View File

@@ -1,8 +1,9 @@
//! \~\ingroup Geo /*! \file piellipsoidmodel.h
//! \~\file piellipsoidmodel.h * \ingroup Geo
//! \brief * \~\brief
//! \~english Geographical ellipsoid Earth models * \~english Geographical ellipsoid Earth models
//! \~russian Географическая эллипсоидная модель Земли * \~russian Географическая эллипсоидная модель Земли
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Contains geo ellipsoid models Contains geo ellipsoid models
@@ -28,60 +29,21 @@
#include "pimathbase.h" #include "pimathbase.h"
//! \~\ingroup Geo
//! \~\brief
//! \~english Reference ellipsoid parameters used by geographic calculations.
//! \~russian Параметры опорного эллипсоида для географических вычислений.
//! \details
//! \~english This module provides Earth ellipsoid models used in geodesy and navigation systems. It includes standard models like WGS84,
//! PZ90, GPS, and Krasovskiy.
//! \~russian Этот модуль предоставляет модели эллипсоидов Земли, используемые в геодезии и навигационных системах. Он включает стандартные
//! модели WGS84, ПЗ-90, GPS и Красовского.
class PIP_EXPORT PIEllipsoidModel { class PIP_EXPORT PIEllipsoidModel {
public: public:
//! \~english Constructs an empty ellipsoid description.
//! \~russian Создает пустое описание эллипсоида.
PIEllipsoidModel(); PIEllipsoidModel();
double eccSquared() const { return eccentricity * eccentricity; } // eccentricity squared
//! \~english Returns squared eccentricity.
//! \~russian Возвращает квадрат эксцентриситета.
double eccSquared() const { return eccentricity * eccentricity; }
//! \~english Returns semi-minor axis in meters.
//! \~russian Возвращает малую полуось в метрах.
double b() const { return a * sqrt(1 - eccSquared()); } double b() const { return a * sqrt(1 - eccSquared()); }
//! \~english Returns the WGS84 reference ellipsoid.
//! \~russian Возвращает опорный эллипсоид WGS84.
static PIEllipsoidModel WGS84Ellipsoid(); static PIEllipsoidModel WGS84Ellipsoid();
//! \~english Returns the PZ-90 reference ellipsoid.
//! \~russian Возвращает опорный эллипсоид ПЗ-90.
static PIEllipsoidModel PZ90Ellipsoid(); static PIEllipsoidModel PZ90Ellipsoid();
//! \~english Returns the GPS ellipsoid variant used by this module.
//! \~russian Возвращает вариант GPS-эллипсоида, используемый в этом модуле.
static PIEllipsoidModel GPSEllipsoid(); static PIEllipsoidModel GPSEllipsoid();
//! \~english Returns the Krasovskiy reference ellipsoid.
//! \~russian Возвращает опорный эллипсоид Красовского.
static PIEllipsoidModel KrasovskiyEllipsoid(); static PIEllipsoidModel KrasovskiyEllipsoid();
//! \~english Semi-major axis in meters. double a; /// Major axis of Earth in meters
//! \~russian Большая полуось в метрах. double flattening; /// Flattening (ellipsoid parameter)
double a; double eccentricity; /// Eccentricity (ellipsoid parameter)
double angVelocity; /// Angular velocity of Earth in radians/sec
//! \~english Flattening coefficient.
//! \~russian Коэффициент сжатия.
double flattening;
//! \~english First eccentricity.
//! \~russian Первый эксцентриситет.
double eccentricity;
//! \~english Angular velocity in radians per second.
//! \~russian Угловая скорость в радианах в секунду.
double angVelocity;
}; };

View File

@@ -1,13 +1,3 @@
/*! \file pigeomodule.h
* \ingroup Geo
* \~\brief
* \~english Entry header for the Geo module
* \~russian Входной заголовок модуля Geo
*
* \~\details
* \~english Includes the public geographic position header.
* \~russian Подключает публичный заголовок географической позиции.
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -28,8 +18,8 @@
*/ */
//! \defgroup Geo Geo //! \defgroup Geo Geo
//! \~\brief //! \~\brief
//! \~english Geographical position and Earth models module. //! \~english Geographical position and Earth models
//! \~russian Модуль географической позиции и моделей Земли. //! \~russian Географическая позиция и модели Земли
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module_Geo Building with CMake //! \~english \section cmake_module_Geo Building with CMake
@@ -44,17 +34,19 @@
//! \~russian \par Общее //! \~russian \par Общее
//! //!
//! \~english //! \~english
//! The module provides Earth ellipsoid models, geographic position storage and //! These files provides geographical position, several Earth models and converting
//! conversions between supported coordinate systems. //! from one model to another.
//! //!
//! \~russian //! \~russian
//! Модуль предоставляет модели земного эллипсоида, хранение географической //! Эти файлы обеспечивают географическую позицию, несколько моделей Земли и
//! позиции и преобразования между поддерживаемыми системами координат. //! преобразования из одной модели в другую.
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru; //! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian //! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru; //! Андрей Бычков work.a.b@yandex.ru;
//! //!

View File

@@ -1,8 +1,9 @@
//! \~\ingroup Geo /*! \file pigeoposition.h
//! \~\file pigeoposition.h * \ingroup Geo
//! \brief * \~\brief
//! \~english Class for geo position storage and conversions * \~english Class for geo position storage and conversions
//! \~russian Класс для хранения географической позиции и преобразований * \~russian Класс для хранения географической позиции и преобразований
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for geo position storage and conversions Class for geo position storage and conversions
@@ -28,285 +29,147 @@
#include "piellipsoidmodel.h" #include "piellipsoidmodel.h"
#include "pimathvector.h" #include "pimathvector.h"
//! \~\ingroup Geo
//! \~\brief
//! \~english Geographic position represented in one of several coordinate systems.
//! \~russian Географическая позиция, представленная в одной из нескольких систем координат.
//! \details
//! \~english This class provides functionality for storing and converting between different coordinate systems including geodetic,
//! geocentric, Cartesian, and spherical coordinates. It supports various ellipsoid models for Earth representation.
//! \~russian Этот класс предоставляет функциональность для хранения и преобразования между различными системами координат, включая
//! геодезическую, геоцентрическую, декартову и сферическую. Он поддерживает различные модели эллипсоида для представления Земли.
class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d { class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d {
public: public:
//! \~english Coordinate system used by stored components.
//! \~russian Система координат, используемая для хранимых компонент.
enum CoordinateSystem { enum CoordinateSystem {
Unknown = 0 /** \~english Unknown coordinate system \~russian Неизвестная система координат */, Unknown = 0, /// Unknown coordinate system
Geodetic /** \~english Geodetic latitude, longitude and height above the ellipsoid \~russian Геодезическая широта, долгота и высота Geodetic, /// Geodetic latitude, longitude, and height above ellipsoid
над эллипсоидом */ Geocentric, /// Geocentric (regular spherical coordinates)
, Cartesian, /// Cartesian (Earth-centered, Earth-fixed)
Geocentric /** \~english Geocentric latitude, longitude and radius \~russian Геоцентрическая широта, долгота и радиус */, Spherical /// Spherical coordinates (theta,phi,radius)
Cartesian /** \~english Earth-centered Earth-fixed Cartesian coordinates \~russian Декартовы координаты ECEF */,
Spherical /** \~english Spherical coordinates as theta, phi and radius \~russian Сферические координаты: тета, фи и радиус */
}; };
//! \~english One centimeter tolerance in meters. static const double one_cm_tolerance; /// One centimeter tolerance.
//! \~russian Допуск в один сантиметр в метрах. static const double one_mm_tolerance; /// One millimeter tolerance.
static const double one_cm_tolerance; static const double one_um_tolerance; /// One micron tolerance.
static double position_tolerance; /// Default tolerance (default 1mm)
//! \~english One millimeter tolerance in meters.
//! \~russian Допуск в один миллиметр в метрах.
static const double one_mm_tolerance;
//! \~english One micron tolerance in meters.
//! \~russian Допуск в один микрон в метрах.
static const double one_um_tolerance;
//! \~english Default comparison and singularity tolerance in meters.
//! \~russian Допуск по умолчанию для сравнений и вырожденных случаев, в метрах.
static double position_tolerance;
//! \~english Sets the default tolerance in meters.
//! \~russian Устанавливает допуск по умолчанию в метрах.
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 Returns the default tolerance in meters.
//! \~russian Возвращает допуск по умолчанию в метрах.
static double getPositionTolerance() { return position_tolerance; } static double getPositionTolerance() { return position_tolerance; }
//! \~english Constructs the zero position in Cartesian coordinates.
//! \~russian Создает нулевую позицию в декартовой системе координат.
PIGeoPosition(); PIGeoPosition();
//! \~english Constructs a position from three components in the selected coordinate system.
//! \~russian Создает позицию из трех компонент в выбранной системе координат.
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 Constructs a position from an existing 3D vector.
//! \~russian Создает позицию из существующего трехмерного вектора.
PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Converts the stored value to another coordinate system in place.
//! \~russian Преобразует хранимое значение в другую систему координат на месте.
PIGeoPosition & transformTo(CoordinateSystem sys); PIGeoPosition & transformTo(CoordinateSystem sys);
//! \~english Converts this position to geodetic coordinates.
//! \~russian Преобразует позицию в геодезические координаты.
PIGeoPosition & asGeodetic() { PIGeoPosition & asGeodetic() {
transformTo(Geodetic); transformTo(Geodetic);
return *this; return *this;
} } /// Convert to geodetic coordinate
//! \~english Switches to another ellipsoid and converts to geodetic coordinates.
//! \~russian Переключает эллипсоид и преобразует позицию в геодезические координаты.
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 Converts this position to Cartesian ECEF coordinates.
//! \~russian Преобразует позицию в декартовы координаты ECEF.
PIGeoPosition & asECEF() { PIGeoPosition & asECEF() {
transformTo(Cartesian); transformTo(Cartesian);
return *this; return *this;
} } /// Convert to cartesian coordinates
//! \~english Returns the X component in Cartesian ECEF coordinates.
//! \~russian Возвращает компоненту X в декартовых координатах ECEF.
double x() const; double x() const;
//! \~english Returns the Y component in Cartesian ECEF coordinates.
//! \~russian Возвращает компоненту Y в декартовых координатах ECEF.
double y() const; double y() const;
//! \~english Returns the Z component in Cartesian ECEF coordinates.
//! \~russian Возвращает компоненту Z в декартовых координатах ECEF.
double z() const; double z() const;
//! \~english Returns geodetic latitude in degrees.
//! \~russian Возвращает геодезическую широту в градусах.
double latitudeGeodetic() const; double latitudeGeodetic() const;
//! \~english Returns geocentric latitude in degrees.
//! \~russian Возвращает геоцентрическую широту в градусах.
double latitudeGeocentric() const; double latitudeGeocentric() const;
//! \~english Returns longitude in degrees.
//! \~russian Возвращает долготу в градусах.
double longitude() const; double longitude() const;
//! \~english Returns spherical theta angle in degrees (angle from Z axis).
//! \~russian Возвращает сферический угол тета в градусах (угол от оси Z).
double theta() const; double theta() const;
//! \~english Returns spherical phi angle in degrees (angle in XY plane from X axis).
//! \~russian Возвращает сферический угол фи в градусах (угол в плоскости XY от оси X).
double phi() const; double phi() const;
//! \~english Returns radius in meters for spherical or geocentric form (distance from Earth center).
//! \~russian Возвращает радиус в метрах для сферического или геоцентрического представления (расстояние от центра Земли).
double radius() const; double radius() const;
//! \~english Returns geodetic height above the ellipsoid in meters.
//! \~russian Возвращает геодезическую высоту над эллипсоидом в метрах.
double height() const; double height() const;
//! \~english Sets the ellipsoid model used by geodetic conversions. /// Set the ellipsoid values for this PIGeoPosition given a ellipsoid.
//! \~russian Устанавливает модель эллипсоида, используемую в геодезических преобразованиях.
void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; } void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; }
//! \~english Sets geodetic latitude, longitude and height in degrees/meters. /// Set the \a PIGeoPosition given geodetic coordinates in degrees. \a CoordinateSystem is set to \a Geodetic.
//! \~russian Устанавливает геодезические широту, долготу и высоту в градусах и метрах.
PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Sets geocentric latitude, longitude and radius in degrees/meters. /// Set the \a PIGeoPosition given geocentric coordinates in degrees. \a CoordinateSystem is set to \a Geocentric
//! \~russian Устанавливает геоцентрические широту, долготу и радиус в градусах и метрах.
PIGeoPosition & setGeocentric(double lat, double lon, double rad); PIGeoPosition & setGeocentric(double lat, double lon, double rad);
//! \~english Sets spherical theta, phi and radius in degrees/meters. /// Set the \a PIGeoPosition given spherical coordinates in degrees. \a CoordinateSystem is set to \a Spherical
//! \~russian Устанавливает сферические тета, фи и радиус в градусах и метрах.
PIGeoPosition & setSpherical(double theta, double phi, double rad); PIGeoPosition & setSpherical(double theta, double phi, double rad);
//! \~english Sets Cartesian ECEF coordinates in meters. /// Set the \a PIGeoPosition given ECEF coordinates in meeters. \a CoordinateSystem is set to \a Cartesian.
//! \~russian Устанавливает декартовы координаты ECEF в метрах.
PIGeoPosition & setECEF(double x, double y, double z); PIGeoPosition & setECEF(double x, double y, double z);
//! \~english Converts spherical coordinates to Cartesian ECEF coordinates. /// Fundamental conversion from spherical to cartesian coordinates.
//! \~russian Преобразует сферические координаты в декартовы координаты ECEF.
static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz); static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz);
//! \~english Converts Cartesian ECEF coordinates to spherical coordinates. /// Fundamental routine to convert cartesian to spherical coordinates.
//! \~russian Преобразует декартовы координаты ECEF в сферические координаты.
static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr); static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr);
//! \~english Converts Cartesian ECEF coordinates to geodetic coordinates. /// Fundamental routine to convert ECEF (cartesian) to geodetic coordinates,
//! \~russian Преобразует декартовы координаты ECEF в геодезические координаты.
static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz, static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz,
PIMathVectorT3d & llh, PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Converts geodetic coordinates to Cartesian ECEF coordinates. /// Fundamental routine to convert geodetic to ECEF (cartesian) coordinates,
//! \~russian Преобразует геодезические координаты в декартовы координаты ECEF.
static void convertGeodeticToCartesian(const PIMathVectorT3d & llh, static void convertGeodeticToCartesian(const PIMathVectorT3d & llh,
PIMathVectorT3d & xyz, PIMathVectorT3d & xyz,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Converts Cartesian ECEF coordinates to geocentric coordinates. /// Fundamental routine to convert cartesian (ECEF) to geocentric
//! \~russian Преобразует декартовы координаты ECEF в геоцентрические координаты.
static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr); static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr);
//! \~english Converts geocentric coordinates to Cartesian ECEF coordinates. /// Fundamental routine to convert geocentric to cartesian (ECEF)
//! \~russian Преобразует геоцентрические координаты в декартовы координаты ECEF.
static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz); static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz);
//! \~english Converts geocentric coordinates to geodetic coordinates. /// Fundamental routine to convert geocentric to geodetic
//! \~russian Преобразует геоцентрические координаты в геодезические координаты.
static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr, static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr,
PIMathVectorT3d & llh, PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Converts geodetic coordinates to geocentric coordinates. /// Fundamental routine to convert geodetic to geocentric
//! \~russian Преобразует геодезические координаты в геоцентрические координаты.
static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh, static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh,
PIMathVectorT3d & llr, PIMathVectorT3d & llr,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Returns ellipsoid radius at the given geodetic latitude. /// Compute the radius of the ellipsoidal Earth, given the geodetic latitude.
//! \~russian Возвращает радиус эллипсоида на заданной геодезической широте.
static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Returns ellipsoid radius for this 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);
} }
//! \~english Returns straight-line range between two positions in meters. /// Compute the range in meters between two PIGeoPositions.
//! \~russian Возвращает прямую дальность между двумя позициями в метрах.
static double range(const PIGeoPosition & a, const PIGeoPosition & b); static double range(const PIGeoPosition & a, const PIGeoPosition & b);
//! \~english Returns straight-line range to another position in meters.
//! \~russian Возвращает прямую дальность до другой позиции в метрах.
double range(const PIGeoPosition & p) const { return range((*this), p); } double range(const PIGeoPosition & p) const { return range((*this), p); }
//! \~english Computes elevation to another position. /// Computes the elevation of the input (p) position as seen from this PIGeoPosition.
//! \~russian Вычисляет угол места до другой позиции.
double elevation(const PIGeoPosition & p) const; double elevation(const PIGeoPosition & p) const;
//! \~english Computes elevation using local geodetic vertical. /// Computes the elevation of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system.
//! \~russian Вычисляет угол места относительно локальной геодезической вертикали.
double elevationGeodetic(const PIGeoPosition & p) const; double elevationGeodetic(const PIGeoPosition & p) const;
//! \~english Computes azimuth to another position. /// Computes the azimuth of the input (p) position as seen from this PIGeoPosition.
//! \~russian Вычисляет азимут на другую позицию.
double azimuth(const PIGeoPosition & p) const; double azimuth(const PIGeoPosition & p) const;
//! \~english Computes azimuth using local geodetic north-east axes. /// Computes the azimuth of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system.
//! \~russian Вычисляет азимут по локальным геодезическим осям север-восток.
double azimuthGeodetic(const PIGeoPosition & p) const; double azimuthGeodetic(const PIGeoPosition & p) const;
//! \~english Returns meridian radius of curvature for this position. /// Computes the radius of curvature of the meridian (Rm) corresponding to this PIGeoPosition.
//! \~russian Возвращает радиус кривизны меридиана для этой позиции.
double getCurvMeridian() const; double getCurvMeridian() const;
//! \~english Returns prime-vertical radius of curvature for this position. /// Computes the radius of curvature in the prime vertical (Rn) corresponding to this PIGeoPosition.
//! \~russian Возвращает радиус кривизны первого вертикала для этой позиции.
double getCurvPrimeVertical() const; double getCurvPrimeVertical() const;
//! \~english Returns the underlying three-component vector in the current system. /// Returns as PIMathVectorT3d
//! \~russian Возвращает базовый трехкомпонентный вектор в текущей системе.
const PIMathVectorT3d & vector() const { return *this; } const PIMathVectorT3d & vector() const { return *this; }
//! \~english Assigns coordinates from a plain 3D vector without changing metadata.
//! \~russian Присваивает координаты из обычного 3D-вектора без изменения метаданных.
PIGeoPosition & operator=(const PIMathVectorT3d & v); PIGeoPosition & operator=(const PIMathVectorT3d & v);
//! \~english Subtracts another position after converting both operands to Cartesian coordinates.
//! \~russian Вычитает другую позицию после перевода обоих операндов в декартовы координаты.
PIGeoPosition & operator-=(const PIGeoPosition & right); PIGeoPosition & operator-=(const PIGeoPosition & right);
//! \~english Adds another position after converting both operands to Cartesian coordinates.
//! \~russian Складывает другую позицию после перевода обоих операндов в декартовы координаты.
PIGeoPosition & operator+=(const PIGeoPosition & right); PIGeoPosition & operator+=(const PIGeoPosition & right);
//! \~english Returns Cartesian difference of two positions.
//! \~russian Возвращает декартову разность двух позиций.
friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right); friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Returns Cartesian sum of two positions.
//! \~russian Возвращает декартову сумму двух позиций.
friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right); friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Scales a position by a floating-point factor.
//! \~russian Масштабирует позицию вещественным коэффициентом.
friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right); friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right);
//! \~english Scales a position by a floating-point factor.
//! \~russian Масштабирует позицию вещественным коэффициентом.
friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale); friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale);
//! \~english Scales a position by an integer factor.
//! \~russian Масштабирует позицию целочисленным коэффициентом.
friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right); friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right);
//! \~english Scales a position by an integer factor.
//! \~russian Масштабирует позицию целочисленным коэффициентом.
friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale); friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale);
//! \~english Compares two positions using the configured tolerance and ellipsoid model.
//! \~russian Сравнивает две позиции с учетом настроенного допуска и модели эллипсоида.
bool operator==(const PIGeoPosition & right) const; bool operator==(const PIGeoPosition & right) const;
//! \~english Returns true when positions are not equal.
//! \~russian Возвращает true, если позиции не равны.
bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); } bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); }
@@ -318,11 +181,6 @@ private:
}; };
//! \~english Subtraction
//! \~russian Вычитание
//! \details
//! \~english Subtracts two positions by converting them to Cartesian coordinates and performing element-wise 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);
@@ -330,12 +188,6 @@ inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition &
l -= r; l -= r;
return l; return l;
} }
//! \~english Addition
//! \~russian Сложение
//! \details
//! \~english Adds two positions by converting them to Cartesian coordinates and performing element-wise 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);
@@ -343,40 +195,17 @@ inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition &
l += r; l += r;
return l; return l;
} }
//! \~english Scalar multiplication (double)
//! \~russian Умножение на скаляр (double)
//! \details
//! \~english Multiplies a position by a double scalar value.
//! \~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)
//! \details
//! \~english Multiplies a position by a double scalar value.
//! \~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)
//! \details
//! \~english Multiplies a position by an integer scalar value.
//! \~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)
//! \details
//! \~english Multiplies a position by an integer scalar value.
//! \~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,27 +1,3 @@
//! \~\file pihttpclient.h
//! \~\ingroup HTTPClient
//! \~\brief
//! \~english Public HTTP client request API
//! \~russian Публичный API HTTP-клиента для выполнения запросов
/*
PIP - Platform Independent Primitives
Public HTTP client request API
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef pihttpclient_h #ifndef pihttpclient_h
#define pihttpclient_h #define pihttpclient_h
@@ -37,65 +13,53 @@ public:
}; };
//! \~\ingroup HTTPClient //! \~english Main HTTP client class for performing requests with event callbacks.
//! \~\brief //! \~russian Основной класс HTTP-клиента для выполнения запросов с callback-ми событий.
//! \~english Asynchronous HTTP client request with completion callbacks.
//! \~russian Асинхронный HTTP-запрос клиента с callback-ами завершения.
class PIP_HTTP_CLIENT_EXPORT PIHTTPClient: private PIHTTPClientBase { class PIP_HTTP_CLIENT_EXPORT PIHTTPClient: private PIHTTPClientBase {
friend class PIHTTPClientBase; friend class PIHTTPClientBase;
friend class CurlThreadPool; friend class CurlThreadPool;
public: public:
//! \~english Creates a request object for the specified URL, method and initial message data. //! \~english Creates a new HTTP request instance with the specified URL, method and message.
//! \~russian Создает объект запроса для указанного URL, метода и начальных данных сообщения. //! \~russian Создает новый экземпляр HTTP-запроса с указанным URL, методом и сообщением.
static PIHTTPClient * create(const PIString & url, PIHTTP::Method method = PIHTTP::Method::Get, const PIHTTP::MessageConst & req = {}); static PIHTTPClient * create(const PIString & url, PIHTTP::Method method = PIHTTP::Method::Get, const PIHTTP::MessageConst & req = {});
//! \~english Sets a callback for successful request completion (no parameters).
//! \~english Sets a callback invoked when the transfer completes successfully. //! \~russian Устанавливает callback для успешного завершения запроса (без параметров).
//! \~russian Устанавливает callback, вызываемый при успешном завершении передачи.
PIHTTPClient * onFinish(std::function<void()> f); PIHTTPClient * onFinish(std::function<void()> f);
//! \~english Sets a callback invoked when the transfer completes successfully and provides the parsed reply. //! \~english Sets a callback for successful request completion (with response).
//! \~russian Устанавливает callback, вызываемый при успешном завершении передачи, и передает разобранный ответ. //! \~russian Устанавливает callback для успешного завершения запроса (с ответом).
PIHTTPClient * onFinish(std::function<void(const PIHTTP::MessageConst &)> f); PIHTTPClient * onFinish(std::function<void(const PIHTTP::MessageConst &)> f);
//! \~english Sets a callback invoked when the transfer fails with a transport-level error. //! \~english Sets a callback for request errors (no parameters).
//! \~russian Устанавливает callback, вызываемый при ошибке передачи на транспортном уровне. //! \~russian Устанавливает callback для ошибок запроса (без параметров).
PIHTTPClient * onError(std::function<void()> f); PIHTTPClient * onError(std::function<void()> f);
//! \~english Sets a callback invoked when the transfer fails with a transport-level error and provides the partial reply state. //! \~english Sets a callback for request errors (with error response).
//! \~russian Устанавливает callback, вызываемый при ошибке передачи на транспортном уровне, и передает текущее состояние ответа. //! \~russian Устанавливает callback для ошибок запроса (с ответом об ошибке).
PIHTTPClient * onError(std::function<void(const PIHTTP::MessageConst &)> f); PIHTTPClient * onError(std::function<void(const PIHTTP::MessageConst &)> f);
//! \~english Sets a callback invoked when the request is aborted. //! \~english Sets a callback for request abortion (no parameters).
//! \~russian Устанавливает callback, вызываемый при прерывании запроса. //! \~russian Устанавливает callback для прерывания запроса (без параметров).
PIHTTPClient * onAbort(std::function<void()> f); PIHTTPClient * onAbort(std::function<void()> f);
//! \~english Sets a callback invoked when the request is aborted and provides the current reply state. //! \~english Sets a callback for request abortion (with abort response).
//! \~russian Устанавливает callback, вызываемый при прерывании запроса, и передает текущее состояние ответа. //! \~russian Устанавливает callback для прерывания запроса (с ответом о прерывании).
PIHTTPClient * onAbort(std::function<void(const PIHTTP::MessageConst &)> f); PIHTTPClient * onAbort(std::function<void(const PIHTTP::MessageConst &)> f);
//! \~english Starts the HTTP request execution.
//! \~english Disables SSL verification checks for this request. Call \b before \a start(). //! \~russian Начинает выполнение HTTP-запроса.
//! \~russian Отключает проверки SSL для этого запроса. Вызывайте \b до \a start().
PIHTTPClient * ignoreSSLErrors();
//! \~english Queues the request for asynchronous execution.
//! \~russian Ставит запрос в очередь на асинхронное выполнение.
void start(); void start();
//! \~english Requests cancellation of the running transfer. //! \~english Aborts the current HTTP request.
//! \~russian Запрашивает отмену выполняющейся передачи. //! \~russian Прерывает текущий HTTP-запрос.
void abort(); void abort();
//! \~english Returns the last error message.
//! \~english Returns the last transport error message. //! \~russian Возвращает последнее сообщение об ошибке.
//! \~russian Возвращает последнее сообщение об ошибке транспортного уровня.
PIString lastError() const { return last_error; } PIString lastError() const { return last_error; }
private: private:
NO_COPY_CLASS(PIHTTPClient) NO_COPY_CLASS(PIHTTPClient)
PIHTTPClient(); PIHTTPClient();
@@ -119,7 +83,6 @@ private:
PIByteArray buffer_out; PIByteArray buffer_out;
PIHTTP::MessageMutable request, reply; PIHTTP::MessageMutable request, reply;
std::atomic_bool is_cancel = {false}; std::atomic_bool is_cancel = {false};
bool ignore_ssl_errors = false;
ssize_t read_pos = 0; ssize_t read_pos = 0;
std::function<void(const PIHTTP::MessageConst &)> on_finish, on_error, on_abort; std::function<void(const PIHTTP::MessageConst &)> on_finish, on_error, on_abort;
}; };

View File

@@ -1,19 +1,7 @@
//! \~\file pihttpclientmodule.h
//! \~\ingroup HTTPClient
//! \~\brief
//! \~english HTTP client module includes for PIP library
//! \~russian Модуль инклюдов HTTP клиента для библиотеки PIP
//! \details
//! \~english
//! This file includes all HTTP client module headers providing async HTTP client functionality
//! using libcurl for performing HTTP requests with callbacks.
//! \~russian
//! Этот файл включает все заголовки модуля HTTP клиента, предоставляющие функциональность
//! асинхронного HTTP клиента с использованием libcurl.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
Ivan Pelipenko peri4ko@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
@@ -28,25 +16,28 @@
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/>.
*/ */
//! \defgroup HTTPClient HTTPClient //! \defgroup HTTPServer HTTPServer
//! \~\brief //! \~\brief
//! \~english HTTP client //! \~english HTTP client
//! \~russian HTTP клиент //! \~russian HTTP сервер
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module_HTTPClient Building with CMake //! \~english \section cmake_module_HTTPServer Building with CMake
//! \~russian \section cmake_module_HTTPClient Сборка с использованием CMake //! \~russian \section cmake_module_HTTPServer Сборка с использованием CMake
//! //!
//! \~\code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::HTTPClient) //! target_link_libraries([target] PIP::HTTPServer)
//! \endcode //! \endcode
//! //!
//! \~\details //! \~english \par Common
//! \~russian \par Общее
//!
//! \~english //! \~english
//! These files provide HTTP client functionality using libcurl for performing asynchronous HTTP requests with callbacks. //! These files provides HTTP server based on libmicrohttpd
//!
//! \~russian //! \~russian
//! Эти файлы предоставляют функциональность HTTP клиента с использованием libcurl для выполнения асинхронных HTTP запросов с callback-ми. //! Эти файлы обеспечивают HTTP сервер, основанный на libmicrohttpd
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -1,41 +1,9 @@
//! \~\ingroup 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
//! заголовков.
/*
PIP - Platform Independent Primitives
HTTP constants and enumerations
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef pihttpconstants_h #ifndef pihttpconstants_h
#define pihttpconstants_h #define pihttpconstants_h
//! \~english Namespace with shared HTTP constants and vocabulary.
//! \~russian Пространство имен с общими HTTP-константами и базовой терминологией.
namespace PIHTTP { namespace PIHTTP {
//! \~english HTTP request method.
//! \~russian HTTP-метод запроса.
enum class Method { enum class Method {
Unknown, Unknown,
Get, Get,
@@ -46,11 +14,9 @@ enum class Method {
Connect, Connect,
Options, Options,
Trace, Trace,
Patch, Patch
}; };
//! \~english HTTP status code.
//! \~russian HTTP-код статуса.
enum class Code { enum class Code {
Unknown = -1, Unknown = -1,
Continue = 100, Continue = 100,
@@ -124,14 +90,7 @@ enum class Code {
NetworkAuthenticationRequired = 511, NetworkAuthenticationRequired = 511,
}; };
//! \~english Namespace with shared HTTP header field name literals.
//! \~russian Пространство имен с общими строковыми литералами имен HTTP-заголовков.
//!
//! \~english Constant names follow the header field names used on the wire.
//! \~russian Имена констант повторяют имена полей заголовков, используемые в протоколе.
namespace Header { namespace Header {
//! \~english Common request and response header fields.
//! \~russian Общие поля заголовков запросов и ответов.
constexpr static char Accept[] = "Accept"; constexpr static char Accept[] = "Accept";
constexpr static char AcceptCharset[] = "Accept-Charset"; constexpr static char AcceptCharset[] = "Accept-Charset";
constexpr static char AcceptEncoding[] = "Accept-Encoding"; constexpr static char AcceptEncoding[] = "Accept-Encoding";
@@ -181,11 +140,7 @@ constexpr static char UserAgent[] = "User-Agent";
constexpr static char Vary[] = "Vary"; constexpr static char Vary[] = "Vary";
constexpr static char Via[] = "Via"; constexpr static char Via[] = "Via";
constexpr static char WWWAuthenticate[] = "WWW-Authenticate"; constexpr static char WWWAuthenticate[] = "WWW-Authenticate";
//! \~english Special wildcard token used by some HTTP fields.
//! \~russian Специальный подстановочный токен, используемый некоторыми HTTP-полями.
constexpr static char Asterisk[] = "*"; constexpr static char Asterisk[] = "*";
//! \~english Extended, CORS, security and protocol-specific header fields.
//! \~russian Расширенные, CORS-, security- и protocol-specific поля заголовков.
constexpr static char AIM[] = "A-IM"; constexpr static char AIM[] = "A-IM";
constexpr static char AcceptAdditions[] = "Accept-Additions"; constexpr static char AcceptAdditions[] = "Accept-Additions";
constexpr static char AcceptCH[] = "Accept-CH"; constexpr static char AcceptCH[] = "Accept-CH";

View File

@@ -1,27 +1,3 @@
//! \~\file pihttptypes.h
//! \~\ingroup HTTP
//! \~\brief
//! \~english Shared HTTP message container types
//! \~russian Общие типы контейнеров HTTP-сообщений
/*
PIP - Platform Independent Primitives
Shared HTTP message container types
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef pihttptypes_h #ifndef pihttptypes_h
#define pihttptypes_h #define pihttptypes_h
@@ -30,76 +6,71 @@
#include "pistringlist.h" #include "pistringlist.h"
//! \~english Namespace with shared HTTP data types.
//! \~russian Пространство имен с общими HTTP-типами данных.
namespace PIHTTP { namespace PIHTTP {
//! \~\ingroup HTTP //! \~english Immutable HTTP message container with accessors for message components
//! \~\brief //! \~russian Контейнер для неизменяемого HTTP-сообщения с методами доступа к компонентам
//! \~english Immutable HTTP message view with accessors for method, path, headers and body.
//! \~russian Неизменяемое HTTP-сообщение с доступом к методу, пути, заголовкам и телу.
class PIP_EXPORT MessageConst { class PIP_EXPORT MessageConst {
public: public:
//! \~english Returns the HTTP method of the message. //! \~english Gets the HTTP method used in the message
//! \~russian Возвращает HTTP-метод сообщения. //! \~russian Возвращает HTTP-метод, использованный в сообщении
PIHTTP::Method method() const { return m_method; } PIHTTP::Method method() const { return m_method; }
//! \~english Returns the HTTP status code of the message. //! \~english Gets the HTTP status code
//! \~russian Возвращает HTTP-код статуса сообщения. //! \~russian Возвращает HTTP-статус код
PIHTTP::Code code() const { return m_code; } PIHTTP::Code code() const { return m_code; }
//! \~english Returns \c true for informational status codes in the 1xx range. //! \~english Checks if status code is informational (1xx)
//! \~russian Возвращает \c true для информационных кодов статуса из диапазона 1xx. //! \~russian Проверяет, является ли статус код информационным (1xx)
bool isCodeInformational() const; bool isCodeInformational() const;
//! \~english Returns \c true for successful status codes in the 2xx range. //! \~english Checks if status code indicates success (2xx)
//! \~russian Возвращает \c true для успешных кодов статуса из диапазона 2xx. //! \~russian Проверяет, указывает ли статус код на успех (2xx)
bool isCodeSuccess() const; bool isCodeSuccess() const;
//! \~english Returns \c true for redirection status codes in the 3xx range. //! \~english Checks if status code indicates redirection (3xx)
//! \~russian Возвращает \c true для кодов перенаправления из диапазона 3xx. //! \~russian Проверяет, указывает ли статус код на перенаправление (3xx)
bool isCodeRedirection() const; bool isCodeRedirection() const;
//! \~english Returns \c true for client error status codes in the 4xx range. //! \~english Checks if status code indicates client error (4xx)
//! \~russian Возвращает \c true для кодов ошибки клиента из диапазона 4xx. //! \~russian Проверяет, указывает ли статус код на ошибку клиента (4xx)
bool isCodeClientError() const; bool isCodeClientError() const;
//! \~english Returns \c true for server error status codes in the 5xx range. //! \~english Checks if status code indicates server error (5xx)
//! \~russian Возвращает \c true для кодов ошибки сервера из диапазона 5xx. //! \~russian Проверяет, указывает ли статус код на ошибку сервера (5xx)
bool isCodeServerError() const; bool isCodeServerError() const;
//! \~english Returns \c true for any client or server error status code. //! \~english Checks if status code indicates any error (4xx or 5xx)
//! \~russian Возвращает \c true для любого кода ошибки клиента или сервера. //! \~russian Проверяет, указывает ли статус код на любую ошибку (4xx или 5xx)
bool isCodeError() const { return isCodeClientError() || isCodeServerError(); } bool isCodeError() const { return isCodeClientError() || isCodeServerError(); }
//! \~english Gets the request/response path
//! \~english Returns the request path or response target path. //! \~russian Возвращает путь запроса/ответа
//! \~russian Возвращает путь запроса или целевой путь ответа.
const PIString & path() const { return m_path; } const PIString & path() const { return m_path; }
//! \~english Returns the path split into non-empty components. //! \~english Gets path components as list
//! \~russian Возвращает путь, разбитый на непустые компоненты. //! \~russian Возвращает компоненты пути в виде списка
PIStringList pathList() const { return m_path.split('/').removeAll({}); } PIStringList pathList() const { return m_path.split('/').removeAll({}); }
//! \~english Returns the message body. //! \~english Gets the message body
//! \~russian Возвращает тело сообщения. //! \~russian Возвращает тело сообщения
const PIByteArray & body() const { return m_body; } const PIByteArray & body() const { return m_body; }
//! \~english Returns all message headers. //! \~english Gets all message headers
//! \~russian Возвращает все заголовки сообщения. //! \~russian Возвращает все заголовки сообщения
const PIMap<PIString, PIString> & headers() const { return m_headers; } const PIMap<PIString, PIString> & headers() const { return m_headers; }
//! \~english Returns parsed query arguments from the URL. //! \~english Gets URL query arguments
//! \~russian Возвращает разобранные query-аргументы URL. //! \~russian Возвращает URL query аргументы
const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; } const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; }
//! \~english Returns extracted path arguments. //! \~english Gets URL path arguments
//! \~russian Возвращает извлеченные аргументы пути. //! \~russian Возвращает URL path аргументы
const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; } const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; }
//! \~english Returns the combined argument map from query and path arguments. //! \~english Gets all message arguments (query + path)
//! \~russian Возвращает объединенную карту аргументов из query и path. //! \~russian Возвращает все аргументы сообщения (query + path)
const PIMap<PIString, PIString> & arguments() const { return m_arguments; } const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
protected: protected:
@@ -112,101 +83,78 @@ protected:
}; };
//! \~\ingroup HTTP //! \~english Mutable HTTP message container with modifiers for message components
//! \~\brief //! \~russian Контейнер для изменяемого HTTP-сообщения с методами модификации
//! \~english Mutable HTTP message with setters and argument/header modifiers.
//! \~russian Изменяемое HTTP-сообщение с сеттерами и методами изменения аргументов и заголовков.
class PIP_EXPORT MessageMutable: public MessageConst { class PIP_EXPORT MessageMutable: public MessageConst {
public: public:
//! \~english Sets the HTTP method. //! \~english Sets the HTTP method
//! \~russian Устанавливает HTTP-метод. //! \~russian Устанавливает HTTP-метод
MessageMutable & setMethod(PIHTTP::Method m); MessageMutable & setMethod(PIHTTP::Method m);
//! \~english Sets the HTTP status code. //! \~english Sets the HTTP status code
//! \~russian Устанавливает HTTP-код статуса. //! \~russian Устанавливает HTTP-статус код
MessageMutable & setCode(PIHTTP::Code c); MessageMutable & setCode(PIHTTP::Code c);
//! \~english Sets the request path or response target path. //! \~english Sets the request/response path
//! \~russian Устанавливает путь запроса или целевой путь ответа. //! \~russian Устанавливает путь запроса/ответа
MessageMutable & setPath(PIString p); MessageMutable & setPath(PIString p);
//! \~english Sets the message body. //! \~english Sets the message body
//! \~russian Устанавливает тело сообщения. //! \~russian Устанавливает тело сообщения
MessageMutable & setBody(PIByteArray b); MessageMutable & setBody(PIByteArray b);
//! \~english Returns all message headers.
//! \~russian Возвращает все заголовки сообщения.
const PIMap<PIString, PIString> & headers() const { return m_headers; } const PIMap<PIString, PIString> & headers() const { return m_headers; }
//! \~english Returns a modifiable map of all arguments.
//! \~russian Возвращает изменяемую карту всех аргументов.
PIMap<PIString, PIString> & arguments() { return m_arguments; } PIMap<PIString, PIString> & arguments() { return m_arguments; }
//! \~english Returns all arguments.
//! \~russian Возвращает все аргументы.
const PIMap<PIString, PIString> & arguments() const { return m_arguments; } const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
//! \~english Returns query arguments.
//! \~russian Возвращает query-аргументы.
const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; } const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; }
//! \~english Returns path arguments.
//! \~russian Возвращает аргументы пути.
const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; } const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; }
//! \~english Returns a modifiable map of all message headers.
//! \~russian Возвращает изменяемую карту всех заголовков сообщения.
PIMap<PIString, PIString> & headers() { return m_headers; } PIMap<PIString, PIString> & headers() { return m_headers; }
//! \~english Adds or replaces a header in the message. //! \~english Adds a header to the message
//! \~russian Добавляет заголовок в сообщение или заменяет существующий. //! \~russian Добавляет заголовок к сообщению
MessageMutable & addHeader(const PIString & header, const PIString & value); MessageMutable & addHeader(const PIString & header, const PIString & value);
//! \~english Removes a header from the message. //! \~english Removes a header from the message
//! \~russian Удаляет заголовок из сообщения. //! \~russian Удаляет заголовок из сообщения
MessageMutable & removeHeader(const PIString & header); MessageMutable & removeHeader(const PIString & header);
//! \~english Gets reference to URL query arguments
//! \~english Returns a modifiable map of query arguments. //! \~russian Возвращает ссылку на URL query аргументы
//! \~russian Возвращает изменяемую карту query-аргументов.
PIMap<PIString, PIString> & queryArguments() { return m_query_arguments; } PIMap<PIString, PIString> & queryArguments() { return m_query_arguments; }
//! \~english Adds or replaces a query argument. //! \~english Adds an URL query argument to the message
//! \~russian Добавляет query-аргумент или заменяет существующий. //! \~russian Добавляет URL query аргумент к сообщению
MessageMutable & addQueryArgument(const PIString & arg, const PIString & value); MessageMutable & addQueryArgument(const PIString & arg, const PIString & value);
//! \~english Removes a query argument. //! \~english Removes an URL query argument from the message
//! \~russian Удаляет query-аргумент. //! \~russian Удаляет URL query аргумент из сообщения
MessageMutable & removeQueryArgument(const PIString & arg); MessageMutable & removeQueryArgument(const PIString & arg);
//! \~english Gets reference to URL path arguments
//! \~english Returns a modifiable map of path arguments. //! \~russian Возвращает ссылку на URL path аргументы
//! \~russian Возвращает изменяемую карту аргументов пути.
PIMap<PIString, PIString> & pathArguments() { return m_path_arguments; } PIMap<PIString, PIString> & pathArguments() { return m_path_arguments; }
//! \~english Adds or replaces a path argument. //! \~english Adds an URL path argument to the message
//! \~russian Добавляет аргумент пути или заменяет существующий. //! \~russian Добавляет URL path аргумент к сообщению
MessageMutable & addPathArgument(const PIString & arg, const PIString & value); MessageMutable & addPathArgument(const PIString & arg, const PIString & value);
//! \~english Removes a path argument. //! \~english Removes an URL path argument from the message
//! \~russian Удаляет аргумент пути. //! \~russian Удаляет URL query path из сообщения
MessageMutable & removePathArgument(const PIString & arg); MessageMutable & removePathArgument(const PIString & arg);
//! \~english Creates message from HTTP status code
//! \~english Creates a message initialized from an HTTP status code. //! \~russian Создает сообщение из HTTP-статус кода
//! \~russian Создает сообщение, инициализированное HTTP-кодом статуса.
static MessageMutable fromCode(PIHTTP::Code c); static MessageMutable fromCode(PIHTTP::Code c);
//! \~english Creates a message initialized from an HTTP method. //! \~english Creates message from HTTP method
//! \~russian Создает сообщение, инициализированное HTTP-методом. //! \~russian Создает сообщение из HTTP-метода
static MessageMutable fromMethod(PIHTTP::Method m); static MessageMutable fromMethod(PIHTTP::Method m);
}; };
//! \~english Returns the canonical string representation of an HTTP method. //! \~english Gets string representation of HTTP method
//! \~russian Возвращает каноническое строковое представление HTTP-метода. //! \~russian Возвращает строковое представление HTTP-метода
PIP_EXPORT const char * methodName(Method m); PIP_EXPORT const char * methodName(Method m);

View File

@@ -1,27 +1,3 @@
//! \~\file microhttpd_server.h
//! \~\ingroup HTTPServer
//! \~\brief
//! \~english Base HTTP server API built on top of libmicrohttpd
//! \~russian Базовый API HTTP-сервера, построенный поверх libmicrohttpd
/*
PIP - Platform Independent Primitives
Base HTTP server API built on top of libmicrohttpd
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MICROHTTPD_SERVER_P_H #ifndef MICROHTTPD_SERVER_P_H
#define MICROHTTPD_SERVER_P_H #define MICROHTTPD_SERVER_P_H
@@ -31,93 +7,86 @@
struct MicrohttpdServerConnection; struct MicrohttpdServerConnection;
//! \~\ingroup HTTPServer //! \~english Base HTTP server class implementing core functionality
//! \~\brief //! \~russian Базовый класс HTTP сервера, реализующий основную функциональность
//! \~english Base HTTP server with request dispatch and optional basic authentication.
//! \~russian Базовый HTTP-сервер с диспетчеризацией запросов и необязательной basic-аутентификацией.
class PIP_HTTP_SERVER_EXPORT MicrohttpdServer: public PIObject { class PIP_HTTP_SERVER_EXPORT MicrohttpdServer: public PIObject {
PIOBJECT(MicrohttpdServer) PIOBJECT(MicrohttpdServer)
friend struct MicrohttpdServerConnection; friend struct MicrohttpdServerConnection;
public: public:
//! \~english Creates a stopped server instance with default options.
//! \~russian Создает остановленный экземпляр сервера с настройками по умолчанию.
MicrohttpdServer(); MicrohttpdServer();
//! \~english Stops the server and releases native resources.
//! \~russian Останавливает сервер и освобождает нативные ресурсы.
virtual ~MicrohttpdServer(); virtual ~MicrohttpdServer();
//! \~english Server configuration options accepted by \a setOption(). //! \~english Server configuration options
//! \~russian Параметры конфигурации сервера, принимаемые методом \a setOption(). //! \~russian Опции конфигурации сервера
enum class Option { enum class Option {
ConnectionLimit /** \~english Maximum number of simultaneously accepted connections. \~russian Максимальное число одновременно ConnectionLimit, //!< \~english Maximum concurrent connections
принимаемых соединений. */ //!< \~russian Максимальное количество соединений
, ConnectionTimeout, //!< \~english Connection timeout in seconds
ConnectionTimeout /** \~english Per-connection timeout value. \~russian Значение таймаута для отдельного соединения. */, //!< \~russian Таймаут соединения в секундах
HTTPSEnabled /** \~english Enables TLS mode for the daemon. \~russian Включает режим TLS для демона. */, HTTPSEnabled, //!< \~english Enable HTTPS support
HTTPSMemKey /** \~english Private key stored in memory as \c PIByteArray. \~russian Приватный ключ, хранящийся в памяти в виде \c //!< \~russian Включить поддержку HTTPS
PIByteArray. */ HTTPSMemKey, //!< \~english SSL key in memory (PIByteArray)
, //!< \~russian SSL ключ в памяти (PIByteArray)
HTTPSMemCert /** \~english Certificate stored in memory as \c PIByteArray. \~russian Сертификат, хранящийся в памяти в виде \c HTTPSMemCert, //!< \~english SSL certificate in memory (PIByteArray)
PIByteArray. */ //!< \~russian SSL сертификат в памяти (PIByteArray)
, HTTPSKeyPassword //!< \~english SSL key password (PIByteArray)
HTTPSKeyPassword /** \~english Password for the in-memory private key as \c PIByteArray. \~russian Пароль для приватного ключа в //!< \~russian Пароль SSL ключа (PIByteArray)
памяти в виде \c PIByteArray. */
}; };
//! \~english Sets a server option. The expected variant payload depends on the selected \a Option. //! \~english Sets server option
//! \~russian Устанавливает параметр сервера. Ожидаемый тип значения \c PIVariant зависит от выбранного \a Option. //! \~russian Устанавливает опцию сервера
void setOption(Option o, PIVariant v); void setOption(Option o, PIVariant v);
//! \~english Sets the bytes returned for requests to \c /favicon.ico. //! \~english Sets server favicon
//! \~russian Устанавливает байты, возвращаемые для запросов к \c /favicon.ico. //! \~russian Устанавливает фавикон сервера
void setFavicon(const PIByteArray & im); void setFavicon(const PIByteArray & im);
//! \~english Starts listening on the specified network address, restarting the daemon if needed. //! \~english Starts server on specified address
//! \~russian Запускает прослушивание на указанном сетевом адресе, при необходимости перезапуская демон. //! \~russian Запускает сервер на указанном адресе
bool listen(PINetworkAddress addr); bool listen(PINetworkAddress addr);
//! \~english Starts listening on all interfaces for the specified port. //! \~english Starts server on all interfaces
//! \~russian Запускает прослушивание на всех интерфейсах для указанного порта. //! \~russian Запускает сервер на всех интерфейсах
bool listenAll(ushort port) { return listen({0, port}); } bool listenAll(ushort port) { return listen({0, port}); }
//! \~english Returns \c true while the native HTTP daemon is running. //! \~english Checks if server is running
//! \~russian Возвращает \c true, пока нативный HTTP-демон запущен. //! \~russian Проверяет, работает ли сервер
bool isListen() const; bool isListen() const;
//! \~english Stops listening and shuts down the native HTTP daemon. //! \~english Stops the server
//! \~russian Останавливает прослушивание и завершает работу нативного HTTP-демона. //! \~russian Останавливает сервер
void stop(); void stop();
//! \~english Enables HTTP Basic authentication checks for new requests. //! \~english Enables basic authentication
//! \~russian Включает проверки HTTP Basic-аутентификации для новых запросов. //! \~russian Включает базовую аутентификацию
void enableBasicAuth() { setBasicAuthEnabled(true); } void enableBasicAuth() { setBasicAuthEnabled(true); }
//! \~english Disables HTTP Basic authentication checks. //! \~english Disables basic authentication
//! \~russian Отключает проверки HTTP Basic-аутентификации. //! \~russian Выключает базовую аутентификацию
void disableBasicAuth() { setBasicAuthEnabled(false); } void disableBasicAuth() { setBasicAuthEnabled(false); }
//! \~english Enables or disables HTTP Basic authentication checks. //! \~english Set basic authentication enabled to "yes"
//! \~russian Включает или отключает проверки HTTP Basic-аутентификации. //! \~russian Устанавливает базовую аутентификацию в "yes"
void setBasicAuthEnabled(bool yes) { use_basic_auth = yes; } void setBasicAuthEnabled(bool yes) { use_basic_auth = yes; }
//! \~english Returns whether HTTP Basic authentication checks are enabled. //! \~english Return if basic authentication enabled
//! \~russian Возвращает, включены ли проверки HTTP Basic-аутентификации. //! \~russian Возвращает включена ли базовая аутентификация
bool isBasicAuthEnabled() const { return use_basic_auth; } bool isBasicAuthEnabled() const { return use_basic_auth; }
//! \~english Sets the realm sent in HTTP Basic authentication challenges. //! \~english Sets basic authentication realm
//! \~russian Устанавливает realm, отправляемый в challenge HTTP Basic-аутентификации. //! \~russian Устанавливает область аутентификации
void setBasicAuthRealm(const PIString & r) { realm = r; } void setBasicAuthRealm(const PIString & r) { realm = r; }
//! \~english Sets the callback that receives parsed requests and returns replies. //! \~english Sets request processing callback
//! \~russian Устанавливает callback, который получает разобранные запросы и возвращает ответы. //! \~russian Устанавливает callback для обработки запросов
void setRequestCallback(std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> c) { callback = std::move(c); } void setRequestCallback(std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> c) { callback = c; }
//! \~english Sets the credential validator used when HTTP Basic authentication is enabled. //! \~english Sets basic authentication callback
//! \~russian Устанавливает валидатор учетных данных, используемый при включенной HTTP Basic-аутентификации. //! \~russian Устанавливает callback для базовой аутентификации
void setBasicAuthCallback(std::function<bool(const PIString &, const PIString &)> c) { callback_auth = std::move(c); } void setBasicAuthCallback(std::function<bool(const PIString &, const PIString &)> c) { callback_auth = c; }
private: private:
static void addFixedHeaders(PIHTTP::MessageMutable & msg); static void addFixedHeaders(PIHTTP::MessageMutable & msg);

View File

@@ -1,67 +1,26 @@
//! \addtogroup HTTPServer
//! \~\file pihttpserver.h
//! \brief High-level HTTP server implementation
//! \~english High-level HTTP server with path-based routing and handler registration
//! \~russian Высокоуровневый HTTP сервер с маршрутизацией по путям и регистрацией обработчиков
/*
PIP - Platform Independent Primitives
High-level HTTP server implementation
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIHTTPSERVER_H #ifndef PIHTTPSERVER_H
#define PIHTTPSERVER_H #define PIHTTPSERVER_H
#include "microhttpd_server.h" #include "microhttpd_server.h"
//! \~\ingroup HTTPServer //! \~english HTTP server
//! \~\brief //! \~russian HTTP сервер
//! \~english HTTP server that routes requests by method and path pattern.
//! \~russian HTTP-сервер, маршрутизирующий запросы по методу и шаблону пути.
//!
//! \~\details
//! \~english Registered paths are matched segment by segment. The router supports fixed segments,
//! \c * for any single segment, \c ** for any tail, and \c {name} placeholders that populate
//! \a PIHTTP::MessageConst::pathArguments().
//! \~russian Зарегистрированные пути сопоставляются посегментно. Маршрутизатор поддерживает
//! фиксированные сегменты, \c * для любого одного сегмента, \c ** для любого хвоста и
//! заполнители \c {name}, которые заполняют \a PIHTTP::MessageConst::pathArguments().
class PIP_HTTP_SERVER_EXPORT PIHTTPServer: public MicrohttpdServer { class PIP_HTTP_SERVER_EXPORT PIHTTPServer: public MicrohttpdServer {
PIOBJECT_SUBCLASS(PIHTTPServer, MicrohttpdServer) PIOBJECT_SUBCLASS(PIHTTPServer, MicrohttpdServer)
public: public:
//! \~english Creates a server with built-in path dispatching.
//! \~russian Создает сервер со встроенной диспетчеризацией по путям.
PIHTTPServer(); PIHTTPServer();
//! \~english Destroys the server and stops listening if needed.
//! \~russian Удаляет сервер и при необходимости останавливает прослушивание.
virtual ~PIHTTPServer(); virtual ~PIHTTPServer();
//! \~english Request handler used by registered routes and fallback processing.
//! \~russian Обработчик запроса, используемый зарегистрированными маршрутами и fallback-обработкой.
using RequestFunction = std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)>; using RequestFunction = std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)>;
//! \~english Registers a handler for the specified path pattern and HTTP method. //! \~english Registers handler for specific path and HTTP method
//! \~russian Регистрирует обработчик для указанного шаблона пути и HTTP-метода. //! \~russian Регистрирует обработчик для указанного пути и HTTP метода
bool registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor); bool registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor);
//! \~english Registers an object method as a handler for the specified path pattern and HTTP method. //! \~english Registers handler for specific path and HTTP method
//! \~russian Регистрирует метод объекта как обработчик для указанного шаблона пути и HTTP-метода. //! \~russian Регистрирует обработчик для указанного пути и HTTP метода
template<typename T> template<typename T>
bool bool
registerPath(const PIString & path, PIHTTP::Method method, T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) { registerPath(const PIString & path, PIHTTP::Method method, T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
@@ -69,36 +28,36 @@ public:
} }
//! \~english Registers a fallback handler for requests that did not match any route. //! \~english Registers handler for unregistered pathes
//! \~russian Регистрирует fallback-обработчик для запросов, не совпавших ни с одним маршрутом. //! \~russian Регистрирует обработчик для незарегистрированных путей
void registerUnhandled(RequestFunction functor); void registerUnhandled(RequestFunction functor);
//! \~english Registers an object method as the fallback handler for unmatched requests. //! \~english Registers handler for unregistered pathes
//! \~russian Регистрирует метод объекта как fallback-обработчик для несовпавших запросов. //! \~russian Регистрирует обработчик для незарегистрированных путей
template<typename T> template<typename T>
void registerUnhandled(T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) { void registerUnhandled(T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
registerUnhandled([o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); }); registerUnhandled([o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); });
} }
//! \~english Unregisters the handler for the specified path pattern and HTTP method. //! \~english Unregisters handler for specific path and method
//! \~russian Удаляет обработчик для указанного шаблона пути и HTTP-метода. //! \~russian Удаляет обработчик для указанного пути и метода
void unregisterPath(const PIString & path, PIHTTP::Method method); void unregisterPath(const PIString & path, PIHTTP::Method method);
//! \~english Unregisters all handlers bound to the specified path pattern. //! \~english Unregisters all handlers for specific path
//! \~russian Удаляет все обработчики, привязанные к указанному шаблону пути. //! \~russian Удаляет все обработчики для указанного пути
void unregisterPath(const PIString & path); void unregisterPath(const PIString & path);
//! \~english Adds a header that will be copied to all replies produced by this router. //! \~english Adds header to all server responses
//! \~russian Добавляет заголовок, который будет копироваться во все ответы этого маршрутизатора. //! \~russian Добавляет заголовок ко всем ответам сервера
void addReplyHeader(const PIString & name, const PIString & value) { reply_headers[name] = value; } void addReplyHeader(const PIString & name, const PIString & value) { reply_headers[name] = value; }
//! \~english Removes a previously added common reply header. //! \~english Removes header from server responses
//! \~russian Удаляет ранее добавленный общий заголовок ответа. //! \~russian Удаляет заголовок из ответов сервера
void removeReplyHeader(const PIString & name) { reply_headers.remove(name); } void removeReplyHeader(const PIString & name) { reply_headers.remove(name); }
//! \~english Clears all custom headers added to router replies. //! \~english Clears all custom response headers
//! \~russian Очищает все пользовательские заголовки, добавленные к ответам маршрутизатора. //! \~russian Очищает все пользовательские заголовки ответов
void clearReplyHeaders() { reply_headers.clear(); } void clearReplyHeaders() { reply_headers.clear(); }
private: private:

View File

@@ -1,11 +1,3 @@
//! \file pihttpservermodule.h
//! \ingroup HTTPServer
//! \~\brief
//! \~english Module include for the public HTTP server API
//! \~russian Модульный include для публичного API HTTP-сервера
//! \~\details
//! \~english Includes the primary public HTTP server class declarations.
//! \~russian Подключает основные публичные объявления классов HTTP-сервера.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Module includes Module includes
@@ -38,9 +30,14 @@
//! target_link_libraries([target] PIP::HTTPServer) //! target_link_libraries([target] PIP::HTTPServer)
//! \endcode //! \endcode
//! //!
//! \~\details //! \~english \par Common
//! \~english This file provides includes for the HTTP server module //! \~russian \par Общее
//! \~russian Этот файл предоставляет включения для модуля HTTP сервера //!
//! \~english
//! These files provides HTTP server based on libmicrohttpd
//!
//! \~russian
//! Эти файлы обеспечивают HTTP сервер, основанный на libmicrohttpd
//! //!
//! \~\authors //! \~\authors
//! \~english //! \~english

View File

@@ -1,9 +1,3 @@
/*! \file piintrospection_base.h
* \ingroup Introspection
* \~\brief
* \~english Base declarations for the introspection subsystem
* \~russian Базовые объявления подсистемы интроспекции
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module - base macros and types Introspection module - base macros and types
@@ -66,22 +60,6 @@ class PIPeer;
class PIIntrospection; class PIIntrospection;
class PIIntrospectionServer; class PIIntrospectionServer;
#ifdef DOXYGEN
//! \~\ingroup Introspection
//! \~\brief
//! \~english Declares singleton accessor `instance()` for an introspection interface class.
//! \~russian Объявляет метод-синглтон `instance()` для класса интерфейса интроспекции.
# define __PIINTROSPECTION_SINGLETON_H__(T)
//! \~\ingroup Introspection
//! \~\brief
//! \~english Defines singleton accessor `instance()` for an introspection interface class.
//! \~russian Определяет метод-синглтон `instance()` для класса интерфейса интроспекции.
# define __PIINTROSPECTION_SINGLETON_CPP__(T)
#else
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
# define __PIINTROSPECTION_SINGLETON_H__(T) static PIIntrospection##T##Interface * instance(); # define __PIINTROSPECTION_SINGLETON_H__(T) static PIIntrospection##T##Interface * instance();
@@ -91,6 +69,4 @@ class PIIntrospectionServer;
return &ret; \ return &ret; \
} }
#endif // PIP_INTROSPECTION #endif // PIP_INTROSPECTION
#endif // DOXYGEN
#endif // PIINTROSPECTION_BASE_H #endif // PIINTROSPECTION_BASE_H

View File

@@ -1,8 +1,3 @@
//! \~\file piintrospection_containers.h
//! \~\ingroup Introspection
//! \~\brief
//! \~english Container introspection helpers
//! \~russian Вспомогательные средства интроспекции контейнеров
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module - interface for containers Introspection module - interface for containers
@@ -27,37 +22,13 @@
#include "pibase.h" #include "pibase.h"
//! \~\ingroup Introspection
//! \~\brief
//! \~english Metadata describing one tracked container element type.
//! \~russian Метаданные, описывающие один отслеживаемый тип элементов контейнера.
struct PIP_EXPORT PIIntrospectionContainersType { struct PIP_EXPORT PIIntrospectionContainersType {
//! \~english Destroys the type descriptor.
//! \~russian Уничтожает дескриптор типа.
~PIIntrospectionContainersType(); ~PIIntrospectionContainersType();
//! \~english Finalizes type information, including generated identifiers and names.
//! \~russian Завершает подготовку информации о типе, включая сгенерированные идентификаторы и имена.
void finish(); void finish();
//! \~english Stable identifier of the tracked type.
//! \~russian Стабильный идентификатор отслеживаемого типа.
uint id = 0; uint id = 0;
//! \~english Compiler-provided type name.
//! \~russian Имя типа, предоставленное компилятором.
const char * name = nullptr; const char * name = nullptr;
//! \~english Demangled type name when available.
//! \~russian Деманглированное имя типа, если доступно.
const char * demangled = "?"; const char * demangled = "?";
//! \~english True after \a finish() prepares the descriptor.
//! \~russian Истина после того, как \a finish() подготовит дескриптор.
bool inited = false; bool inited = false;
//! \~english True when demangled name was resolved successfully.
//! \~russian Истина, если деманглированное имя успешно получено.
bool has_demangled = false; bool has_demangled = false;
}; };
@@ -67,15 +38,9 @@ struct PIP_EXPORT PIIntrospectionContainersType {
class PIIntrospectionContainers; class PIIntrospectionContainers;
//! \~\ingroup Introspection
//! \~\brief
//! \~english Lazily builds and caches type metadata for container introspection macros.
//! \~russian Лениво создает и кеширует метаданные типа для макросов интроспекции контейнеров.
template<typename T> template<typename T>
class PIIntrospectionContainersTypeInfo { class PIIntrospectionContainersTypeInfo {
public: public:
//! \~english Returns cached metadata for type `T`.
//! \~russian Возвращает кешированные метаданные для типа `T`.
static const PIIntrospectionContainersType & get() { static const PIIntrospectionContainersType & get() {
static PIIntrospectionContainersType ret = create(); static PIIntrospectionContainersType ret = create();
return ret; return ret;
@@ -92,52 +57,6 @@ private:
# define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance()) # define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())
# ifdef DOXYGEN
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionContainersInterface
//! \~\brief
//! \~english Registers construction of a container storing elements of type `t`.
//! \~russian Регистрирует создание контейнера, хранящего элементы типа `t`.
# define PIINTROSPECTION_CONTAINER_NEW(t, isz)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionContainersInterface
//! \~\brief
//! \~english Registers destruction of a container storing elements of type `t`.
//! \~russian Регистрирует уничтожение контейнера, хранящего элементы типа `t`.
# define PIINTROSPECTION_CONTAINER_DELETE(t)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionContainersInterface
//! \~\brief
//! \~english Adds `cnt` allocated element slots for containers of type `t`.
//! \~russian Добавляет `cnt` выделенных слотов элементов для контейнеров типа `t`.
# define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionContainersInterface
//! \~\brief
//! \~english Removes `cnt` allocated element slots for containers of type `t`.
//! \~russian Убирает `cnt` выделенных слотов элементов для контейнеров типа `t`.
# define PIINTROSPECTION_CONTAINER_FREE(t, cnt)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionContainersInterface
//! \~\brief
//! \~english Adds `cnt` used element slots for containers of type `t`.
//! \~russian Добавляет `cnt` занятых слотов элементов для контейнеров типа `t`.
# define PIINTROSPECTION_CONTAINER_USED(t, cnt)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionContainersInterface
//! \~\brief
//! \~english Removes `cnt` used element slots for containers of type `t`.
//! \~russian Убирает `cnt` занятых слотов элементов для контейнеров типа `t`.
# define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt)
# else
// 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);
# define PIINTROSPECTION_CONTAINER_DELETE(t) PIINTROSPECTION_CONTAINERS->containerDelete(PIIntrospectionContainersTypeInfo<t>::get() ); # define PIINTROSPECTION_CONTAINER_DELETE(t) PIINTROSPECTION_CONTAINERS->containerDelete(PIIntrospectionContainersTypeInfo<t>::get() );
@@ -147,13 +66,7 @@ private:
# define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUnused(PIIntrospectionContainersTypeInfo<t>::get(), cnt); # define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUnused(PIIntrospectionContainersTypeInfo<t>::get(), cnt);
// clang-format on // clang-format on
# endif
//! \~\ingroup Introspection
//! \~\brief
//! \~english Entry point for collecting container allocation and usage statistics.
//! \~russian Точка входа для сбора статистики выделения и использования контейнеров.
class PIP_EXPORT PIIntrospectionContainersInterface { class PIP_EXPORT PIIntrospectionContainersInterface {
friend class PIIntrospection; friend class PIIntrospection;
friend class PIIntrospectionServer; friend class PIIntrospectionServer;
@@ -161,32 +74,15 @@ class PIP_EXPORT PIIntrospectionContainersInterface {
public: public:
__PIINTROSPECTION_SINGLETON_H__(Containers) __PIINTROSPECTION_SINGLETON_H__(Containers)
//! \~english Registers construction of a container instance with element size `isz`. // clang-format off
//! \~russian Регистрирует создание экземпляра контейнера с размером элемента `isz`. void containerNew (const PIIntrospectionContainersType & ti, uint isz);
void containerNew(const PIIntrospectionContainersType & ti, uint isz);
//! \~english Registers destruction of a container instance.
//! \~russian Регистрирует уничтожение экземпляра контейнера.
void containerDelete(const PIIntrospectionContainersType & ti); void containerDelete(const PIIntrospectionContainersType & ti);
void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Adds `cnt` allocated element slots for tracked type `ti`. void containerFree (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~russian Добавляет `cnt` выделенных слотов элементов для отслеживаемого типа `ti`. void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt);
void containerAlloc(const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Removes `cnt` allocated element slots for tracked type `ti`.
//! \~russian Убирает `cnt` выделенных слотов элементов для отслеживаемого типа `ti`.
void containerFree(const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Adds `cnt` used element slots for tracked type `ti`.
//! \~russian Добавляет `cnt` занятых слотов элементов для отслеживаемого типа `ti`.
void containerUsed(const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Removes `cnt` used element slots for tracked type `ti`.
//! \~russian Убирает `cnt` занятых слотов элементов для отслеживаемого типа `ti`.
void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt); void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt);
// clang-format on
//! \~english Private implementation pointer with collected statistics.
//! \~russian Указатель на приватную реализацию с накопленной статистикой.
PIIntrospectionContainers * p; PIIntrospectionContainers * p;
private: private:

View File

@@ -1,8 +1,9 @@
//! \~\file piintrospection_server.h /*! \file piintrospection_server.h
//! \~\ingroup Introspection * \ingroup Introspection
//! \~\brief * \~\brief
//! \~english Introspection server * \~english Introspection server
//! \~russian Сервер интроспекции * \~russian Сервер интроспекции
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module Introspection module
@@ -27,16 +28,12 @@
#ifdef DOXYGEN #ifdef DOXYGEN
//! \~\ingroup Introspection //! \ingroup Introspection
//! \relatesalso PIIntrospectionServer
//! \~\brief
//! \~english Start introspection server with name "name" //! \~english Start introspection server with name "name"
//! \~russian Запускает сервер интроспекции с именем "name" //! \~russian Запускает сервер интроспекции с именем "name"
# define PIINTROSPECTION_START(name) # define PIINTROSPECTION_START(name)
//! \~\ingroup Introspection //! \ingroup Introspection
//! \relatesalso PIIntrospectionServer
//! \~\brief
//! \~english Stop introspection server //! \~english Stop introspection server
//! \~russian Останавливает сервер интроспекции //! \~russian Останавливает сервер интроспекции
# define PIINTROSPECTION_STOP # define PIINTROSPECTION_STOP
@@ -54,24 +51,13 @@ 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();
//! \~\ingroup Introspection
//! \~\brief
//! \~english Peer-based server that replies to introspection requests for the current process.
//! \~russian Сервер на основе peer, отвечающий на запросы интроспекции для текущего процесса.
class PIP_EXPORT PIIntrospectionServer: public PIPeer { class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer); PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer);
public: public:
//! \~english Returns singleton server instance.
//! \~russian Возвращает экземпляр сервера-синглтона.
static PIIntrospectionServer * instance(); static PIIntrospectionServer * instance();
//! \~english Starts the server and publishes it under name derived from `server_name`.
//! \~russian Запускает сервер и публикует его под именем, построенным от `server_name`.
void start(const PIString & server_name); void start(const PIString & server_name);
//! \~english Stops the server and releases its system monitor when needed.
//! \~russian Останавливает сервер и при необходимости освобождает его системный монитор.
void stop(); void stop();
private: private:

View File

@@ -19,10 +19,12 @@
#include "piintrospection_server_p.h" #include "piintrospection_server_p.h"
#include "pichunkstream.h" #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piinit.h"
#include "piobject.h" # include "pichunkstream.h"
#include "pisysteminfo.h" # include "piinit.h"
# include "piobject.h"
# include "pisysteminfo.h"
const uint PIIntrospection::sign = 0x0F1C2B3A; const uint PIIntrospection::sign = 0x0F1C2B3A;
@@ -111,9 +113,9 @@ PIByteArray PIIntrospection::packContainers() {
PIByteArray ret; PIByteArray ret;
PIVector<PIIntrospectionContainers::TypeInfo> data; PIVector<PIIntrospectionContainers::TypeInfo> data;
PIIntrospectionContainers * p = 0; PIIntrospectionContainers * p = 0;
#ifdef PIP_INTROSPECTION # ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_CONTAINERS->p; p = PIINTROSPECTION_CONTAINERS->p;
#endif # endif
if (p) { if (p) {
data = p->getInfo(); data = p->getInfo();
} }
@@ -131,9 +133,9 @@ void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector<PIIntrospectio
PIByteArray PIIntrospection::packThreads() { PIByteArray PIIntrospection::packThreads() {
PIByteArray ret; PIByteArray ret;
PIIntrospectionThreads * p = 0; PIIntrospectionThreads * p = 0;
#ifdef PIP_INTROSPECTION # ifdef PIP_INTROSPECTION
p = PIINTROSPECTION_THREADS->p; p = PIINTROSPECTION_THREADS->p;
#endif # endif
if (p) { if (p) {
p->mutex.lock(); p->mutex.lock();
PIMap<PIThread *, PIIntrospectionThreads::ThreadInfo> & tm(p->threads); PIMap<PIThread *, PIIntrospectionThreads::ThreadInfo> & tm(p->threads);
@@ -170,3 +172,5 @@ void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector<PIIntrospection::
objects.clear(); objects.clear();
ba >> objects; ba >> objects;
} }
#endif // #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)

View File

@@ -27,6 +27,7 @@
#include "piintrospection_threads_p.h" #include "piintrospection_threads_p.h"
#include "pisystemmonitor.h" #include "pisystemmonitor.h"
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
class PIP_EXPORT PIIntrospection { class PIP_EXPORT PIIntrospection {
public: public:
@@ -168,4 +169,5 @@ BINARY_STREAM_READ(PIIntrospection::ObjectInfo) {
return s; return s;
} }
#endif // #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#endif // PIINTROSPECTION_SERVER_P_H #endif // PIINTROSPECTION_SERVER_P_H

View File

@@ -1,8 +1,3 @@
//! \~\file piintrospection_threads.h
//! \~\ingroup Introspection
//! \~\brief
//! \~english Thread introspection helpers
//! \~russian Вспомогательные средства интроспекции потоков
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module - interface for threads Introspection module - interface for threads
@@ -33,59 +28,6 @@ class PIIntrospectionThreads;
# define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance()) # define PIINTROSPECTION_THREADS (PIIntrospectionThreadsInterface::instance())
# ifdef DOXYGEN
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionThreadsInterface
//! \~\brief
//! \~english Registers creation of thread object `t`.
//! \~russian Регистрирует создание объекта потока `t`.
# define PIINTROSPECTION_THREAD_NEW(t)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionThreadsInterface
//! \~\brief
//! \~english Registers destruction of thread object `t`.
//! \~russian Регистрирует уничтожение объекта потока `t`.
# define PIINTROSPECTION_THREAD_DELETE(t)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionThreadsInterface
//! \~\brief
//! \~english Marks thread `t` as starting.
//! \~russian Помечает поток `t` как запускающийся.
# define PIINTROSPECTION_THREAD_START(t)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionThreadsInterface
//! \~\brief
//! \~english Marks thread `t` as running.
//! \~russian Помечает поток `t` как выполняющийся.
# define PIINTROSPECTION_THREAD_RUN(t)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionThreadsInterface
//! \~\brief
//! \~english Marks thread `t` as waiting.
//! \~russian Помечает поток `t` как ожидающий.
# define PIINTROSPECTION_THREAD_WAIT(t)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionThreadsInterface
//! \~\brief
//! \~english Marks thread `t` as stopped.
//! \~russian Помечает поток `t` как остановленный.
# define PIINTROSPECTION_THREAD_STOP(t)
//! \~\ingroup Introspection
//! \relatesalso PIIntrospectionThreadsInterface
//! \~\brief
//! \~english Reports completed run of thread `t` that took `us` microseconds.
//! \~russian Сообщает о завершенном проходе потока `t`, занявшем `us` микросекунд.
# define PIINTROSPECTION_THREAD_RUN_DONE(t, us)
# else
# 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);
@@ -94,45 +36,21 @@ class PIIntrospectionThreads;
# 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);
# endif
//! \~\ingroup Introspection
//! \~\brief
//! \~english Entry point for collecting state and timing statistics of \a PIThread objects.
//! \~russian Точка входа для сбора статистики состояний и времени выполнения объектов \a PIThread.
class PIP_EXPORT PIIntrospectionThreadsInterface { class PIP_EXPORT PIIntrospectionThreadsInterface {
friend class PIIntrospection; friend class PIIntrospection;
public: public:
__PIINTROSPECTION_SINGLETON_H__(Threads) __PIINTROSPECTION_SINGLETON_H__(Threads)
//! \~english Registers creation of thread object `t`. // clang-format off
//! \~russian Регистрирует создание объекта потока `t`. void threadNew (PIThread * t);
void threadNew(PIThread * t); void threadDelete (PIThread * t);
void threadStart (PIThread * t);
//! \~english Registers destruction of thread object `t`. void threadRun (PIThread * t);
//! \~russian Регистрирует уничтожение объекта потока `t`. void threadWait (PIThread * t);
void threadDelete(PIThread * t); void threadStop (PIThread * t);
//! \~english Updates statistics for thread `t` when it starts.
//! \~russian Обновляет статистику потока `t` при его запуске.
void threadStart(PIThread * t);
//! \~english Updates statistics for thread `t` when its run handler begins.
//! \~russian Обновляет статистику потока `t`, когда начинается его рабочий проход.
void threadRun(PIThread * t);
//! \~english Marks thread `t` as waiting for the next run.
//! \~russian Помечает поток `t` как ожидающий следующего прохода.
void threadWait(PIThread * t);
//! \~english Marks thread `t` as stopped.
//! \~russian Помечает поток `t` как остановленный.
void threadStop(PIThread * t);
//! \~english Updates averaged run time of thread `t` in microseconds.
//! \~russian Обновляет усредненное время выполнения потока `t` в микросекундах.
void threadRunDone(PIThread * t, ullong us); void threadRunDone(PIThread * t, ullong us);
// clang-format on
private: private:
PIIntrospectionThreadsInterface(); PIIntrospectionThreadsInterface();

View File

@@ -19,6 +19,7 @@
#include "piintrospection_threads_p.h" #include "piintrospection_threads_p.h"
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
PIIntrospectionThreads::ThreadInfo::ThreadInfo() { PIIntrospectionThreads::ThreadInfo::ThreadInfo() {
id = delay = 0; id = delay = 0;
@@ -78,3 +79,5 @@ void PIIntrospectionThreads::threadRunDone(PIThread * t, ullong us) {
ThreadInfo & ti(threads[t]); ThreadInfo & ti(threads[t]);
ti.run_us = (ti.run_us * 0.8) + (us * 0.2); /// WARNING ti.run_us = (ti.run_us * 0.8) + (us * 0.2); /// WARNING
} }
#endif // #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)

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