Doxygen generated by local qwen3-coder-next

This commit is contained in:
2026-02-28 18:32:00 +03:00
parent 0878891cd8
commit 6ed7befa47
12 changed files with 1696 additions and 487 deletions

View File

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

View File

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

View File

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

View File

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