112 Commits

Author SHA1 Message Date
Бычков Анлрей
e85b11a233 PIMap via pipair, fix tests 2022-05-26 18:07:44 +03:00
Бычков Анлрей
831adf3fc9 some new tests 2022-05-25 18:52:19 +03:00
Бычков Анлрей
a18f461ce3 pimap tests 2022-05-24 18:40:06 +03:00
12c032392c pip_cmg namespaces fix 2022-05-20 15:23:01 +03:00
ffa25c18f0 pip_cmg include fix 2022-05-15 17:56:52 +03:00
a502182eba NO_UNUSED 2022-05-09 11:56:09 +03:00
d219baee27 path fix 2022-05-08 22:29:35 +03:00
0ea1e2c856 support for git download of CMake project (standalone PIP build) 2022-05-08 22:22:48 +03:00
3107949e6f doc, small fixes 2022-05-08 19:23:52 +03:00
460519c075 PISingleApplication fix and optimize 2022-05-08 16:35:01 +03:00
9347ed2e55 doc 2022-05-06 23:42:20 +03:00
5770adfd34 PIMap fix 2022-05-06 16:27:40 +03:00
9714d8ea42 PIMap {{K, T}, {K, T}, ...} constructor
doc ru
2022-05-06 12:45:08 +03:00
0b3ee4bb6a doc ru 2022-05-05 22:31:59 +03:00
d1f7065c8a PICout::writePIString -> PICout::write 2022-05-05 10:35:15 +03:00
6995c25613 PIIODevice fullPathPrefix returns PIConstChars 2022-05-04 16:33:05 +03:00
28ce6e8f3f version 2.39.0
PIString works with PIConstChars
picodeinfo optimizations
PIIODevice::availableClasses
2022-05-03 18:44:00 +03:00
8d5730f715 PIPluginLoader +1 error 2022-04-30 16:07:30 +03:00
2bbdbc3ac9 PIIODevice registration dramatically optimization 2022-04-30 11:21:57 +03:00
19e4eee222 PIConstChars API 2022-04-30 09:05:14 +03:00
4139d88103 PIConstChars PIMap supports 2022-04-30 00:07:58 +03:00
6881fd13b7 PIConstChars 2022-04-29 23:53:07 +03:00
Andrey
8c8553a6af PIObject Property const char * 2022-04-29 18:17:03 +03:00
97dd19f0c7 !!!!!!!!!!!!!!!!!! 2022-04-27 16:34:12 +03:00
Andrey
784c949b1a Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-27 15:49:37 +03:00
Andrey
7325e12e30 PIString doc 2022-04-27 15:49:30 +03:00
019ddbb80b TileInput fix 2022-04-27 13:35:27 +03:00
Andrey
6322b248a8 dtos fix 2022-04-27 13:27:58 +03:00
c1c47b4869 locale changes, piscreen 2022-04-27 12:41:38 +03:00
2f4e73ef13 console encoding patch 2022-04-26 22:49:31 +03:00
5ae1cfae87 Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-26 21:02:07 +03:00
5d82caf889 Merge pull request 'PIString wo pideue parent' (#91) from pistring_unparent into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/91
2022-04-26 21:01:36 +03:00
d3028a3ce8 pistring remove indexOf* 2022-04-26 21:01:20 +03:00
eef4573a68 Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-26 20:04:10 +03:00
48f3b62540 deploy_tool/main.cpp 2022-04-26 20:04:05 +03:00
Andrey
f7d6302572 fix 2022-04-26 17:20:07 +03:00
Andrey
7ad520a1c3 PIString optimization 2022-04-26 17:19:05 +03:00
Andrey
4bc12989ca Merge branch 'master' of https://git.shs.tools/SHS/pip into pistring_unparent 2022-04-26 16:59:36 +03:00
Andrey
186c71d973 linux mb test 2022-04-26 16:41:04 +03:00
Andrey
06c8e6af10 linux mb test 2022-04-26 16:30:26 +03:00
Andrey
69b9589e84 linux mb test 2022-04-26 16:03:37 +03:00
Andrey
5c767c5e3e linux mb test 2022-04-26 16:01:14 +03:00
Andrey
9cd0389a0b PIString wo pideue parent 2022-04-26 14:41:12 +03:00
Andrey
a7ffc85404 piminsleep bug and PIIODevice splitFullPath optimization 2022-04-26 14:09:59 +03:00
Andrey
2e9c3a1dbf PIString benchmarks 2022-04-26 11:53:28 +03:00
9f581335d3 version 2.37 2022-04-26 00:33:17 +03:00
e70e1c0203 pichar fix 2022-04-26 00:17:53 +03:00
cb179de856 linux PIString fix 2022-04-26 00:11:27 +03:00
0aaa5ba890 linux PIString fix 2022-04-25 23:58:38 +03:00
0cf7fb9f25 linux PIString fix 2022-04-25 23:58:06 +03:00
a304997177 linux PIString fix 2022-04-25 23:56:57 +03:00
d6ba51e4bc linux PIString fix 2022-04-25 23:44:30 +03:00
892edb7d5b linux PIString fix 2022-04-25 23:42:46 +03:00
c3cf0f3586 linux PIString fix 2022-04-25 23:41:43 +03:00
2dec17e871 linux PIString fix 2022-04-25 23:41:21 +03:00
88ffd602d6 linux PIString fix 2022-04-25 23:40:17 +03:00
a57e51bdf8 linux PIString fix 2022-04-25 23:39:33 +03:00
44c52c40f1 linux PIString fix 2022-04-25 23:38:09 +03:00
6ecd04b0d8 linux PIString fix 2022-04-25 23:37:06 +03:00
964823b332 linux PIString fix 2022-04-25 23:35:54 +03:00
ca8839f097 linux PIString fix 2022-04-25 23:34:16 +03:00
546ad6a744 linux PIString fix 2022-04-25 23:32:21 +03:00
bd9ad16074 linux PIString fix 2022-04-25 23:31:46 +03:00
23907c7043 fix appendFromChars 2022-04-25 23:06:49 +03:00
a6cea11911 PIString ICU 2022-04-25 22:54:46 +03:00
cea7a7c121 piChar mbrtowc 2022-04-25 22:15:58 +03:00
095ecd254f piChar mbrtowc 2022-04-25 22:14:42 +03:00
2246b8b5fd linux test 2022-04-25 22:01:50 +03:00
914ff5355d Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-25 21:55:14 +03:00
858269a46b linux test 2022-04-25 21:55:10 +03:00
5072d8c915 Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-25 21:44:30 +03:00
5f8c04a78e containers minimum elements, windows memory leaks 2022-04-25 21:43:57 +03:00
41fb7cc40d linux fix 2022-04-25 21:32:35 +03:00
6a399c7d39 Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-25 20:40:34 +03:00
90afc369f0 string brush 2022-04-25 15:29:27 +03:00
Andrey
765ef7368e PIString replace pibytearray by char * 2022-04-25 11:42:58 +03:00
03384d02a0 Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-24 22:11:16 +03:00
cf48c9ebf7 string ascii 2022-04-24 19:15:51 +03:00
dd3d42944e Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-23 13:59:23 +03:00
c2e44dc3ba doc fix 2022-04-23 13:59:06 +03:00
c1c324a5a8 doc 2022-04-23 12:44:09 +03:00
7f93ba55b4 doc 2022-04-23 12:37:55 +03:00
fcd871c0fc doc 2022-04-23 12:32:17 +03:00
0c54709414 doc ru 2022-04-23 11:27:07 +03:00
7a458c5cbe doc ru 2022-04-23 00:44:52 +03:00
8da0469dbf Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-22 23:24:34 +03:00
38b75c85d7 doc fix 2022-04-22 23:24:28 +03:00
833d0333d7 doc fixes 2022-04-22 22:28:43 +03:00
e67a426ff2 doc fix 2022-04-22 21:48:35 +03:00
39e4d9a73c doc ru 2022-04-22 21:19:12 +03:00
Andrey
91216c4b17 PIPair doc 2022-04-22 19:20:50 +03:00
Andrey
416b142889 Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-22 18:45:04 +03:00
Andrey
cb4df7dc42 fix PIVector and PIDeque typedefs 2022-04-22 18:44:58 +03:00
Andrey
99a4546775 ещё правки для PIVector и PIDeque iterator и убрал лишние строки 2022-04-22 17:54:08 +03:00
Andrey
8a9864a91c PIPair refactoring 2022-04-22 17:35:29 +03:00
6485d81025 piobject metasystem memory and performance optimization 2022-04-22 15:35:25 +03:00
Andrey
db54d0b052 mistake 2022-04-22 12:13:43 +03:00
Andrey
87105cff21 ещё правки документации для PIVector и PIDeque 2022-04-22 12:12:26 +03:00
Andrey
a489daa475 уменьшил количество строк 2022-04-22 11:51:19 +03:00
c476a06e8c containers doc brush 2022-04-21 22:58:24 +03:00
9deae168a6 thread doc ru 2022-04-21 22:26:49 +03:00
Andrey
93b881da1b PIDeque doc, fixes in PIVector and PIString 2022-04-21 18:25:44 +03:00
Andrey
8beaac5193 finish PIVector doc 2022-04-20 16:50:36 +03:00
Andrey
d4294e3d95 PIVector reshape... not works 2022-04-19 16:33:13 +03:00
Andrey
8c6db321cf PIDeque doc 2022-04-18 19:10:01 +03:00
Andrey
35e68bcd0e Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-18 18:16:38 +03:00
Andrey
f01ca5e5bf pivector doc 2022-04-18 18:16:26 +03:00
bef0ac1194 pip_cmg -H 2022-04-16 01:13:10 +03:00
9fa78a1dbf doc 2022-04-15 16:36:14 +03:00
4b32101de6 introspection major optimization 2022-04-15 01:31:22 +03:00
Andrey
6abec38856 Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-04-14 18:00:39 +03:00
Andrey
d22af96bea PIDeque optimization 2022-04-14 18:00:33 +03:00
139 changed files with 7950 additions and 3225 deletions

View File

@@ -2,15 +2,52 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip) project(pip)
set(pip_MAJOR 2) set(pip_MAJOR 2)
set(pip_MINOR 35) set(pip_MINOR 39)
set(pip_REVISION 0) set(pip_REVISION 0)
set(pip_SUFFIX ) set(pip_SUFFIX )
set(pip_COMPANY SHS) set(pip_COMPANY SHS)
set(pip_DOMAIN org.SHS) set(pip_DOMAIN org.SHS)
set(GIT_CMAKE_DIR)
if (NOT DEFINED SHSTKPROJECT)
set(ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cmake-download/CMakeLists.txt"
"# This file was generated by PIP CMake, don`t edit it!
cmake_minimum_required(VERSION 2.8.2)
project(cmake-download NONE)
include(ExternalProject)
ExternalProject_Add(cmake
GIT_REPOSITORY https://git.shs.tools/SHS/cmake.git
GIT_TAG \"origin/master\"
GIT_CONFIG \"advice.detachedHead=false\"
SOURCE_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cmake-src\"
BINARY_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cmake-build\"
INSTALL_COMMAND \"\"
TEST_COMMAND \"\"
)
")
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cmake-download)
if(result)
message(FATAL_ERROR "CMake step for cmake failed: ${result}")
endif()
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cmake-download)
if(result)
message(FATAL_ERROR "Build step for cmake failed: ${result}")
endif()
install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" --build \"${CMAKE_CURRENT_BINARY_DIR}/cmake-build\" --target install)")
set(GIT_CMAKE_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake-src")
endif()
if ("x${CMAKE_MODULE_PATH}" STREQUAL "x") if ("x${CMAKE_MODULE_PATH}" STREQUAL "x")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
endif() endif()
if (NOT "x${GIT_CMAKE_DIR}" STREQUAL "x")
list(APPEND CMAKE_MODULE_PATH "${GIT_CMAKE_DIR}")
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
include(CheckFunctionExists) include(CheckFunctionExists)
include(PIPMacros) include(PIPMacros)
@@ -550,6 +587,11 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
include(PIPDocumentation) include(PIPDocumentation)
find_package(Doxygen) find_package(Doxygen)
if(DOXYGEN_FOUND) if(DOXYGEN_FOUND)
set(DOXY_DEFINES "${PIP_EXPORTS}")
foreach (_m "console" "usb" "compress" "crypt" "cloud" "fftw" "opencl" "io_utils" "lua")
string(TOUPPER "${_m}" _mdef)
list(APPEND DOXY_DEFINES "PIP_${_mdef}_EXPORT")
endforeach()
set(DOXY_PROJECT_NUMBER "${pip_VERSION}") set(DOXY_PROJECT_NUMBER "${pip_VERSION}")
set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${pip_VERSION}\"") set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${pip_VERSION}\"")
set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${pip_VERSION}\"") set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${pip_VERSION}\"")
@@ -574,9 +616,9 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
foreach(F ${PIP_MAIN_FOLDERS}) foreach(F ${PIP_MAIN_FOLDERS})
list(APPEND DOXY_INPUT "\"${F}\"") list(APPEND DOXY_INPUT "\"${F}\"")
endforeach(F) endforeach(F)
string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/libs\"") string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/libs\";\"${CMAKE_CURRENT_SOURCE_DIR}/doc/pages\"")
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_INCLUDES}") string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_INCLUDES}")
string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS}") string(REPLACE ";" " " DOXY_DEFINES "${DOXY_DEFINES}")
add_documentation(doc doc/Doxyfile.in) add_documentation(doc doc/Doxyfile.in)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL)
endif() endif()

View File

@@ -3,7 +3,7 @@ void _() {
//! [0] //! [0]
class SomeIO: public PIIODevice { class SomeIO: public PIIODevice {
PIIODEVICE(SomeIO) PIIODEVICE(SomeIO, "myio")
public: public:
SomeIO(): PIIODevice() {} SomeIO(): PIIODevice() {}
protected: protected:
@@ -19,9 +19,8 @@ protected:
// write to your device here // write to your device here
return written_bytes; return written_bytes;
} }
PIString fullPathPrefix() const {return "myio";}
void configureFromFullPath(const PIString & full_path) { void configureFromFullPath(const PIString & full_path) {
// parse full_path and configure device there // parse full_path and configure device here
} }
}; };
REGISTER_DEVICE(SomeIO) REGISTER_DEVICE(SomeIO)

44
doc/pages/main.md Normal file
View File

@@ -0,0 +1,44 @@
\~english \mainpage What is PIP
\~russian \mainpage Что такое PIP
\~english
PIP - Platform-Independent Primitives - is crossplatform library for C++ developers.
This library can help developers write non-GUI projects much more quickly, efficiently
and customizable than on pure C++.
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.
Many common data types, system primitives and devices implemented in this library.
PIP also tightly integrates with [CMake](https://cmake.org/) build system, providing handly search
main library, additional modules of PIP and several utilites. With
CMake with PIP one can easily generate and use code metainformation or
serialize custom types with it versions back-compatability.
Summary one can find at \ref summary page.
Basic using of PIP described at \ref using_basic page.
\~russian
PIP - Platform-Independent Primitives - кроссплатформенная библиотека для разработчиков на C++.
Эта библиотека поможет разработчику написать неграфическое приложение быстрее, эффективнее
и более гибко, чем на чистом C++.
Приложения, написанные на PIP, работают одинаково на многих системах. Можно читать и писать
любые типы данных, сериализовать любые типы в каналы устройств между любыми системами.
Многие типы данных, системные сущности и устройства реализованы в библиотеке.
PIP также тесно интегрируется с системой сборки [CMake](https://cmake.org/), предоставляя удобный поиск
главной библиотеки, модулей PIP и некоторых утилит. Используя CMake вместе с PIP
можно генерировать и использовать метаинформация о коде или сериализовать
свои типы данных с обратной совместимостью их версий.
Сводку можно найти на странице \ref summary.
Базовое использование PIP описано на странице \ref using_basic.

104
doc/pages/summary.md Normal file
View File

@@ -0,0 +1,104 @@
\~english \page summary Functionality summary
\~russian \page summary Сводка функциональности
\~english
* direct output to console (\a PICout)
* containers (\a PIVector, \a PIDeque, \a PIVector2D, \a PIStack, \a PIQueue, \a PIMap, \a PISet)
* byte array (\a PIByteArray)
* serialization (\a PIChunkStream)
* string (\a PIConstChars, \a PIString, \a PIStringList)
* base object (events and handlers) (\a PIObject)
* multithreading
* thread (\a PIThread)
* blocking (\a PIMutex, \a PISpinlock)
* executor (\a PIThreadPoolExecutor)
* blocking dequeue (\a PIBlockingDequeue)
* timer (\a PITimer)
* tiling console (with widgets) (\a PIScreen)
* simple text rows
* scroll bar
* list
* button
* buttons group
* check box
* progress bar
* PICout output
* text input
* I/O devices
* base class (\a PIIODevice)
* file (\a PIFile)
* serial port (\a PISerial)
* ethernet (\a PIEthernet)
* USB (\a PIUSB)
* packets extractor (\a PIPacketExtractor)
* binary log (\a PIBinaryLog)
* complex I/O point (\a PIConnection)
* peering net node (\a PIPeer)
* connection quality diagnotic (\a PIDiagnostics)
* Run-time libraries
* abstract (\a PILibrary)
* plugin (\a PIPluginLoader)
* Mathematics
* complex numbers
* vectors (\a PIMathVector, \a PIMathVectorT)
* matrices (\a PIMathMatrix, \a PIMathMatrixT)
* quaternion (\a PIQuaternion)
* 2D geometry (\a PIPoint, \a PILine, \a PIRect)
* statistic (\a PIStatistic)
* CRC checksum (\a PICRC)
* Fourier transform (\a PIFFTW, \a PIFFT)
* expression evaluator (\a PIEvaluator)
* command-line arguments parser (\a PICLI)
* process (\a PIProcess)
\~russian
* общение с консолью (\a PICout)
* контейнеры (\a PIVector, \a PIDeque, \a PIVector2D, \a PIStack, \a PIQueue, \a PIMap, \a PISet)
* байтовый массив (\a PIByteArray)
* сериализация (\a PIChunkStream)
* строка (\a PIConstChars, \a PIString, \a PIStringList)
* базовый объект (события и обработчики) (\a PIObject)
* многопоточность
* поток (\a PIThread)
* блокировки (\a PIMutex, \a PISpinlock)
* исполнитель (\a PIThreadPoolExecutor)
* блокирующая очередь (\a PIBlockingDequeue)
* таймер (\a PITimer)
* тайлинговая консоль (с виджетами) (\a PIScreen)
* простой вывод строк
* скроллбар
* лист
* кнопка
* группа кнопок
* галочка
* прогрессбар
* вывод PICout
* текстовый ввод
* устройства ввода/вывода
* базовый класс (\a PIIODevice)
* файл (\a PIFile)
* последовательный порт (\a PISerial)
* ethernet (\a PIEthernet)
* USB (\a PIUSB)
* packets extractor (\a PIPacketExtractor)
* бинарный логфайл (\a PIBinaryLog)
* сложное составное устройство (\a PIConnection)
* пиринговая сеть (\a PIPeer)
* диагностика качества связи (\a PIDiagnostics)
* поддержка библиотек времени выполнения
* базовая функциональность (\a PILibrary)
* плагин (\a PIPluginLoader)
* Математика
* комплексные числа
* вектора (\a PIMathVector, \a PIMathVectorT)
* матрицы (\a PIMathMatrix, \a PIMathMatrixT)
* кватернион (\a PIQuaternion)
* 2D геометрия (\a PIPoint, \a PILine, \a PIRect)
* статистика (\a PIStatistic)
* CRC контрольная сумма (\a PICRC)
* преобразования Фурье (\a PIFFTW, \a PIFFT)
* вычислитель выражений (\a PIEvaluator)
* парсер аргументов командной строки (\a PICLI)
* процесс (\a PIProcess)

128
doc/pages/using_basic.md Normal file
View File

@@ -0,0 +1,128 @@
\~english \page using_basic Getting started
\~russian \page using_basic Простые начала
\~english
Many novice programmers are solved many common task with system integrity: output to console,
keyboard buttons press detecting, working with serial ports, ethernet or files, and many other.
These tasks can solve this library, and code, based only on PIP will be compile and work
similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX.
Typical application on PIP looks like this: \n
\~russian
Многие начинающие программисты решают общие задачи взаимодействия с операционной системой:
вывод в консоль, определение нажатия клавиш, работа с последовательными портами, сетью или файлами,
и многое другое. Эти задачи решены в библиотеке, и код, основанный на PIP будет компилироваться
и работать одинаково на многих системах: Windows, любой Linux, Red Hat, FreeBSD, MacOS X и QNX.
Типовое приложение на PIP выглядит примерно так: \n
\code{.cpp}
#include <pip.h>
// declare key press handler
void key_event(char key, void * );
PIConsole console(false, key_event); // don`t start now, key handler is "key_event"
// some vars
int i = 2, j = 3;
// implicit key press handler
void key_event(char key, void * ) {
switch (key) {
case '-':
i--;
break;
case '+':
i++;
break;
case '(':
j--;
break;
case ')':
j++;
break;
};
};
class MainClass: public PITimer {
PIOBJECT(MainClass)
public:
MainClass() {}
protected:
void tick(void * data, int delimiter) {
piCout << "timer tick";
// timer tick
}
};
MainClass main_class;
int main(int argc, char * argv[]) {
// enabling auto-detection of exit button press, by default 'Q' (shift+q)
console.enableExitCapture();
// if we want to parse command-line arguments
PICLI cli(argc, argv);
cli.addArgument("console"); // "-c" or "--console"
cli.addArgument("debug"); // "-d" or "--debug"
// enabling or disabling global debug flag
piDebug = cli.hasArgument("debug");
// configure console
console.addTab("first tab", '1');
console.addString("PIP console", 1, PIConsole::Bold);
console.addVariable("int var (i)", &i, 1);
console.addVariable("int green var (j)", &j, 1, PIConsole::Green);
console.addString("'-' - i--", 2);
console.addString("'+' - i++", 2);
console.addString("'(' - j--", 2);
console.addString("')' - j++", 2);
console.addTab("second tab", '2');
console.addString("col 1", 1);
console.addString("col 2", 2);
console.addString("col 3", 3);
console.setTab("first tab");
// start output to console if "console" argument exists
if (cli.hasArgument("console"))
console.start();
// start main class, e.g. 40 Hz
main_class.start(25.);
// wait for 'Q' press, independently if console is started or not
console.waitForFinish();
return 0;
};
\endcode
\~english
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
\a PIThread and reimplement \a run() function.
\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).
\n To configure your program from file use \a PIConfig.
\n If you want more information see \ref using_advanced
\~russian
Этот код демонстрирует простую конфигурируемую программу, которая может быть запущена с
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
\a PIThread and reimplement \a run() function.
\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).
\n To configure your program from file use \a PIConfig.

View File

@@ -219,14 +219,15 @@ void PIScreen::SystemConsole::print() {
} else { } else {
if (!s.isEmpty()) { if (!s.isEmpty()) {
moveTo(si, sj); moveTo(si, sj);
printf("%s", s.data()); PICout::stdoutPIString(s);
s.clear(); s.clear();
} }
} }
} }
if (!s.isEmpty()) { if (!s.isEmpty()) {
moveTo(si, sj); moveTo(si, sj);
printf("%s", s.data()); PICout::stdoutPIString(s);
//printf("%s", s.data());
s.clear(); s.clear();
} }
} }
@@ -295,32 +296,32 @@ void PIScreen::SystemConsole::newLine() {
} }
#else // WINDOWS #else // WINDOWS
PIString PIScreen::SystemConsole::formatString(const PIScreenTypes::Cell & c) { PIString PIScreen::SystemConsole::formatString(const PIScreenTypes::Cell & c) {
PIString ts("\e[0"); PIString ts = PIStringAscii("\e[0");
switch (c.format.color_char) { switch (c.format.color_char) {
case Black: ts += ";30"; break; case Black: ts += PIStringAscii(";30"); break;
case Red: ts += ";31"; break; case Red: ts += PIStringAscii(";31"); break;
case Green: ts += ";32"; break; case Green: ts += PIStringAscii(";32"); break;
case Blue: ts += ";34"; break; case Blue: ts += PIStringAscii(";34"); break;
case Cyan: ts += ";36"; break; case Cyan: ts += PIStringAscii(";36"); break;
case Magenta: ts += ";35"; break; case Magenta: ts += PIStringAscii(";35"); break;
case Yellow: ts += ";33"; break; case Yellow: ts += PIStringAscii(";33"); break;
case White: ts += ";37"; break; case White: ts += PIStringAscii(";37"); break;
} }
switch (c.format.color_back) { switch (c.format.color_back) {
case Black: ts += ";40"; break; case Black: ts += PIStringAscii(";40"); break;
case Red: ts += ";41"; break; case Red: ts += PIStringAscii(";41"); break;
case Green: ts += ";42"; break; case Green: ts += PIStringAscii(";42"); break;
case Blue: ts += ";44"; break; case Blue: ts += PIStringAscii(";44"); break;
case Cyan: ts += ";46"; break; case Cyan: ts += PIStringAscii(";46"); break;
case Magenta: ts += ";45"; break; case Magenta: ts += PIStringAscii(";45"); break;
case Yellow: ts += ";43"; break; case Yellow: ts += PIStringAscii(";43"); break;
case White: ts += ";47"; break; case White: ts += PIStringAscii(";47"); break;
} }
if ((c.format.flags & Bold) == Bold) ts += ";1"; if ((c.format.flags & Bold ) == Bold ) ts += PIStringAscii(";1");
if ((c.format.flags & Underline) == Underline) ts += ";4"; if ((c.format.flags & Underline) == Underline) ts += PIStringAscii(";4");
if ((c.format.flags & Blink) == Blink) ts += ";5"; if ((c.format.flags & Blink ) == Blink ) ts += PIStringAscii(";5");
if ((c.format.flags & Inverse) == Inverse) ts += ";7"; if ((c.format.flags & Inverse ) == Inverse ) ts += PIStringAscii(";7");
return ts + "m"; return ts + 'm';
} }
#endif // WINDOWS #endif // WINDOWS

View File

@@ -689,13 +689,7 @@ bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
case PIKbdListener::F12: case PIKbdListener::F12:
break; break;
default: default:
PIChar tc text.insert(cur, PIChar((ushort)key.key));
#ifdef WINDOWS
= PIChar((ushort)key.key);
#else
= PIChar::fromUTF8((char *)&(key.key));
#endif
text.insert(cur, tc);
cur++; cur++;
oo++; oo++;
if (cur - offset >= lwid - osp) offset += oo; if (cur - offset >= lwid - osp) offset += oo;

View File

@@ -812,11 +812,12 @@ bool PITerminal::initialize() {
//piCoutObj << fr << PRIVATE->fd << pty; //piCoutObj << fr << PRIVATE->fd << pty;
if (fr == 0) { if (fr == 0) {
char ** argv = new char*[2]; char ** argv = new char*[2];
argv[0] = new char[PRIVATE->shell.lengthAscii() + 1]; PIByteArray shell = PRIVATE->shell.toByteArray();
memcpy(argv[0], PRIVATE->shell.dataAscii(), PRIVATE->shell.lengthAscii()); argv[0] = new char[shell.size() + 1];
argv[0][PRIVATE->shell.lengthAscii()] = 0; memcpy(argv[0], shell.data(), shell.size());
argv[0][shell.size()] = 0;
argv[1] = 0; argv[1] = 0;
execvp(PRIVATE->shell.dataAscii(), argv); execvp(argv[0], argv);
delete[] argv[0]; delete[] argv[0];
delete[] argv; delete[] argv;
exit(0); exit(0);

View File

@@ -34,7 +34,7 @@
class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase
{ {
PIIODEVICE(PICloudClient) PIIODEVICE(PICloudClient, "")
public: public:
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudClient(); virtual ~PICloudClient();

View File

@@ -16,16 +16,16 @@
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 Cloud //! \defgroup Cloud Cloud
//! \~\brief //! \~\brief
//! \~english Cloud transport over ethernet //! \~english Cloud transport over ethernet
//! \~russian Облачный транспорт через ethernet //! \~russian Облачный транспорт через ethernet
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Cloud Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Cloud Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Cloud) //! target_link_libraries([target] PIP::Cloud)
//! \endcode //! \endcode

View File

@@ -32,14 +32,14 @@
class PIP_CLOUD_EXPORT PICloudServer: public PIIODevice, public PICloudBase class PIP_CLOUD_EXPORT PICloudServer: public PIIODevice, public PICloudBase
{ {
PIIODEVICE(PICloudServer) PIIODEVICE(PICloudServer, "")
public: public:
//! PICloudServer //! PICloudServer
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudServer(); virtual ~PICloudServer();
class Client : public PIIODevice { class Client : public PIIODevice {
PIIODEVICE(PICloudServer::Client) PIIODEVICE(PICloudServer::Client, "")
friend class PICloudServer; friend class PICloudServer;
public: public:
Client(PICloudServer * srv = nullptr, uint id = 0); Client(PICloudServer * srv = nullptr, uint id = 0);

View File

@@ -24,39 +24,39 @@
PIString PICodeInfo::EnumInfo::memberName(int value_) const { PIString PICodeInfo::EnumInfo::memberName(int value_) const {
piForeachC (PICodeInfo::EnumeratorInfo & e, members) piForeachC (PICodeInfo::EnumeratorInfo & e, members)
if (e.value == value_) if (e.value == value_)
return e.name; return e.name.toString();
return PIString(); return PIString();
} }
int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const { int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const {
piForeachC (PICodeInfo::EnumeratorInfo & e, members) piForeachC (PICodeInfo::EnumeratorInfo & e, members)
if (e.name == name_) if (e.name.toString() == name_)
return e.value; return e.value;
return -1; return -1;
} }
PIVariantTypes::Enum PICodeInfo::EnumInfo::toPIVariantEnum() { PIVariantTypes::Enum PICodeInfo::EnumInfo::toPIVariantEnum() {
PIVariantTypes::Enum en(name); PIVariantTypes::Enum en(name.toString());
for (auto m: members) en << m.toPIVariantEnumerator(); for (auto m: members) en << m.toPIVariantEnumerator();
if (!en.isEmpty()) en.selectValue(members.front().value); if (!en.isEmpty()) en.selectValue(members.front().value);
return en; return en;
} }
PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo; PIMap<PIConstChars, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo; PIMap<PIConstChars, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;
PIMap<PIString, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions; PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions;
PIMap<PIString, PICodeInfo::AccessTypeFunction> * PICodeInfo::accessTypeFunctions; PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * PICodeInfo::accessTypeFunctions;
bool __PICodeInfoInitializer__::_inited_ = false; bool __PICodeInfoInitializer__::_inited_ = false;
PIVariant PICodeInfo::getMemberAsVariant(const void * p, const char * class_name, const char * member_name) { PIVariant PICodeInfo::getMemberAsVariant(const void * p, const char * class_name, const char * member_name) {
if (!p || !class_name || !member_name || !accessTypeFunctions || !accessValueFunctions) return PIVariant(); if (!p || !class_name || !member_name || !accessTypeFunctions || !accessValueFunctions) return PIVariant();
AccessTypeFunction atf = accessTypeFunctions->value(PIStringAscii(class_name), (AccessTypeFunction)0); AccessTypeFunction atf = accessTypeFunctions->value(class_name, (AccessTypeFunction)0);
AccessValueFunction avf = accessValueFunctions->value(PIStringAscii(class_name), (AccessValueFunction)0); AccessValueFunction avf = accessValueFunctions->value(class_name, (AccessValueFunction)0);
if (!atf || !avf) return PIVariant(); if (!atf || !avf) return PIVariant();
return PIVariant::fromValue(avf(p, member_name), PIStringAscii(atf(member_name))); return PIVariant::fromValue(avf(p, member_name), PIStringAscii(atf(member_name)));
} }

View File

@@ -27,6 +27,7 @@
#ifndef PICODEINFO_H #ifndef PICODEINFO_H
#define PICODEINFO_H #define PICODEINFO_H
#include "piconstchars.h"
#include "pistringlist.h" #include "pistringlist.h"
#include "pivarianttypes.h" #include "pivarianttypes.h"
@@ -52,18 +53,18 @@ typedef PIByteArray(*AccessValueFunction)(const void *, const char *);
typedef const char*(*AccessTypeFunction)(const char *); typedef const char*(*AccessTypeFunction)(const char *);
struct PIP_EXPORT TypeInfo { struct PIP_EXPORT TypeInfo {
TypeInfo(const PIString & n = PIString(), const PIString & t = PIString(), PICodeInfo::TypeFlags f = 0, int b = -1) {name = n; type = t; flags = f; bits = b;} TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {name = n; type = t; flags = f; bits = b;}
bool isBitfield() const {return bits > 0;} bool isBitfield() const {return bits > 0;}
MetaMap meta; MetaMap meta;
PIString name; PIConstChars name;
PIString type; PIConstChars type;
PICodeInfo::TypeFlags flags; PICodeInfo::TypeFlags flags;
int bits; int bits;
}; };
struct PIP_EXPORT FunctionInfo { struct PIP_EXPORT FunctionInfo {
MetaMap meta; MetaMap meta;
PIString name; PIConstChars name;
TypeInfo return_type; TypeInfo return_type;
PIVector<PICodeInfo::TypeInfo> arguments; PIVector<PICodeInfo::TypeInfo> arguments;
}; };
@@ -72,19 +73,19 @@ struct PIP_EXPORT ClassInfo {
ClassInfo() {has_name = true;} ClassInfo() {has_name = true;}
MetaMap meta; MetaMap meta;
bool has_name; bool has_name;
PIString type; PIConstChars type;
PIString name; PIConstChars name;
PIStringList parents; PIVector<PIConstChars> parents;
PIVector<PICodeInfo::TypeInfo> variables; PIVector<PICodeInfo::TypeInfo> variables;
PIVector<PICodeInfo::FunctionInfo> functions; PIVector<PICodeInfo::FunctionInfo> functions;
PIVector<PICodeInfo::ClassInfo * > children_info; PIVector<PICodeInfo::ClassInfo * > children_info;
}; };
struct PIP_EXPORT EnumeratorInfo { struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;} EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {name = n; value = v;}
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name);} PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name.toString());}
MetaMap meta; MetaMap meta;
PIString name; PIConstChars name;
int value; int value;
}; };
@@ -93,7 +94,7 @@ struct PIP_EXPORT EnumInfo {
int memberValue(const PIString & name) const; int memberValue(const PIString & name) const;
PIVariantTypes::Enum toPIVariantEnum(); PIVariantTypes::Enum toPIVariantEnum();
MetaMap meta; MetaMap meta;
PIString name; PIConstChars name;
PIVector<PICodeInfo::EnumeratorInfo> members; PIVector<PICodeInfo::EnumeratorInfo> members;
}; };
@@ -119,17 +120,17 @@ inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
if (!v.parents.isEmpty()) { if (!v.parents.isEmpty()) {
s << ": "; s << ": ";
bool first = true; bool first = true;
piForeachC (PIString & i, v.parents) { for (const auto & i: v.parents) {
if (first) first = false; if (first) first = false;
else s << ", "; else s << ", ";
s << i; s << i;
} }
} }
s << " Meta" << v.meta << " {\n"; s << " Meta" << v.meta << " {\n";
piForeachC (FunctionInfo & i, v.functions) { for (const auto & i: v.functions) {
s << PICoutManipulators::Tab << i.return_type << " " << i.name << "("; s << PICoutManipulators::Tab << i.return_type << " " << i.name << "(";
bool fa = true; bool fa = true;
piForeachC (TypeInfo & a, i.arguments) { for (const auto & a: i.arguments) {
if (fa) fa = false; if (fa) fa = false;
else s << ", "; else s << ", ";
s << a; s << a;
@@ -138,7 +139,7 @@ inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
} }
if (!v.functions.isEmpty() && !v.variables.isEmpty()) if (!v.functions.isEmpty() && !v.variables.isEmpty())
s << "\n"; s << "\n";
piForeachC (TypeInfo & i, v.variables) { for (const auto & i: v.variables) {
s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n"; s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n";
} }
s << "}\n"; s << "}\n";
@@ -149,7 +150,7 @@ inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) { inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
s.setControl(0, true); s.setControl(0, true);
s << "enum " << v.name << " Meta" << v.meta << " {\n"; s << "enum " << v.name << " Meta" << v.meta << " {\n";
piForeachC (EnumeratorInfo & i, v.members) { for (const auto & i: v.members) {
bool f = true; bool f = true;
if (f) f = false; if (f) f = false;
else s << ", "; else s << ", ";
@@ -160,21 +161,21 @@ inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
return s; return s;
} }
extern PIP_EXPORT PIMap<PIString, PICodeInfo::ClassInfo * > * classesInfo; extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::ClassInfo * > * classesInfo;
extern PIP_EXPORT PIMap<PIString, PICodeInfo::EnumInfo * > * enumsInfo; extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::EnumInfo * > * enumsInfo;
extern PIP_EXPORT PIMap<PIString, PICodeInfo::AccessValueFunction> * accessValueFunctions; extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
extern PIP_EXPORT PIMap<PIString, PICodeInfo::AccessTypeFunction> * accessTypeFunctions; extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
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 || !accessValueFunctions) return PIByteArray(); if (!p || !class_name || !member_name || !accessValueFunctions) return PIByteArray();
AccessValueFunction af = accessValueFunctions->value(PIStringAscii(class_name), (AccessValueFunction)0); AccessValueFunction af = accessValueFunctions->value(class_name, (AccessValueFunction)0);
if (!af) return PIByteArray(); if (!af) return PIByteArray();
return af(p, member_name); return af(p, member_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 || !accessTypeFunctions) return ""; if (!class_name || !member_name || !accessTypeFunctions) return "";
AccessTypeFunction af = accessTypeFunctions->value(PIStringAscii(class_name), (AccessTypeFunction)0); AccessTypeFunction af = accessTypeFunctions->value(class_name, (AccessTypeFunction)0);
if (!af) return ""; if (!af) return "";
return af(member_name); return af(member_name);
} }
@@ -195,10 +196,10 @@ public:
__PICodeInfoInitializer__() { __PICodeInfoInitializer__() {
if (_inited_) return; if (_inited_) return;
_inited_ = true; _inited_ = true;
PICodeInfo::classesInfo = new PIMap<PIString, PICodeInfo::ClassInfo * >; PICodeInfo::classesInfo = new PIMap<PIConstChars, PICodeInfo::ClassInfo * >;
PICodeInfo::enumsInfo = new PIMap<PIString, PICodeInfo::EnumInfo * >; PICodeInfo::enumsInfo = new PIMap<PIConstChars, PICodeInfo::EnumInfo * >;
PICodeInfo::accessValueFunctions = new PIMap<PIString, PICodeInfo::AccessValueFunction>; PICodeInfo::accessValueFunctions = new PIMap<PIConstChars, PICodeInfo::AccessValueFunction>;
PICodeInfo::accessTypeFunctions = new PIMap<PIString, PICodeInfo::AccessTypeFunction>; PICodeInfo::accessTypeFunctions = new PIMap<PIConstChars, PICodeInfo::AccessTypeFunction>;
} }
static bool _inited_; static bool _inited_;
}; };

View File

@@ -16,16 +16,16 @@
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 Code //! \defgroup Code Code
//! \~\brief //! \~\brief
//! \~english C++ code parsing //! \~english C++ code parsing
//! \~russian Разбор C++ кода //! \~russian Разбор C++ кода
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Code Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Code Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP) //! target_link_libraries([target] PIP)
//! \endcode //! \endcode

View File

@@ -321,7 +321,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
PIString prev_namespace = cur_namespace, ccmn; PIString prev_namespace = cur_namespace, ccmn;
cur_namespace += pfc.takeCWord() + s_ns; cur_namespace += pfc.takeCWord() + s_ns;
ccmn = pfc.takeRange('{', '}'); ccmn = pfc.takeRange('{', '}');
parseClass(0, ccmn); parseClass(0, ccmn, true);
cur_namespace = prev_namespace; cur_namespace = prev_namespace;
continue; continue;
} }
@@ -340,7 +340,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;} if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;}
ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc; ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
pfc.remove(0, ccmn.size()); pfc.remove(0, ccmn.size());
parseClass(0, ccmn); parseClass(0, ccmn, false);
continue; continue;
} }
if (pfc.left(4) == s_enum) { if (pfc.left(4) == s_enum) {
@@ -425,7 +425,7 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
} }
PIString PICodeParser::parseClass(Entity * parent, PIString & fc) { void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace) {
static const PIString s_ns = PIStringAscii("::"); static const PIString s_ns = PIStringAscii("::");
static const PIString s_public = PIStringAscii("public"); static const PIString s_public = PIStringAscii("public");
static const PIString s_protected = PIStringAscii("protected"); static const PIString s_protected = PIStringAscii("protected");
@@ -436,22 +436,31 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
static const PIString s_enum = PIStringAscii("enum"); static const PIString s_enum = PIStringAscii("enum");
static const PIString s_friend = PIStringAscii("friend"); static const PIString s_friend = PIStringAscii("friend");
static const PIString s_typedef = PIStringAscii("typedef"); static const PIString s_typedef = PIStringAscii("typedef");
static const PIString s_namespace = PIStringAscii("namespace");
static const PIString s_template = PIStringAscii("template"); static const PIString s_template = PIStringAscii("template");
Visibility prev_vis = cur_def_vis; Visibility prev_vis = cur_def_vis;
int dind = fc.find('{'), find = fc.find(';'), end = 0; int dind = fc.find('{'), find = fc.find(';'), end = 0;
if (dind < 0 && find < 0) return PIString(); if (dind < 0 && find < 0) return;
if (dind < 0 || find < dind) return fc.left(find); if (dind < 0 || find < dind) {
//piCout << "parse class <****\n" << fc.left(20) << "\n****>"; fc.left(find);
Entity * ce = parseClassDeclaration(fc.takeLeft(dind)); return;
}
//piCout << "parse class <****\n" << fc << "\n****>";
Entity * ce = parent;
if (!is_namespace) {
ce = parseClassDeclaration(fc.takeLeft(dind));
fc.trim().cutLeft(1).cutRight(1).trim(); fc.trim().cutLeft(1).cutRight(1).trim();
}
//piCout << "found class <****\n" << fc << "\n****>"; //piCout << "found class <****\n" << fc << "\n****>";
if (!ce) return PIString(); ///if (!ce) return PIString();
if (ce) {
if (parent) parent->children << ce; if (parent) parent->children << ce;
ce->parent_scope = parent; ce->parent_scope = parent;
}
int ps = -1; int ps = -1;
bool def = false; bool def = false;
PIString prev_namespace = cur_namespace, stmp; PIString prev_namespace = cur_namespace, stmp;
cur_namespace += ce->name + s_ns; if (ce) cur_namespace += ce->name + s_ns;
//piCout << "parse class" << ce->name << "namespace" << cur_namespace; //piCout << "parse class" << ce->name << "namespace" << cur_namespace;
//piCout << "\nparse class" << ce->name << "namespace" << cur_namespace; //piCout << "\nparse class" << ce->name << "namespace" << cur_namespace;
while (!fc.isEmpty()) { while (!fc.isEmpty()) {
@@ -460,6 +469,14 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
if (cw == s_public ) {cur_def_vis = Public; fc.cutLeft(1); continue;} if (cw == s_public ) {cur_def_vis = Public; fc.cutLeft(1); continue;}
if (cw == s_protected) {cur_def_vis = Protected; fc.cutLeft(1); continue;} if (cw == s_protected) {cur_def_vis = Protected; fc.cutLeft(1); continue;}
if (cw == s_private ) {cur_def_vis = Private; fc.cutLeft(1); continue;} if (cw == s_private ) {cur_def_vis = Private; fc.cutLeft(1); continue;}
if (cw == s_namespace) {
PIString prev_namespace = cur_namespace, ccmn;
cur_namespace += fc.takeCWord() + s_ns;
ccmn = fc.takeRange('{', '}');
parseClass(ce, ccmn, true);
cur_namespace = prev_namespace;
continue;
}
if (cw == s_class || cw == s_struct || cw == s_union) { if (cw == s_class || cw == s_struct || cw == s_union) {
if (isDeclaration(fc, 0, &end)) { if (isDeclaration(fc, 0, &end)) {
fc.cutLeft(end); fc.cutLeft(end);
@@ -470,7 +487,7 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
stmp = fc.takeRange('{', '}'); stmp = fc.takeRange('{', '}');
fc.takeSymbol(); fc.takeSymbol();
stmp = cw + ' ' + tmp + '{' + stmp + '}'; stmp = cw + ' ' + tmp + '{' + stmp + '}';
parseClass(ce, stmp); parseClass(ce, stmp, false);
continue; continue;
} }
if (cw == s_enum) { if (cw == s_enum) {
@@ -483,11 +500,13 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
} }
if (cw == s_friend) {fc.cutLeft(fc.find(';') + 1); continue;} if (cw == s_friend) {fc.cutLeft(fc.find(';') + 1); continue;}
if (cw == s_typedef) { if (cw == s_typedef) {
if (ce) {
ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';'))); ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';')));
typedefs << ce->typedefs.back(); typedefs << ce->typedefs.back();
typedefs.back().first.insert(0, cur_namespace); typedefs.back().first.insert(0, cur_namespace);
if (ce->typedefs.back().first.isEmpty()) if (ce->typedefs.back().first.isEmpty())
ce->typedefs.pop_back(); ce->typedefs.pop_back();
}
fc.takeSymbol(); fc.takeSymbol();
continue; continue;
} }
@@ -501,7 +520,7 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
} }
def = !isDeclaration(fc, 0, &end); def = !isDeclaration(fc, 0, &end);
tmp = (cw + fc.takeLeft(end)).trim(); tmp = (cw + fc.takeLeft(end)).trim();
if (!tmp.isEmpty()) if (!tmp.isEmpty() && ce)
parseMember(ce, tmp); parseMember(ce, tmp);
if (def) fc.takeRange('{', '}'); if (def) fc.takeRange('{', '}');
else fc.takeSymbol(); else fc.takeSymbol();
@@ -510,7 +529,6 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
} }
cur_def_vis = prev_vis; cur_def_vis = prev_vis;
cur_namespace = prev_namespace; cur_namespace = prev_namespace;
return ce->name;
} }

View File

@@ -151,7 +151,7 @@ private:
bool parseFileContent(PIString & fc, bool main); bool parseFileContent(PIString & fc, bool main);
bool parseDirective(PIString d); bool parseDirective(PIString d);
Entity * parseClassDeclaration(const PIString & fc); Entity * parseClassDeclaration(const PIString & fc);
PIString parseClass(Entity * parent, PIString & fc); void parseClass(Entity * parent, PIString & fc, bool is_namespace);
MetaMap parseMeta(PIString & fc); MetaMap parseMeta(PIString & fc);
bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta); bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta);
Typedef parseTypedef(PIString fc); Typedef parseTypedef(PIString fc);

View File

@@ -23,16 +23,16 @@
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 Compress //! \defgroup Compress Compress
//! \~\brief //! \~\brief
//! \~english Compression support //! \~english Compression support
//! \~russian Поддержка сжатия //! \~russian Поддержка сжатия
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Compress Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Compress Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Compress) //! target_link_libraries([target] PIP::Compress)
//! \endcode //! \endcode

View File

@@ -16,16 +16,16 @@
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 Console //! \defgroup Console Console
//! \~\brief //! \~\brief
//! \~english Console graphic //! \~english Console graphic
//! \~russian Графика в консоли //! \~russian Графика в консоли
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Console Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Console Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Console) //! target_link_libraries([target] PIP::Console)
//! \endcode //! \endcode

View File

@@ -323,12 +323,18 @@ void PIKbdListener::readKeyboard() {
for (int i = 0; i < PRIVATE->ret; ++i) for (int i = 0; i < PRIVATE->ret; ++i)
PICout(0) << PICoutManipulators::Hex << int(((uchar * )&rc)[i]) << ' '; PICout(0) << PICoutManipulators::Hex << int(((uchar * )&rc)[i]) << ' ';
PICout(0) << "\n"; PICout(0) << "\n";
std::cout << PRIVATE->ret << " chars ";
for (int i = 0; i < PRIVATE->ret; ++i) for (int i = 0; i < PRIVATE->ret; ++i)
cout << "'" << (char)(rc[i]) << "' "; std::cout << "'" << (char)(rc[i]) << "' " << (int)(uchar)(rc[i]);
cout << endl;*/ std::cout << std::endl;*/
if (rc[0] == 0) {piMSleep(10); return;} if (rc[0] == 0) {piMSleep(10); return;}
if (PRIVATE->ret < 0 || PRIVATE->ret > 7) {piMSleep(10); return;} if (PRIVATE->ret < 0 || PRIVATE->ret > 7) {piMSleep(10); return;}
if (PRIVATE->ret == 1) ke.key = PIChar::fromConsole(rc[0]).unicode16Code(); if (PRIVATE->ret == 1) {
if (rc[0] == 8)
ke.key = Backspace;
else
ke.key = PIChar::fromConsole(rc[0]).unicode16Code();
}
int mod(0); int mod(0);
// 2 - shift 1 // 2 - shift 1
// 3 - alt 2 // 3 - alt 2

View File

@@ -0,0 +1,34 @@
/*
PIP - Platform Independent Primitives
Base macros for generic containers
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is 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 "picontainers.h"
const ssize_t minAlloc = 64;
ssize_t _PIContainerConstantsBase::calcMinCountPoT(ssize_t szof) {
ssize_t ret = 0, elc = 1;
while (elc * szof < minAlloc) {
elc *= 2;
++ret;
}
//printf("calcMinCount sizeof = %d, min_count = %d, pot = %d\n", szof, elc, ret);
return ret;
}

View File

@@ -63,6 +63,18 @@ private:
}; };
class PIP_EXPORT _PIContainerConstantsBase {
public:
static ssize_t calcMinCountPoT(ssize_t szof);
};
template<typename T>
class _PIContainerConstants {
public:
static ssize_t minCountPoT() {static ssize_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
};
//! \brief //! \brief
//! \~english Template reverse wrapper over any container //! \~english Template reverse wrapper over any container
//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы //! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
@@ -159,4 +171,14 @@ template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _P
#define piForeachRC(i, c) for(const i : PIReverseWrap(c)) #define piForeachRC(i, c) for(const i : PIReverseWrap(c))
#define piForeachCR piForeachRC #define piForeachCR piForeachRC
//! \~\brief
//! \~english Reshape order enum for reshape() function.
//! \~russian Порядок обхода для функции изменения размерности reshape().
//! \~ \sa \a PIVector::reshape(), \a PIDeque::reshape()
enum ReshapeOrder {
ReshapeByRow /*! \~english Traversing elements by line, just as they stay in memory \~russian Обход элементов построчно, так же как они находятся в памяти */,
ReshapeByColumn /*! \~english Traversing elements by column \~russian Обход элементов по столбцам */,
};
#endif // PICONTAINERS_H #endif // PICONTAINERS_H

View File

@@ -16,14 +16,14 @@
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 Containers //! \defgroup Containers Containers
//! \~\brief //! \~\brief
//! \~english Various standart containers realization //! \~english Various standart containers realization
//! \~russian Различные классы контейнеров //! \~russian Различные классы контейнеров
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Containers Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Containers Сборка с использованием CMake
//! //!
//! \~\code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)

View File

@@ -1,8 +1,17 @@
/*! \file pideque.h //! \addtogroup Containers
* \brief Dynamic array of any type //! \{
* //! \file pideque.h
* This file declares PIDeque //! \brief
*/ //! \~english Declares \a PIDeque
//! \~russian Объявление \a PIDeque
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Dynamic array of any type Dynamic array of any type
@@ -28,41 +37,165 @@
#include "picontainers.h" #include "picontainers.h"
//! \addtogroup Containers
//! \{
//! \class PIDeque
//! \brief
//! \~english Sequence two-way linear container - dynamic size array of any type.
//! \~russian Последовательный двухсторонний контейнер с линейной памятью - динамический массив любого типа.
//! \~\}
//! \details
//! \~english
//! The elements are stored contiguously,
//! which means that elements can be accessed not only through iterators,
//! but also using offsets to regular pointers to elements.
//! This means that a pointer to an element of a PIDeque may be passed to any function
//! that expects a pointer to an element of an array.
//! To add elements you can use functions \a append() and \a insert(),
//! to remove elements you can use functions \a remove() and \a removeOne(), \a removeWhere().
//! Change size by function \a resize() and \a assign().
//! Items in an array are numbered, starting from zero.
//! This number is called the item's index.
//! So the first item has index 0, the last has index `size() - 1`.
//! A set of various convenient functions is also available for the array,
//! for example: \a indexOf(), \a contains(), \a entries(), \a isEmpty(), \a isNotEmpty(),
//! \a every(), \a any(), \a forEach(), \a indexWhere(), \a getRange(), \a sort(),
//! \a map(), \a reduce(), \a filter(), \a flatten(), \a reshape() and others.
//!
//! The storage of the PIDeque is handled automatically,
//! being expanded as needed.
//! PIDeque usually occupy more space than \a PIVector,
//! because more memory is allocated to handle future growth
//! from both the beginning and the end.
//! This way a PIDeque does not need to reallocate each time an element is inserted,
//! but only when the additional memory is exhausted.
//! The total amount of allocated memory can be queried using \a capacity() function.
//! Reallocations are usually costly operations in terms of performance.
//! The \a reserve() function can be used to eliminate reallocations
//! if the number of elements is known beforehand.
//!
//! The complexity (efficiency) of common operations on PIDeque is as follows:
//! - Random access - constant 𝓞(1)
//! - Insertion or removal of elements at the end or begin - amortized constant 𝓞(1)
//! - Insertion or removal of elements - linear in the distance to the end of the array 𝓞(n)
//!
//! \~russian
//! Элементы хранятся непрерывно, а значит доступны не только через итераторы,
//! но и с помощью смещений для обычных указателей на элементы.
//! Это означает, что указатель на элемент PIDeque может передаваться в любую функцию,
//! ожидающую указатель на элемент массива.
//! Добавить элементы можно с помощью функции \a append() или \a insert(),
//! а удалить с помощью \a remove() или \a removeOne(), \a removeWhere().
//! Изменить размер можно функцией \a resize() или \a assign().
//! Массив индексируется с нуля:
//! первый элемент массива имеет индекс, равный `0`,
//! а индекс последнего элемента равен `size() - 1`.
//! Также для массива доступен набор различных удобных функций,
//! например: \a indexOf(), \a contains(), \a entries(), \a isEmpty(), \a isNotEmpty(),
//! \a every(), \a any(), \a forEach(), \a indexWhere(), \a getRange(), \a sort(),
//! \a map(), \a reduce(), \a filter(), \a flatten(), \a reshape() и другие.
//!
//! Память PIDeque обрабатывается автоматически,
//! расширяясь по мере необходимости.
//! PIDeque занимает больше места, чем \a PIVector, поскольку
//! больше памяти выделяется для обработки будущего роста и с начала и с конца.
//! Таким образом, память для PIDeque требуется выделять
//! не при каждой вставке элемента, а только после исчерпания дополнительной памяти.
//! Общий объём выделенной памяти можно получить с помощью функции \a capacity().
//!
//! Выделение памяти обычно является дорогостоящей операцией
//! с точки зрения производительности.
//! Функцию \a reserve() можно использовать для исключения выделения памяти,
//! если количество элементов известно заранее.
//!
//! Сложность (эффективность) обычных операций над PIDeque следующая:
//! - Произвольный доступ — постоянная 𝓞(1)
//! - Вставка и удаление элементов в конце или начале — амортизированная постоянная 𝓞(1)
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива 𝓞(n)
//!
//! \~\sa \a PIVector, \a PIMap
template <typename T> template <typename T>
class PIDeque { class PIDeque {
public: public:
typedef bool (*CompareFunc)(const T & , const T & ); typedef bool (*CompareFunc)(const T & , const T & );
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
//! \~english Constructs an empty array.
//! \~russian Создает пустой массив.
inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
} }
//! \~english Copy constructor.
//! \~russian Копирующий конструктор.
inline PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(other.pid_size, true); alloc_forward(other.pid_size);
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
} }
//! \~english Contructs array from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Создает массив из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\details
//! \~\code
//! PIDeque <int> v{1,2,3};
//! piCout << v; // {1, 2, 3}
//! \endcode
inline PIDeque(std::initializer_list<T> init_list): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(std::initializer_list<T> init_list): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(init_list.size(), true); alloc_forward(init_list.size());
newT(pid_data, init_list.begin(), init_list.size()); newT(pid_data, init_list.begin(), init_list.size());
} }
//! \~english Contructs array from raw `data`.
//! This constructor reserve `size` and copy from `data` pointer.
//! \~russian Создает массив из указателя на данные `data` и размер `size`.
//! То есть выделяет память для `size` элементов и копирует данные из указателя `data`.
inline PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(size, true); alloc_forward(size);
newT(pid_data + pid_start, data, pid_size); newT(pid_data + pid_start, data, pid_size);
} }
inline PIDeque(size_t pid_size, const T & f = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
//! \~english Contructs array with size `size` filled elements `e`.
//! \~russian Создает массив из `size` элементов заполненных `e`.
inline PIDeque(size_t pid_size, const T & e = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(pid_size, f); resize(pid_size, e);
} }
//! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
//! \~russian Создает массив из `size` элементов созданных функцией `f(size_t i)`.
//! \~\details
//! \~english Can use
//! [Lambda expressions](https://en.cppreference.com/w/cpp/language/lambda)
//! as constructor argument.
//! \~russian Позволяет передавать
//! [Лямбда-выражения](https://ru.cppreference.com/w/cpp/language/lambda)
//! для создания элементов в конструкторе.
//! \~\code
//! PIDeque <int> v(5, [](size_t i){return i*2;});
//! piCout << v; // {0, 2, 4, 6, 8}
//! \endcode
inline PIDeque(size_t piv_size, std::function<T(size_t i)> f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { inline PIDeque(size_t piv_size, std::function<T(size_t i)> f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(piv_size, f); resize(piv_size, f);
} }
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
inline PIDeque(PIDeque<T> && other): pid_data(other.pid_data), pid_size(other.pid_size), pid_rsize(other.pid_rsize), pid_start(other.pid_start) { inline PIDeque(PIDeque<T> && other): pid_data(other.pid_data), pid_size(other.pid_size), pid_rsize(other.pid_rsize), pid_start(other.pid_start) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
other._reset(); other._reset();
} }
inline virtual ~PIDeque() { inline virtual ~PIDeque() {
PIINTROSPECTION_CONTAINER_DELETE(T) PIINTROSPECTION_CONTAINER_DELETE(T)
PIINTROSPECTION_CONTAINER_FREE(T, (pid_rsize)) PIINTROSPECTION_CONTAINER_FREE(T, (pid_rsize))
@@ -71,26 +204,23 @@ public:
_reset(); _reset();
} }
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIDeque<T> & operator =(const PIDeque<T> & other) { inline PIDeque<T> & operator =(const PIDeque<T> & other) {
if (this == &other) return *this; if (this == &other) return *this;
deleteT(pid_data + pid_start, pid_size); deleteT(pid_data + pid_start, pid_size);
alloc(other.pid_size, true); alloc_forward(other.pid_size);
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
return *this; return *this;
} }
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIDeque<T> & operator =(PIDeque<T> && other) { inline PIDeque<T> & operator =(PIDeque<T> && other) {
swap(other); swap(other);
return *this; return *this;
} }
typedef T value_type;
enum ReshapeOrder {
byRow,
byColumn
};
class iterator { class iterator {
friend class PIDeque<T>; friend class PIDeque<T>;
private: private:
@@ -111,29 +241,73 @@ public:
inline T & operator ->() {return (*parent)[pos];} inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline iterator & operator ++() {++pos; return *this;} inline iterator & operator ++() {
inline iterator & operator ++(int) {const auto tmp = *this; ++*this; return tmp;} ++pos;
inline iterator & operator --() {--pos; return *this;} return *this;
inline iterator & operator --(int) {const auto tmp = *this; --*this; return tmp;} }
inline iterator operator ++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline iterator & operator --() {
--pos;
return *this;
}
inline iterator operator --(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline iterator & operator +=(const iterator & it) {pos += it.pos; return *this;} inline iterator & operator +=(const iterator & it) {
inline iterator & operator +=(size_t p) {pos += p; return *this;} pos += it.pos;
inline iterator & operator -=(const iterator & it) {pos -= it.pos; return *this;} return *this;
inline iterator & operator -=(size_t p) {pos -= p; return *this;} }
inline iterator & operator +=(size_t p) {
pos += p;
return *this;
}
inline iterator & operator -=(const iterator & it) {
pos -= it.pos;
return *this;
}
inline iterator & operator -=(size_t p) {
pos -= p;
return *this;
}
friend inline iterator operator -(const iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
friend inline iterator operator -(size_t p, const iterator & it) {return it - p;} friend inline iterator operator -(size_t p, const iterator & it) {return it - p;}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {return it1.pos - it2.pos;} friend inline iterator operator -(const iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
return it1.pos - it2.pos;
}
friend inline iterator operator +(const iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;} friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
friend inline iterator operator +(const iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const iterator & it) const {return (pos == it.pos);} inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const iterator & it) const {return (pos != it.pos);} inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const iterator & it1, const iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const iterator & it1, const iterator & it2) {
friend inline bool operator <=(const iterator & it1, const iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const iterator & it1, const iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const iterator & it1, const iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const iterator & it1, const iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const iterator & it1, const iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const iterator & it1, const iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
class const_iterator { class const_iterator {
@@ -154,29 +328,73 @@ public:
inline const T & operator *() const {return (*parent)[pos];} inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline const_iterator & operator ++() {++pos; return *this;} inline const_iterator & operator ++() {
inline const_iterator & operator ++(int) {const auto tmp = *this; ++*this; return tmp;} ++pos;
inline const_iterator & operator --() {--pos; return *this;} return *this;
inline const_iterator & operator --(int) {const auto tmp = *this; --*this; return tmp;} }
inline const_iterator operator ++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_iterator & operator --() {
--pos;
return *this;
}
inline const_iterator operator --(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_iterator & operator +=(const const_iterator & it) {pos += it.pos; return *this;} inline const_iterator & operator +=(const const_iterator & it) {
inline const_iterator & operator +=(size_t p) {pos += p; return *this;} pos += it.pos;
inline const_iterator & operator -=(const const_iterator & it) {pos -= it.pos; return *this;} return *this;
inline const_iterator & operator -=(size_t p) {pos -= p; return *this;} }
inline const_iterator & operator +=(size_t p) {
pos += p;
return *this;
}
inline const_iterator & operator -=(const const_iterator & it) {
pos -= it.pos;
return *this;
}
inline const_iterator & operator -=(size_t p) {
pos -= p;
return *this;
}
friend inline const_iterator operator -(const const_iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
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;}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {return it1.pos - it2.pos;} friend inline const_iterator operator -(const const_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
return it1.pos - it2.pos;
}
friend inline const_iterator operator +(const const_iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
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;}
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);} inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);} inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {
friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
class reverse_iterator { class reverse_iterator {
@@ -199,29 +417,73 @@ public:
inline T & operator ->() {return (*parent)[pos];} inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline reverse_iterator & operator ++() {--pos; return *this;} inline reverse_iterator & operator ++() {
inline reverse_iterator & operator ++(int) {const auto tmp = *this; --*this; return tmp;} --pos;
inline reverse_iterator & operator --() {++pos; return *this;} return *this;
inline reverse_iterator & operator --(int) {const auto tmp = *this; ++*this; return tmp;} }
inline reverse_iterator operator ++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline reverse_iterator & operator --() {
++pos;
return *this;
}
inline reverse_iterator operator --(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline reverse_iterator & operator +=(const reverse_iterator & it) {pos -= it.pos; return *this;} inline reverse_iterator & operator +=(const reverse_iterator & it) {
inline reverse_iterator & operator +=(size_t p) {pos -= p; return *this;} pos -= it.pos;
inline reverse_iterator & operator -=(const reverse_iterator & it) {pos += it.pos; return *this;} return *this;
inline reverse_iterator & operator -=(size_t p) {pos += p; return *this;} }
inline reverse_iterator & operator +=(size_t p) {
pos -= p;
return *this;
}
inline reverse_iterator & operator -=(const reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline reverse_iterator & operator -=(size_t p) {
pos += p;
return *this;
}
friend inline reverse_iterator operator -(const reverse_iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
friend inline reverse_iterator operator -(size_t p, const reverse_iterator & it) {return it - p;} friend inline reverse_iterator operator -(size_t p, const reverse_iterator & it) {return it - p;}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {return it2.pos - it1.pos;} friend inline reverse_iterator operator -(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;} friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {
friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
class const_reverse_iterator { class const_reverse_iterator {
@@ -241,53 +503,216 @@ public:
inline const T & operator *() const {return (*parent)[pos];} inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline const_reverse_iterator & operator ++() {--pos; return *this;} inline const_reverse_iterator & operator ++() {
inline const_reverse_iterator & operator ++(int) {const auto tmp = *this; --*this; return tmp;} --pos;
inline const_reverse_iterator & operator --() {++pos; return *this;} return *this;
inline const_reverse_iterator & operator --(int) {const auto tmp = *this; ++*this; return tmp;} }
inline const_reverse_iterator operator ++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_reverse_iterator & operator --() {
++pos;
return *this;
}
inline const_reverse_iterator operator --(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_reverse_iterator & operator +=(const const_reverse_iterator & it) {pos -= it.pos; return *this;} inline const_reverse_iterator & operator +=(const const_reverse_iterator & it) {
inline const_reverse_iterator & operator +=(size_t p) {pos -= p; return *this;} pos -= it.pos;
inline const_reverse_iterator & operator -=(const const_reverse_iterator & it) {pos += it.pos; return *this;} return *this;
inline const_reverse_iterator & operator -=(size_t p) {pos += p; return *this;} }
inline const_reverse_iterator & operator +=(size_t p) {
pos -= p;
return *this;
}
inline const_reverse_iterator & operator -=(const const_reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline const_reverse_iterator & operator -=(size_t p) {
pos += p;
return *this;
}
friend inline const_reverse_iterator operator -(const const_reverse_iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
friend inline const_reverse_iterator operator -(size_t p, const const_reverse_iterator & it) {return it - p;} friend inline const_reverse_iterator operator -(size_t p, const const_reverse_iterator & it) {return it - p;}
friend inline std::ptrdiff_t operator -(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it2.pos - it1.pos;} friend inline const_reverse_iterator operator -(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline const_reverse_iterator operator +(const const_reverse_iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
friend inline const_reverse_iterator operator +(size_t p, const const_reverse_iterator & it) {return it + p;} friend inline const_reverse_iterator operator +(size_t p, const const_reverse_iterator & it) {return it + p;}
friend inline const_reverse_iterator operator +(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
//! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент.
//! \~\details ![begin, end](doc/images/pivector_begin.png)
//!
//! \~english If the array is empty, the returned iterator is equal to \a end().
//! \~russian Если массив - пуст, возвращаемый итератор будет равен \a end().
//! \~\return \ref stl_iterators
//! \~\sa \a end(), \a rbegin(), \a rend()
inline iterator begin() {return iterator(this, 0);} inline iterator begin() {return iterator(this, 0);}
//! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
//! \~\details ![begin, end](doc/images/pivector_begin.png)
//!
//! \~english This element acts as a placeholder;
//! attempting to access it results in undefined behavior.
//! \~russian Этот элемент существует лишь условно,
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a begin(), \a rbegin(), \a rend()
inline iterator end() {return iterator(this, pid_size);} inline iterator end() {return iterator(this, pid_size);}
inline const_iterator begin() const {return const_iterator(this, 0); } inline const_iterator begin() const {return const_iterator(this, 0); }
inline const_iterator end() const {return const_iterator(this, pid_size);} inline const_iterator end() const {return const_iterator(this, pid_size);}
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
//! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png)
//!
//! \~english It corresponds to the last element of the non-reversed array.
//! If the array is empty, the returned iterator is equal to \a rend().
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на последний элемент.
//! Если массив пустой, то совпадает с итератором \a rend().
//! \~\return \ref stl_iterators
//! \~\sa \a rend(), \a begin(), \a end()
inline reverse_iterator rbegin() {return reverse_iterator(this, pid_size - 1);} inline reverse_iterator rbegin() {return reverse_iterator(this, pid_size - 1);}
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент, следующий за последним элементом.
//! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png)
//!
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
//! This element acts as a placeholder, attempting to access it results in undefined behavior.
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на элемент, предшествующий первому элементу.
//! Этот элемент существует лишь условно,
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a rbegin(), \a begin(), \a end()
inline reverse_iterator rend() {return reverse_iterator(this, -1);} inline reverse_iterator rend() {return reverse_iterator(this, -1);}
inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, pid_size - 1);} inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, pid_size - 1);}
inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
//! \~english Number of elements in the container.
//! \~russian Количество элементов массива.
//! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t size() const {return pid_size;} inline size_t size() const {return pid_size;}
//! \~english Number of elements in the container as signed value.
//! \~russian Количество элементов массива в виде знакового числа.
//! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline ssize_t size_s() const {return pid_size;} inline ssize_t size_s() const {return pid_size;}
//! \~english Same as \a size().
//! \~russian Синоним \a size().
//! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t length() const {return pid_size;} inline size_t length() const {return pid_size;}
//! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
//! \~\details
//! \~english To find out the actual number of items, use the function \a size().
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
//! \~\sa \a reserve(), \a size(), \a size_s()
inline size_t capacity() const {return pid_rsize;} inline size_t capacity() const {return pid_rsize;}
inline size_t _start() const {return pid_start;} inline size_t _start() const {return pid_start;}
//! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли контейнер.
//! \~\return
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если контейнер пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isEmpty() const {return (pid_size == 0);} inline bool isEmpty() const {return (pid_size == 0);}
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли контейнер.
//! \~\return
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если контейнер не пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isNotEmpty() const {return (pid_size > 0);} inline bool isNotEmpty() const {return (pid_size > 0);}
//! \~english Tests whether at least one element in the array
//! passes the test implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяет ли какой-либо элемент массива условию,
//! заданному в передаваемой функции `test`.
//! \~\return
//! \~english **true** if, in the array,
//! it finds an element for which the provided function returns **true**;
//! otherwise it returns **false**. Always returns **false** if is empty.
//! \~russian **true** если хотя бы для одного элемента
//! передаваемая функция возвращает **true**, в остальных случаях **false**.
//! Метод возвращает **false** при любом условии для пустого массива.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 8, 9};
//! piCout << v.any([](int e){return e % 2 == 0;}); // true
//! piCout << v.any([](int e){return e == 3;}); // false
//! \endcode
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
inline bool any(std::function<bool(const T & e)> test) const { inline bool any(std::function<bool(const T & e)> test) const {
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) { for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
if (test(pid_data[i])) return true; if (test(pid_data[i])) return true;
} }
return false; return false;
} }
//! \~english Tests whether all elements in the array passes the test
//! implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяют ли все элементы массива условию,
//! заданному в передаваемой функции `test`.
//! \~\return
//! \~english **true** if, in the array,
//! it finds an element for which the provided function returns **true**;
//! otherwise it returns **false**. Always returns **true** if is empty.
//! \~russian **true** если для всех элементов передаваемая функция возвращает **true**,
//! в остальных случаях **false**.
//! Метод возвращает **true** при любом условии для пустого массива.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 8, 9};
//! piCout << v.every([](int e){return e % 2 == 0;}); // false
//! piCout << v.every([](int e){return e > 0;}); // true
//! \endcode
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
inline bool every(std::function<bool(const T & e)> test) const { inline bool every(std::function<bool(const T & e)> test) const {
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) { for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
if (!test(pid_data[i])) return false; if (!test(pid_data[i])) return false;
@@ -295,64 +720,222 @@ public:
return true; return true;
} }
//! \~english Full access to element by `index`.
//! \~russian Полный доступ к элементу по индексу `index`.
//! \~\details
//! \~english Element index starts from `0`.
//! Element index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! \~\code
//! PIDeque<int> v{1, 2, 8, 9};
//! piCout << v[2]; // 8
//! v[2] = 5;
//! piCout << v; // {1, 2, 5, 9}
//! \endcode
//! \~\sa \a at()
inline T & operator [](size_t index) {return pid_data[pid_start + index];} inline T & operator [](size_t index) {return pid_data[pid_start + index];}
inline const T & operator [](size_t index) const {return pid_data[pid_start + index];} inline const T & operator [](size_t index) const {return pid_data[pid_start + index];}
//! \~english Read only access to element by `index`.
//! \~russian Доступ исключительно на чтение к элементу по индексу `index`.
//! \~\details
//! \~english Element index starts from `0`.
//! Element index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const T & at(size_t index) const {return pid_data[pid_start + index];} inline const T & at(size_t index) const {return pid_data[pid_start + index];}
//! \~english Last element.
//! \~russian Последний элемент массива.
//! \~\details
//! \~english Returns a reference to the last item in the array.
//! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на последний элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline T & back() {return pid_data[pid_start + pid_size - 1];} inline T & back() {return pid_data[pid_start + pid_size - 1];}
inline const T & back() const {return pid_data[pid_start + pid_size - 1];} inline const T & back() const {return pid_data[pid_start + pid_size - 1];}
//! \~english Last element.
//! \~russian Первый элемент массива.
//! \~\details
//! \~english Returns a reference to the last item in the array.
//! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на пенрвый элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline T & front() {return pid_data[pid_start];} inline T & front() {return pid_data[pid_start];}
inline const T & front() const {return pid_data[pid_start];} inline const T & front() const {return pid_data[pid_start];}
//! \~english Compare operator with array `v`.
//! \~russian Оператор сравнения с массивом `v`.
inline bool operator ==(const PIDeque<T> & v) const { inline bool operator ==(const PIDeque<T> & v) const {
if (pid_size != v.pid_size) return false; if (pid_size != v.pid_size) return false;
for (size_t i = 0; i < pid_size; ++i) { for (size_t i = 0; i < pid_size; ++i) {
if (v[i] != (*this)[i]) { if (v[i] != (*this)[i]) return false;
return false;
}
} }
return true; return true;
} }
//! \~english Compare operator with array `v`.
//! \~russian Оператор сравнения с массивом `v`.
inline bool operator !=(const PIDeque<T> & v) const {return !(*this == v);} inline bool operator !=(const PIDeque<T> & v) const {return !(*this == v);}
inline bool operator <(const PIDeque<T> & v) const {
if (pid_size != v.pid_size) return pid_size < v.pid_size; //! \~english Tests if element `e` exists in the array.
for (size_t i = 0; i < pid_size; ++i) { //! \~russian Проверяет наличие элемента `e` в массиве.
if ((*this)[i] != v[i]) return (*this)[i] < v[i]; //! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! **false** is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается **false**, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4};
//! piCout << v.contains(3); // true
//! piCout << v.contains(5); // false
//! piCout << v.contains(3, 3); // false
//! piCout << v.contains(3, -2); // true
//! piCout << v.contains(3, -99); // true
//! \endcode
//! \~\return
//! \~english **true** if the array contains an occurrence of element `e`,
//! otherwise it returns **false**.
//! \~russian **true** если элемент `e` присутствует в массиве,
//! в остальных случаях **false**.
//! \~\sa \a every(), \a any(), \a entries(), \a forEach()
inline bool contains(const T & e, ssize_t start = 0) const {
if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (e == pid_data[i]) return true;
} }
return false; return false;
} }
inline bool operator >(const PIDeque<T> & v) const {
if (pid_size != v.pid_size) return pid_size > v.pid_size; //! \~english Count elements equal `e` in the array.
for (size_t i = 0; i < pid_size; ++i) { //! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
if ((*this)[i] != v[i]) return (*this)[i] > v[i]; //! \~\details
} //! \~english Optional argument `start` - the position in this array at which to begin searching.
return false; //! If the index is greater than or equal to the array's size,
} //! 0 is returned, which means the array will not be searched.
inline bool contains(const T & e) const { //! If the provided index value is a negative number,
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) { //! it is taken as the offset from the end of the array.
if (e == pid_data[i]) { //! Note: if the provided index is negative,
return true; //! the array is still searched from front to back.
} //! Default: 0 (entire array is searched).
} //! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
return false; //! Если индекс больше или равен длине массива,
} //! возвращается 0, что означает, что массив даже не просматривается.
inline int etries(const T & e, size_t start = 0) const { //! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<int> v{2, 2, 4, 2, 6};
//! piCout << v.entries(2); // 3
//! piCout << v.entries(2, 2); // 1
//! piCout << v.entries(2, -4); // 2
//! \endcode
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexOf()
inline int entries(const T & e, size_t start = 0) const {
int ec = 0; int ec = 0;
if (start >= pid_size) return ec; if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) { for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (e == pid_data[i]) ++ec; if (e == pid_data[i]) ++ec;
} }
return ec; return ec;
} }
inline int etries(std::function<bool(const T & e)> test, size_t start = 0) const {
//! \~english Count elements in the array passes the test implemented by the provided function `test`.
//! \~russian Подсчитывает количество элементов в массиве,
//! проходящих по условию, заданному в передаваемой функции `test`.
//! \~\details
//! \~english Overloaded function.
//! Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! 0 is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Перегруженная функция.
//! Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается 0, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere()
inline int entries(std::function<bool(const T & e)> test, size_t start = 0) const {
int ec = 0; int ec = 0;
if (start >= pid_size) return ec; if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) { for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (test(pid_data[i])) ++ec; if (test(pid_data[i])) ++ec;
} }
return ec; return ec;
} }
//! \~english Returns the first index at which a given element `e`
//! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает первый индекс, по которому данный элемент `e`
//! может быть найден в массиве или `-1`, если такого индекса нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! `-1` is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<int> v{2, 5, 9};
//! piCout << v.indexOf(2); // 0
//! piCout << v.indexOf(7); // -1
//! piCout << v.indexOf(9, 2); // 2
//! piCout << v.indexOf(2, -1); // -1
//! piCout << v.indexOf(2, -3); // 0
//! \endcode
//! \~\sa \a indexWhere(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
inline ssize_t indexOf(const T & e, size_t start = 0) const { inline ssize_t indexOf(const T & e, size_t start = 0) const {
if (start >= pid_size) return -1; if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) { for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (e == pid_data[i]) { if (e == pid_data[i]) {
return i - pid_start; return i - pid_start;
@@ -360,8 +943,40 @@ public:
} }
return -1; return -1;
} }
//! \~english Returns the first index passes the test implemented by the provided function `test`,
//! or `-1` if it is not present.
//! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает первый индекс элемента проходящего по условию,
//! заданному в передаваемой функции `test`, или `-1`, если таких элементов нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! `-1` is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<PIString> v{"do", "re", "mi", "re"};
//! piCout << v.indexWhere([](const PIString & s){return s.startsWith('r');}); // 1
//! piCout << v.indexWhere([](const PIString & s){return s.startsWith('r');}, 2); // 3
//! piCout << v.indexWhere([](const PIString & s){return s.startsWith('k');}); // -1
//! \endcode
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const { inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
if (start >= pid_size) return -1; if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) { for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
if (test(pid_data[i])) { if (test(pid_data[i])) {
return i - pid_start; return i - pid_start;
@@ -369,9 +984,44 @@ public:
} }
return -1; return -1;
} }
//! \~english Returns the last index at which a given element `e`
//! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает последний индекс, по которому данный элемент `e`
//! может быть найден в массиве или `-1`, если такого индекса нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array
//! at which to start searching backwards.
//! If the index is greater than or equal to the array's size,
//! causes the whole array to be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Therefore, if calculated index less than 0,
//! the array is not searched, and the method returns `-1`.
//! Note: if the provided index is negative,
//! the array is still searched from back to front.
//! Default: -1 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
//! \~\code
//! PIDeque<int> v{2, 5, 9, 2};
//! piCout << v.lastIndexOf(2); // 3
//! piCout << v.lastIndexOf(7); // -1
//! piCout << v.lastIndexOf(2, 2); // 0
//! piCout << v.lastIndexOf(2, -3); // 0
//! piCout << v.lastIndexOf(2, -300); // -1
//! piCout << v.lastIndexOf(2, 300); // 3
//! \endcode
//! \~\sa \a indexOf(), \a indexWhere(), \a lastIndexWhere(), \a contains()
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const { inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
if (start < 0) start = pid_size - 1; if (start >= size_s()) start = pid_size - 1;
else start = piMin<ssize_t>(pid_size - 1, start); if (start < 0) start = pid_size + start;
for (ssize_t i = pid_start + start; i >= pid_start; --i) { for (ssize_t i = pid_start + start; i >= pid_start; --i) {
if (e == pid_data[i]) { if (e == pid_data[i]) {
return i - pid_start; return i - pid_start;
@@ -379,9 +1029,35 @@ public:
} }
return -1; return -1;
} }
//! \~english Returns the last index passes the test implemented by the provided function `test`,
//! or `-1` if it is not present.
//! \~russian Возвращает последний индекс элемента проходящего по условию,
//! заданному в передаваемой функции `test`, или `-1`, если таких элементов нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array
//! at which to start searching backwards.
//! If the index is greater than or equal to the array's size,
//! causes the whole array to be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Therefore, if calculated index less than 0,
//! the array is not searched, and the method returns `-1`.
//! Note: if the provided index is negative,
//! the array is still searched from back to front.
//! Default: -1 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
//! \~\sa \a indexOf(), \a lastIndexOf(), \a indexWhere(), \a contains()
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const { inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
if (start < 0) start = pid_size - 1; if (start >= size_s()) start = pid_size - 1;
else start = piMin<ssize_t>(pid_size - 1, start); if (start < 0) start = pid_size + start;
for (ssize_t i = pid_start + start; i >= pid_start; --i) { for (ssize_t i = pid_start + start; i >= pid_start; --i) {
if (test(pid_data[i])) { if (test(pid_data[i])) {
return i - pid_start; return i - pid_start;
@@ -390,15 +1066,69 @@ public:
return -1; return -1;
} }
//! \~english Pointer to array
//! \~russian Указатель на память массива
//! \~\details
//! \~english Optional argument `index` the position in this array,
//! where is pointer. Default: start of array.
//! \~russian Опциональный аргумент `index` указывает на индекс c которого брать указатель.
//! По умолчанию указывает на начало массива.
//! \~\code
//! PIDeque<int> v{2, 5, 9, 2};
//! int a[2] = {12, 13};
//! memcpy(vec.data(1), a, 2 * sizeof(int));
//! piCout << v; // {2, 12, 13, 2}
//! \endcode
inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);} inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);}
//! \~english Read only pointer to array
//! \~russian Указатель на память массива только для чтения.
//! \~\details
//! \~english The pointer can be used to access and modify the items in the array.
//! The pointer remains valid as long as the array isn't reallocated.
//! Optional argument `index` the position in this array,
//! where is pointer. Default: start of array.
//! \~russian Указатель можно использовать для доступа и изменения элементов в массиве.
//! Указатель остается действительным только до тех пор, пока массив не будет перераспределен.
//! Опциональный аргумент `index` указывает на индекс c которого брать указатель.
//! По умолчанию указывает на начало массива.
//! \~\code
//! PIDeque<int> v{1, 3, 5};
//! int a[3];
//! memcpy(a, v.data(), a.size() * sizeof(int));
//! piCout << a[0] << a[1] << a[2]; // 1 3 5
//! \endcode
inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);} inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);}
//! \~english Creates sub-array of this array.
//! \~russian Создает подмассив, то есть кусок из текущего массива.
//! \~english
//! \param index - index of this array where sub-array starts
//! \param count - sub-array size
//! \~russian
//! \param index - индекс в текущем массиве, откуда начинётся подмассив
//! \param count - размер подмассива
//! \~\details
//! \~english
//! Index must be in range from `0` to `size()-1`.
//! If sub-array size more than this array size, than ends early.
//! \~russian
//! Индекс начала должен лежать в диапазоне от `0` до `size()-1`.
//! Если заданный размер подмассива превышает размер текущего массива,
//! то вернется подмассив меньшего размера (`size()-index-1`).
PIDeque<T> getRange(size_t index, size_t count) const { PIDeque<T> getRange(size_t index, size_t count) const {
if (index >= pid_size || count == 0) return PIDeque<T>(); if (index >= pid_size || count == 0) return PIDeque<T>();
if (index + count > pid_size) count = pid_size - index; if (index + count > pid_size) count = pid_size - index;
return PIDeque(&(pid_data[pid_start + index]), count); return PIDeque(&(pid_data[pid_start + index]), count);
} }
//! \~english Clear array, remove all elements.
//! \~russian Очищает массив, удаляет все элементы.
//! \~\details
//! \~\note
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value !std::is_trivially_copyable<T1>::value
, int>::type = 0> , int>::type = 0>
@@ -416,14 +1146,33 @@ public:
return *this; return *this;
} }
inline PIDeque<T> & fill(const T & f = T()) { //! \~english Assigns element 'e' to all items in the array.
//! \~russian Заполняет весь массив копиями элемента 'e'.
//! \~\details
//! \code
//! PIDeque<int> v{1, 3, 5};
//! v.fill(7);
//! piCout << v; // {7, 7, 7}
//! \endcode
//! \~\sa \a resize()
inline PIDeque<T> & fill(const T & e = T()) {
deleteT(pid_data + pid_start, pid_size); deleteT(pid_data + pid_start, pid_size);
PIINTROSPECTION_CONTAINER_USED(T, pid_size) PIINTROSPECTION_CONTAINER_USED(T, pid_size)
for (size_t i = pid_start; i < pid_start + pid_size; ++i) { for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
elementNew(pid_data + i, f); elementNew(pid_data + i, e);
} }
return *this; return *this;
} }
//! \~english Assigns result of function 'f(size_t i)' to all items in the array.
//! \~russian Заполняет весь массив результатом вызова функции 'f(size_t i)'.
//! \~\details
//! \code
//! PIDeque<int> v{1, 3, 5};
//! v.fill([](size_t i){return i*2;});
//! piCout << v; // {0, 2, 4}
//! \endcode
//! \~\sa \a resize()
inline PIDeque<T> & fill(std::function<T(size_t i)> f) { inline PIDeque<T> & fill(std::function<T(size_t i)> f) {
deleteT(pid_data + pid_start, pid_size); deleteT(pid_data + pid_start, pid_size);
PIINTROSPECTION_CONTAINER_USED(T, pid_size) PIINTROSPECTION_CONTAINER_USED(T, pid_size)
@@ -432,23 +1181,42 @@ public:
} }
return *this; return *this;
} }
inline PIDeque<T> & assign(const T & f = T()) {return fill(f);}
//! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize()
inline PIDeque<T> & assign(const T & e = T()) {return fill(e);}
//! \~english First does `resize(new_size)` then `fill(e)`.
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
//! \~\sa \a fill(), \a resize()
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value !std::is_trivially_copyable<T1>::value
, int>::type = 0> , int>::type = 0>
inline PIDeque<T> & assign(size_t new_size, const T & f) { inline PIDeque<T> & assign(size_t new_size, const T & e) {
resize(new_size); resize(new_size);
return fill(f); return fill(e);
} }
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value std::is_trivially_copyable<T1>::value
, int>::type = 0> , int>::type = 0>
inline PIDeque<T> & assign(size_t new_size, const T & f) { inline PIDeque<T> & assign(size_t new_size, const T & e) {
_resizeRaw(new_size); _resizeRaw(new_size);
return fill(f); return fill(e);
} }
inline PIDeque<T> & resize(size_t new_size, const T & f = T()) { //! \~english Sets size of the array, new elements are copied from `e`.
//! \~russian Устанавливает размер массива, новые элементы копируются из `e`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements are initialized from `e`.
//! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и создаются из `e`.
//! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIDeque<T> & resize(size_t new_size, const T & e = T()) {
if (new_size < pid_size) { if (new_size < pid_size) {
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
pid_size = new_size; pid_size = new_size;
@@ -458,14 +1226,26 @@ public:
} }
if (new_size > pid_size) { if (new_size > pid_size) {
size_t os = pid_size; size_t os = pid_size;
alloc(new_size, true); alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) { for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, f); elementNew(pid_data + i, e);
} }
} }
return *this; return *this;
} }
//! \~english Sets size of the array, new elements created by function `f(size_t i)`.
//! \~russian Устанавливает размер массива, новые элементы создаются функцией `f(size_t i)`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements created by function `f(size_t i)`.
//! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и функцией `f(size_t i)`.
//! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t i)> f) { inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
if (new_size < pid_size) { if (new_size < pid_size) {
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
@@ -476,7 +1256,7 @@ public:
} }
if (new_size > pid_size) { if (new_size > pid_size) {
size_t os = pid_size; size_t os = pid_size;
alloc(new_size, true); alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) { for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, f(i)); elementNew(pid_data + i, f(i));
@@ -495,30 +1275,59 @@ public:
if (new_size < pid_size) { if (new_size < pid_size) {
PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size)); PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size));
} }
alloc(new_size, true); alloc_forward(new_size);
return *this; return *this;
} }
inline void _copyRaw(T * dst, const T * src, size_t size) {
newT(dst, src, size);
}
//! \~english Attempts to allocate memory for at least `new_size` elements.
//! \~russian Резервируется память под как минимум `new_size` элементов.
//! \~\details
//! \~english If you know in advance how large the array will be,
//! you should call this function to prevent reallocations and memory fragmentation.
//! If `new_size` is greater than the current \a capacity(),
//! new storage is allocated, otherwise the function does nothing.
//! This function does not change the \a size() of the array.
//! \~russian Если вы заранее знаете, насколько велик будет массив,
//! вы можете вызвать эту функцию, чтобы предотвратить перераспределение и фрагментацию памяти.
//! Если размер `new_size` больше чем выделенная память \a capacity(),
//! то произойдёт выделение новой памяти и перераспределение массива.
//! Эта функция не изменяет количество элементов в массиве \a size().
//! \~\sa \a size(), \a capacity(), \a resize()
inline PIDeque<T> & reserve(size_t new_size) { inline PIDeque<T> & reserve(size_t new_size) {
if (new_size <= pid_rsize) return *this; if (new_size <= pid_rsize) return *this;
size_t os = pid_size; size_t os = pid_size;
alloc(new_size, true); alloc_forward(new_size);
pid_size = os; pid_size = os;
return *this; return *this;
} }
//! \~english Inserts value `e` at `index` position in the array.
//! \~russian Вставляет значение `e` в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than 0 and less than or equal to \a size().
//! \~russian Индекс должен быть больше 0 и меньше или равен \a size().
//! \code
//! PIDeque<int> v{1, 3, 5};
//! v.insert(2, 7);
//! piCout << v; // {1, 3, 7, 5}
//! \endcode
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIDeque<T> & insert(size_t index, const T & e = T()) { inline PIDeque<T> & insert(size_t index, const T & e = T()) {
if (index == pid_size) return push_back(e); if (index == pid_size) return push_back(e);
PIINTROSPECTION_CONTAINER_USED(T, 1) PIINTROSPECTION_CONTAINER_USED(T, 1)
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) { if (dir) {
alloc(pid_size + 1, true); alloc_forward(pid_size + 1);
if (index < pid_size - 1) { if (index < pid_size - 1) {
size_t os = pid_size - index - 1; size_t os = pid_size - index - 1;
memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
} }
} else { } else {
alloc(pid_size + 1, false, -1); alloc_backward(pid_size + 1, -1);
if (index > 0) { if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T)); memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
} }
@@ -526,18 +1335,25 @@ public:
elementNew(pid_data + pid_start + index, e); elementNew(pid_data + pid_start + index, e);
return *this; return *this;
} }
//! \~english Inserts value `e` at `index` position in the array.
//! \~russian Вставляет значение `e` в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than 0 and less than or equal to \a size().
//! \~russian Индекс должен быть больше 0 и меньше или равен \a size().
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIDeque<T> & insert(size_t index, T && e) { inline PIDeque<T> & insert(size_t index, T && e) {
if (index == pid_size) return push_back(e); if (index == pid_size) return push_back(e);
PIINTROSPECTION_CONTAINER_USED(T, 1) PIINTROSPECTION_CONTAINER_USED(T, 1)
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) { if (dir) {
alloc(pid_size + 1, true); alloc_forward(pid_size + 1);
if (index < pid_size - 1) { if (index < pid_size - 1) {
size_t os = pid_size - index - 1; size_t os = pid_size - index - 1;
memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
} }
} else { } else {
alloc(pid_size + 1, false, -1); alloc_backward(pid_size + 1, -1);
if (index > 0) { if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T)); memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
} }
@@ -545,31 +1361,75 @@ public:
elementNew(pid_data + pid_start + index, std::move(e)); elementNew(pid_data + pid_start + index, std::move(e));
return *this; return *this;
} }
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
if (other.isEmpty()) return *this; //! \~english Inserts array `v` at `index` position in the array.
//! \~russian Вставляет массив `v` в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & v) {
if (v.isEmpty()) return *this;
#ifndef NDEBUG #ifndef NDEBUG
if (&other == this) { if (&v == this) {
printf("error with PIDeque<%s>::insert\n", __PIP_TYPENAME__(T)); printf("error with PIDeque<%s>::insert\n", __PIP_TYPENAME__(T));
} }
#endif #endif
assert(&other != this); assert(&v != this);
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) { if (dir) {
ssize_t os = pid_size - index; ssize_t os = pid_size - index;
alloc(pid_size + other.pid_size, true); alloc_forward(pid_size + v.pid_size);
if (os > 0) { if (os > 0) {
memmove((void*)(&(pid_data[index + pid_start + other.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); memmove((void*)(&(pid_data[index + pid_start + v.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
} }
} else { } else {
alloc(pid_size + other.pid_size, false, -other.pid_size); alloc_backward(pid_size + v.pid_size, -v.pid_size);
if (index > 0) { if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + other.pid_size])), index * sizeof(T)); memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + v.pid_size])), index * sizeof(T));
} }
} }
newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.pid_size); newT(pid_data + pid_start + index, v.pid_data + v.pid_start, v.pid_size);
return *this; return *this;
} }
//! \~english Inserts the given elements at `index` position in the array.
//! \~russian Вставляет элементы в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
//! Inserts the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
//! Вставляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIDeque<T> & insert(size_t index, std::initializer_list<T> init_list) {
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) {
ssize_t os = pid_size - index;
alloc_forward(pid_size + init_list.size());
if (os > 0) {
memmove((void*)(&(pid_data[index + pid_start + init_list.size()])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
}
} else {
alloc_backward(pid_size + init_list.size(), -init_list.size());
if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + init_list.size()])), index * sizeof(T));
}
}
newT(pid_data + pid_start + index, init_list.begin(), init_list.size());
return *this;
}
//! \~english Removes `count` elements from the middle of the array, starting at `index` position.
//! \~russian Удаляет элементы из массива, начиная с позиции `index` в количестве `count`.
//! \~\details
//! \code
//! PIDeque<int> v{1, 3, 7, 5};
//! v.remove(1, 2);
//! piCout << v; // {1, 5}
//! \endcode
//! \~\sa \a resize(), \a insert(), \a removeOne(), \a removeAll(), \a removeWhere()
inline PIDeque<T> & remove(size_t index, size_t count = 1) { inline PIDeque<T> & remove(size_t index, size_t count = 1) {
if (count == 0) return *this; if (count == 0) return *this;
if (index + count >= pid_size) { if (index + count >= pid_size) {
@@ -592,6 +1452,11 @@ public:
return *this; return *this;
} }
//! \~english Swaps array `v` other with this array.
//! \~russian Меняет местами массив `v` с этим массивом.
//! \~\details
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
inline void swap(PIDeque<T> & other) { inline void swap(PIDeque<T> & other) {
piSwap<T*>(pid_data, other.pid_data); piSwap<T*>(pid_data, other.pid_data);
piSwap<size_t>(pid_size, other.pid_size); piSwap<size_t>(pid_size, other.pid_size);
@@ -599,7 +1464,6 @@ public:
piSwap<ssize_t>(pid_start, other.pid_start); piSwap<ssize_t>(pid_start, other.pid_start);
} }
//! \~\brief
//! \~english Sorts the elements in non-descending order. //! \~english Sorts the elements in non-descending order.
//! \~russian Сортировка элементов в порядке возрастания. //! \~russian Сортировка элементов в порядке возрастания.
//! \~\details //! \~\details
@@ -622,7 +1486,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Sorts the elements in non-descending order. //! \~english Sorts the elements in non-descending order.
//! \~russian Сортировка элементов в порядке возрастания. //! \~russian Сортировка элементов в порядке возрастания.
//! \~\details //! \~\details
@@ -634,6 +1497,8 @@ public:
//! bool comp(const T &a, const T &b); //! bool comp(const T &a, const T &b);
//! \endcode //! \endcode
//! While the signature does not need to have const &, the function must not modify the objects passed to it. //! While the signature does not need to have const &, the function must not modify the objects passed to it.
//! The function must return `false` for identical elements,
//! otherwise, it will lead to undefined program behavior and memory errors.
//! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort). //! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort).
//! Complexity `O(N·log(N))`. //! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется. //! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
@@ -644,6 +1509,8 @@ public:
//! bool comp(const T &a, const T &b); //! bool comp(const T &a, const T &b);
//! \endcode //! \endcode
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты. //! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
//! Функция обязана возвращать `false` для одинаковых элементов,
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). //! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`. //! Сложность сортировки `O(N·log(N))`.
//! \~\code //! \~\code
@@ -657,6 +1524,54 @@ public:
return *this; return *this;
} }
//! \~english Reverses this array.
//! \~russian Обращает порядок следования элементов этого массива.
//! \~\details
//! \~english This method reverses an array [in place](https://en.wikipedia.org/wiki/In-place_algorithm).
//! The first array element becomes the last, and the last array element becomes the first.
//! The reverse method transposes the elements of the calling array object in place,
//! mutating the array, and returning a reference to the array.
//! \~russian Метод reverse() на месте переставляет элементы массива,
//! на котором он был вызван, изменяет массив и возвращает ссылку на него.
//! Первый элемент массива становится последним, а последний — первым.
//! \~\code
//! PIDeque<int> v{1, 3, 7, 5};
//! v.reverse();
//! piCout << v; // {5, 7, 3, 1}
//! \endcode
//! \~\sa \a reversed()
inline PIDeque<T> & reverse() {
size_t s2 = pid_size/2;
for (size_t i = 0; i < s2; ++i) {
piSwap<T>(pid_data[pid_start+i], pid_data[pid_start+pid_size-i-1]);
}
return *this;
}
//! \~english Returns reversed array.
//! \~russian Возвращает перевернутый массив.
//! \~\details
//! \~english Returns a copy of the array with elements in reverse order.
//! The first array element becomes the last, and the last array element becomes the first.
//! \~russian Возвращает копию массива с элементами в обратном порядке.
//! Первый элемент массива становится последним, а последний — первым.
//! \~\sa \a reverse()
inline PIDeque<T> reversed() const {
PIDeque<T> ret(*this);
return ret.reverse();
}
//! \~english Increases or decreases the size of the array by `add_size` elements.
//! \~russian Увеличивает или уменьшает размер массива на `add_size` элементов.
//! \~\details
//! \~english If `add_size > 0` then elements are added to the end of the array.
//! If `add_size < 0` then elements are removed from the end of the array.
//! If `add_size < 0` and there are fewer elements in the array than specified, then the array becomes empty.
//! \~russian Если `add_size > 0`, то в конец массива добавляются элементы.
//! Если `add_size < 0`, то с конца массива удаляются элементы.
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
//! \~\sa \a resize()
inline PIDeque<T> & enlarge(llong pid_size) { inline PIDeque<T> & enlarge(llong pid_size) {
llong ns = size_s() + pid_size; llong ns = size_s() + pid_size;
if (ns <= 0) clear(); if (ns <= 0) clear();
@@ -664,6 +1579,15 @@ public:
return *this; return *this;
} }
//! \~english Remove no more than one element equal `e`.
//! \~russian Удаляет первый элемент, который равен элементу `e`.
//! \~\details
//! \~\code
//! PIDeque<int> v{3, 2, 5, 2, 7};
//! v.removeOne(2);
//! piCout << v; // {3, 5, 2, 7}
//! \endcode
//! \~\sa \a remove(), \a removeAll(), \a removeWhere()
inline PIDeque<T> & removeOne(const T & e) { inline PIDeque<T> & removeOne(const T & e) {
for (size_t i = 0; i < pid_size; ++i) { for (size_t i = 0; i < pid_size; ++i) {
if (pid_data[i + pid_start] == e) { if (pid_data[i + pid_start] == e) {
@@ -673,6 +1597,16 @@ public:
} }
return *this; return *this;
} }
//! \~english Remove all elements equal `e`.
//! \~russian Удаляет все элементы, равные элементу `e`.
//! \~\details
//! \~\code
//! PIDeque<int> v{3, 2, 5, 2, 7};
//! v.removeAll(2);
//! piCout << v; // {3, 5, 7}
//! \endcode
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIDeque<T> & removeAll(const T & e) { inline PIDeque<T> & removeAll(const T & e) {
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) { for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
if (pid_data[i + pid_start] == e) { if (pid_data[i + pid_start] == e) {
@@ -682,6 +1616,18 @@ public:
} }
return *this; return *this;
} }
//! \~english Remove all elements in the array
//! passes the test implemented by the provided function `test`.
//! \~russian Удаляет все элементы, удовлетворяющие условию,
//! заданному в передаваемой функции `test`.
//! \~\details
//! \~\code
//! PIDeque<int> v{3, 2, 5, 2, 7};
//! v.removeWhere([](const int & i){return i > 2;});
//! piCout << v; // {2, 2}
//! \endcode
//! \~\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) {
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) { for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
if (test(pid_data[i + pid_start])) { if (test(pid_data[i + pid_start])) {
@@ -692,21 +1638,74 @@ public:
return *this; return *this;
} }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~english If size() is less than capacity(), which is most often
//! then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If the new size() is greater than capacity()
//! then all iterators and references
//! (including the past-the-end iterator) are invalidated.
//! Otherwise only the past-the-end iterator is invalidated.
//! \~russian Если size() меньше capacity(), что часто бывает,
//! то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если новый size() больше, чем capacity(),
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов, указывающих на конец массива,
//! остаются в рабочем состоянии.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.push_back(4);
//! v.push_back(5);
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a push_front(), \a append(), \a prepend(), \a insert()
inline PIDeque<T> & push_back(const T & e) { inline PIDeque<T> & push_back(const T & e) {
alloc(pid_size + 1, true); alloc_forward(pid_size + 1);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(pid_data + pid_start + pid_size - 1, e); elementNew(pid_data + pid_start + pid_size - 1, e);
return *this; return *this;
} }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_back()
inline PIDeque<T> & push_back(T && e) { inline PIDeque<T> & push_back(T && e) {
alloc(pid_size + 1, true); alloc_forward(pid_size + 1);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
elementNew(pid_data + pid_start + pid_size - 1, std::move(e)); elementNew(pid_data + pid_start + pid_size - 1, std::move(e));
return *this; return *this;
} }
inline PIDeque<T> & append(const T & e) {return push_back(e);}
inline PIDeque<T> & append(T && e) {return push_back(std::move(e));} //! \~english Appends the given elements to the end of the array.
inline PIDeque<T> & append(const PIDeque<T> & v) { //! \~russian Добавляет элементы в конец массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a push_back()
inline PIDeque<T> & push_back(std::initializer_list<T> init_list) {
size_t ps = pid_size;
alloc_forward(pid_size + init_list.size());
newT(pid_data + pid_start + ps, init_list.begin(), init_list.size());
return *this;
}
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_back()
inline PIDeque<T> & push_back(const PIDeque<T> & v) {
#ifndef NDEBUG #ifndef NDEBUG
if (&v == this) { if (&v == this) {
printf("error with PIDeque<%s>::append\n", __PIP_TYPENAME__(T)); printf("error with PIDeque<%s>::append\n", __PIP_TYPENAME__(T));
@@ -714,27 +1713,314 @@ public:
#endif #endif
assert(&v != this); assert(&v != this);
size_t ps = pid_size; size_t ps = pid_size;
alloc(pid_size + v.pid_size, true); alloc_forward(pid_size + v.pid_size);
newT(pid_data + ps + pid_start, v.pid_data + v.pid_start, v.pid_size); newT(pid_data + ps + pid_start, v.pid_data + v.pid_start, v.pid_size);
return *this; return *this;
} }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~english If size() is less than capacity(), which is most often
//! then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If the new size() is greater than capacity()
//! then all iterators and references
//! (including the past-the-end iterator) are invalidated.
//! Otherwise only the past-the-end iterator is invalidated.
//! \~russian Если size() меньше capacity(), что часто бывает,
//! то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если новый size() больше, чем capacity(),
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов, указывающих на конец массива,
//! остаются в рабочем состоянии.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.append(4);
//! v.append(5);
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a prepend(), \a push_front(), \a push_back(), \a insert()
inline PIDeque<T> & append(const T & e) {return push_back(e);}
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a append()
inline PIDeque<T> & append(T && e) {return push_back(std::move(e));}
//! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIDeque<T> & append(std::initializer_list<T> init_list) {return push_back(init_list);}
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.append(PIDeque<int>{4, 5});
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIDeque<T> & append(const PIDeque<T> & v) {return push_back(v);}
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v << 4 << 5;
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIDeque<T> & operator <<(const T & e) {return push_back(e);} inline PIDeque<T> & operator <<(const T & e) {return push_back(e);}
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v << 4 << 5;
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIDeque<T> & operator <<(T && e) {return push_back(std::move(e));} inline PIDeque<T> & operator <<(T && e) {return push_back(std::move(e));}
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v << PIDeque<int>{4, 5};
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append(), \a push_back()
inline PIDeque<T> & operator <<(const PIDeque<T> & v) {return append(v);} inline PIDeque<T> & operator <<(const PIDeque<T> & v) {return append(v);}
inline PIDeque<T> & push_front(const T & e) {insert(0, e); return *this;} //! \~english Appends the given element `e` to the begin of the array.
inline PIDeque<T> & push_front(T && e) {insert(0, std::move(e)); return *this;} //! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english If there is free space at the beginning of the array,
//! which is most often, then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If there is no free space at the beginning of the array
//! then all iterators and references
//! (including the past-the-begin iterator) are invalidated.
//! Otherwise only the past-the-begin iterator is invalidated.
//! \~russian Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.push_front(4);
//! v.push_front(5);
//! piCout << v; // {5, 4, 1, 2, 3}
//! \endcode
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIDeque<T> & push_front(const T & e) {
insert(0, e);
return *this;
}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_front()
inline PIDeque<T> & push_front(T && e) {
insert(0, std::move(e));
return *this;
}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.push_front(PIDeque<int>{4, 5});
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a push_front()
inline PIDeque<T> & push_front(const PIDeque<T> & v) {
insert(0, v);
return *this;
}
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIDeque<T> & push_front(std::initializer_list<T> init_list) {
insert(0, init_list);
return *this;
}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english If there is free space at the beginning of the array,
//! which is most often, then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If there is no free space at the beginning of the array
//! then all iterators and references
//! (including the past-the-begin iterator) are invalidated.
//! Otherwise only the past-the-begin iterator is invalidated.
//! \~russian Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.prepend(4);
//! v.prepend(5);
//! piCout << v; // {5, 4, 1, 2, 3}
//! \endcode
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIDeque<T> & prepend(const T & e) {return push_front(e);} inline PIDeque<T> & prepend(const T & e) {return push_front(e);}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a prepend()
inline PIDeque<T> & prepend(T && e) {return push_front(std::move(e));} inline PIDeque<T> & prepend(T && e) {return push_front(std::move(e));}
inline PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;} //! \~english Appends the given array `v` to the begin of the array.
inline PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;} //! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.prepend(PIDeque<int>{4, 5});
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a prepend()
inline PIDeque<T> & prepend(const PIDeque<T> & v) {return push_front(v);}
inline T take_back() {T e(back()); pop_back(); return e;} //! \~english Appends the given elements to the begin of the array.
inline T take_front() {T e(front()); pop_front(); return e;} //! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIDeque<T> & prepend(std::initializer_list<T> init_list) {return prepend(init_list);}
//! \~english Remove one element from the end of the array.
//! \~russian Удаляет один элемент с конца массива.
//! \~\details
//! \~english Deleting an element from the end is very fast
//! and does not depend on the size of the array.
//! \~russian Удаление элемента с конца выполняется очень быстро
//! и не зависит от размера массива.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.pop_back();
//! piCout << v; // {1, 2}
//! \endcode
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
inline PIDeque<T> & pop_back() {
if (pid_size == 0) return *this;
resize(pid_size - 1);
return *this;
}
//! \~english Remove one element from the begining of the array.
//! \~russian Удаляет один элемент с начала массива.
//! \~\details
//! \~english Removing an element from the beginning takes longer than from the end.
//! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated.
//! \~russian Удаление элемента с начала выполняется дольше, чем с конца.
//! Это время прямопропорционально размеру массива.
//! При удалении элемента все итераторы и указатели становятся нерабочими.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! v.pop_front();
//! piCout << v; // {2, 3}
//! \endcode
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
inline PIDeque<T> & pop_front() {
if (pid_size == 0) return *this;
remove(0);
return *this;
}
//! \~english Remove one element from the end of the array and return it.
//! \~russian Удаляет один элемент с начала массива и возвращает его.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! piCout << v.take_back(); // 3
//! piCout << v; // {1, 2}
//! \endcode
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline T take_back() {
T e(back());
pop_back();
return e;
}
//! \~english Remove one element from the begining of the array and return it.
//! \~russian Удаляет один элемент с конца массива и возвращает его.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! piCout << v.take_front(); // 1
//! piCout << v; // {2, 3}
//! \endcode
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline T take_front() {
T e(front());
pop_front();
return e;
}
//! \~english Returns an array converted to another type.
//! \~russian Возвращает конвертированный в другой тип массив.
//! \~\details
//! \~\code
//! PIDeque<double> v{1.1, 2.5, 3.8};
//! PIDeque<int> v2 = v.toType<int>();
//! piCout << v2; // {1, 2, 3}
//! \endcode
//! \~\sa \a map()
template <typename ST> template <typename ST>
PIDeque<ST> toType() const { inline PIDeque<ST> toType() const {
PIDeque<ST> ret(pid_size); PIDeque<ST> ret(pid_size);
for (size_t i = 0; i < pid_size; ++i) { for (size_t i = 0; i < pid_size; ++i) {
ret[i] = ST(pid_data[i + pid_start]); ret[i] = ST(pid_data[i + pid_start]);
@@ -742,45 +2028,161 @@ public:
return ret; return ret;
} }
const PIDeque<T> & forEach(std::function<void(const T & e)> f) const { //! \~english Returns a new array with all elements
for (size_t i = 0; i < pid_size; ++i) { //! that pass the test implemented by the provided function `test`.
f(pid_data[i + pid_start]); //! \~russian Возвращает новый массив со всеми элементами,
} //! прошедшими проверку, задаваемую в передаваемой функции `test`.
return *this; //! \~\details
} //! \~\code
PIDeque<T> copyForEach(std::function<T(const T & e)> f) const { //! PIDeque<int> v{3, 2, 5, 2, 7};
PIDeque<T> ret; ret.reserve(pid_size); //! PIDeque<int> v2 = v.filter([](const int & i){return i > 2;});
for (size_t i = 0; i < pid_size; ++i) { //! piCout << v2; // {3, 5, 7}
ret << f(pid_data[i + pid_start]); //! \endcode
//! \~\sa \a map(), \a any(), \a every()
inline PIDeque<T> filter(std::function<bool(const T & e)> test) const {
PIDeque<T> ret;
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
if (test(pid_data[i])) ret << pid_data[i];
} }
return ret; return ret;
} }
PIDeque<T> & forEachInplace(std::function<T(const T & e)> f) {
for (size_t i = 0; i < pid_size; ++i) //! \~english Execute function `void f(const T & e)` for every element in array.
pid_data[i + pid_start] = f(pid_data[i + pid_start]); //! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива.
//! \~\details
//! \~russian Не позволяет изменять элементы массива.
//! Для редактирования элементов используйте функцию вида `void f(T & e)`.
//! \~english Does not allow changing array elements.
//! To edit elements, use the function like `void f(T & e)`
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4, 5};
//! int s = 0;
//! v.forEach([&s](const int & e){s += e;});
//! piCout << s; // 15
//! \endcode
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
inline void forEach(std::function<void(const T & e)> f) const {
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
f(pid_data[i]);
}
}
//! \~english Execute function `void f(T & e)` for every element in array.
//! \~russian Выполняет функцию `void f(T & e)` для каждого элемента массива.
//! \~\details
//! \~english Overloaded function.
//! Allows you to change the elements of the array.
//! \~russian Перегруженая функция.
//! Позволяет изменять элементы массива.
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4, 5};
//! v.forEach([](int & e){e++;});
//! piCout << v; // {2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
inline PIDeque<T> & forEach(std::function<void(T & e)> f) {
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
f(pid_data[i]);
}
return *this; return *this;
} }
//! \~english Сreates a new array populated with the results
//! of calling a provided function `ST f(const T & e)` on every element in the calling array.
//! \~russian Создаёт новый массив с результатом вызова указанной функции
//! `ST f(const T & e)` для каждого элемента массива.
//! \~\details
//! \~english Calls a provided function`ST f(const T & e)`
//! once for each element in an array, in order,
//! and constructs a new array from the results.
//! \~russian Метод `map` вызывает переданную функцию `ST f(const T & e)`
//! один раз для каждого элемента в порядке их появления
//! и конструирует новый массив из результатов её вызова.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! PIStringList sl = v.map<PIString>([](const int & i){return PIString::fromNumber(i);});
//! piCout << sl; {"1", "2", "3"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST> template <typename ST>
PIDeque<ST> map(std::function<ST(const T & e)> f) const { inline PIDeque<ST> map(std::function<ST(const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size); PIDeque<ST> ret; ret.reserve(pid_size);
for (size_t i = 0; i < pid_size; ++i) { for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
ret << f(pid_data[i + pid_start]); ret << f(pid_data[i]);
} }
return ret; return ret;
} }
template <typename ST>
PIDeque<ST> toType(std::function<ST(const T & e)> f) const {return map(f);}
//! \~english Applies the function `ST f(const T & e, const ST & acc)`
//! to each element of the array (from left to right), returns one value.
//! \~russian Применяет функцию `ST f(const T & e, const ST & acc)`
//! к каждому элементу массива (слева-направо), возвращает одно значение.
//! \~\details
//! \~english The reduce() method performs the `f` function
//! once for each element in the array.
//! If the `initial` argument is passed when calling reduce(),
//! then when the function `f` is called for the first time,
//! the value of `acc` will be assigned to `initial`.
//! If the array is empty, the value `initial` will be returned.
//! \param f is a function like `ST f(const T & e, const ST & acc)`,
//! executed for each element of the array. It takes two arguments:
//! * **e** - current element of the array
//! * **acc** - accumulator accumulating the value
//! which this function returns after visiting the next element
//!
//! \param initial _optional_ Object used as the second argument
//! when the `f` function is first called.
//! \~russian Метод reduce() выполняет функцию `f`
//! один раз для каждого элемента, присутствующего в массиве.
//! Если при вызове reduce() передан аргумент `initial`,
//! то при первом вызове функции `f` значение `acc`
//! будет равным значению `initial`.
//! Если массив пустой то будет возвращено значение `initial`.
//! \param f Функция, вида `ST f(const T & e, const ST & acc)`,
//! выполняющаяся для каждого элемента массива.
//! Она принимает два аргумента:
//! * **e** - текущий элемент массива
//! * **acc** - аккумулятор, аккумулирующий значение
//! которое возвращает эта функция после посещения очередного элемента
//!
//! \param initial _опциональный_ Объект,
//! используемый в качестве второго аргумента при первом вызове функции `f`.
//!
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4, 5};
//! int s = v.reduce<int>([](const int & e, const int & acc){return e + acc;});
//! piCout << s; // 15
//! \endcode
//! \~\sa \a forEach(), \a map()
template <typename ST> template <typename ST>
ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const { inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial); ST ret(initial);
for (size_t i = 0; i < pid_size; ++i) { for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
ret = f(pid_data[i + pid_start], ret); ret = f(pid_data[i], ret);
} }
return ret; return ret;
} }
inline PIDeque<PIDeque<T>> reshape(size_t rows, size_t cols, int order = byRow) const { //! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
//! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
//! \~\details
//! \~russian
//! \param rows размер внешнего массива
//! \param cols размер внутренних массивов
//! \param order порядок обхода исходного массива, задаётся с помощью \a ReshapeOrder
//! \~english
//! \param rows size external array
//! \param cols size internal arrays
//! \param order the order of traversing the source array is set using \a ReshapeOrder
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4};
//! PIDeque<PIDeque<int>> m1 = v.reshape(2,2);
//! piCout << m1; // {{1, 2}, {3, 4}}
//! PIDeque<PIDeque<int>> m2 = v.reshape(2,2, ReshapeByColumn);
//! piCout << m2; // {{1, 3}, {2, 4}}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a flatten()
inline PIDeque<PIDeque<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
PIDeque<PIDeque<T>> ret; PIDeque<PIDeque<T>> ret;
if (isEmpty()) return ret; if (isEmpty()) return ret;
#ifndef NDEBUG #ifndef NDEBUG
@@ -790,12 +2192,12 @@ public:
#endif #endif
assert(rows*cols == pid_size); assert(rows*cols == pid_size);
ret.resize(rows); ret.resize(rows);
if (order == byRow) { if (order == ReshapeByRow) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols); ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols);
} }
} }
if (order == byColumn) { if (order == ReshapeByColumn) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret[r].resize(cols); ret[r].resize(cols);
for (size_t c = 0; c < cols; c++) { for (size_t c = 0; c < cols; c++) {
@@ -806,21 +2208,35 @@ public:
return ret; return ret;
} }
//! \~english Changes the dimension of the array, creates a one-dimensional array from a two-dimensional array.
//! \~russian Изменяет размерность массива, из двухмерный массива создает одномерный.
//! \~\details
//! \~russian Делает массив плоским.
//! Порядок обхода исходного массива задаётся с помощью \a ReshapeOrder.
//! \~english Makes the array flat.
//! Еhe order of traversing the source array is set using \a ReshapeOrder.
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4, 5, 6};
//! PIDeque<PIDeque<int>> xv = v.reshape(3,2);
//! piCout << xv; // {{1, 2}, {3, 4}, {5, 6}}
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if< template<typename C, typename std::enable_if<
std::is_same<T, PIDeque<C>>::value std::is_same<T, PIDeque<C>>::value
, int>::type = 0> , int>::type = 0>
inline PIDeque<C> reshape(int order = byRow) const { inline PIDeque<C> flatten(ReshapeOrder order = ReshapeByRow) const {
PIDeque<C> ret; PIDeque<C> ret;
if (isEmpty()) return ret; if (isEmpty()) return ret;
size_t rows = size(); size_t rows = size();
size_t cols = at(0).size(); size_t cols = at(0).size();
ret.reserve(rows * cols); ret.reserve(rows * cols);
if (order == byRow) { if (order == ReshapeByRow) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret.append(at(r)); ret.append(at(r));
} }
} }
if (order == byColumn) { if (order == ReshapeByColumn) {
for (size_t c = 0; c < cols; c++) { for (size_t c = 0; c < cols; c++) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret << at(r)[c]; ret << at(r)[c];
@@ -831,6 +2247,32 @@ public:
return ret; return ret;
} }
//! \~english Changes the dimension of the two-dimensional array.
//! \~russian Изменяет размерность двухмерного массива.
//! \~\details
//! \~russian
//! \param rows размер внешнего массива
//! \param cols размер внутренних массивов
//! \param order порядок обхода исходного массива, задаётся с помощью \a ReshapeOrder
//! \~english
//! \param rows size external array
//! \param cols size internal arrays
//! \param order the order of traversing the source array is set using \a ReshapeOrder
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4, 5, 6};
//! PIDeque<PIDeque<int>> xv = v.reshape(3,2);
//! piCout << xv; // {{1, 2}, {3, 4}, {5, 6}}
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if<
std::is_same<T, PIDeque<C>>::value
, int>::type = 0>
inline PIDeque<PIDeque<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
PIDeque<C> fl = flatten<C>();
return fl.reshape(rows, cols, order);
}
private: private:
inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;} inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
inline size_t asize(ssize_t s) { inline size_t asize(ssize_t s) {
@@ -838,10 +2280,9 @@ private:
if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) { if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) {
return pid_rsize + pid_rsize; return pid_rsize + pid_rsize;
} }
ssize_t t = 0, s_ = s - 1; ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
while (s_ >> t) { while (s_ >> t)
++t; ++t;
}
return (1 << t); return (1 << t);
} }
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
@@ -904,7 +2345,7 @@ private:
if ((uchar*)pid_data != 0) free((uchar*)pid_data); if ((uchar*)pid_data != 0) free((uchar*)pid_data);
pid_data = 0; pid_data = 0;
} }
inline void checkMove(bool direction) { inline void checkMove() {
if (pid_size >= 4) { if (pid_size >= 4) {
if (pid_size < pid_rsize / 6) { if (pid_size < pid_rsize / 6) {
if (pid_start < ssize_t(pid_size + pid_size) || pid_start > (ssize_t(pid_rsize) - ssize_t(pid_size) - ssize_t(pid_size))) { if (pid_start < ssize_t(pid_size + pid_size) || pid_start > (ssize_t(pid_rsize) - ssize_t(pid_size) - ssize_t(pid_size))) {
@@ -923,11 +2364,10 @@ private:
} }
} }
} }
inline void alloc(size_t new_size, bool direction, ssize_t start_offset = 0) { // direction == true -> alloc forward inline void alloc_forward(size_t new_size) { // direction == true -> alloc forward
if (direction) {
if (pid_start + new_size <= pid_rsize) { if (pid_start + new_size <= pid_rsize) {
pid_size = new_size; pid_size = new_size;
checkMove(direction); checkMove();
return; return;
} }
pid_size = new_size; pid_size = new_size;
@@ -944,7 +2384,8 @@ private:
pid_data = p_d; pid_data = p_d;
pid_rsize = as; pid_rsize = as;
} }
} else { }
inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) { //alloc backward
size_t as; size_t as;
if (pid_start + start_offset < 0) { if (pid_start + start_offset < 0) {
as = asize(pid_rsize - start_offset); as = asize(pid_rsize - start_offset);
@@ -965,8 +2406,7 @@ private:
} }
pid_start += start_offset; pid_start += start_offset;
pid_size = new_size; pid_size = new_size;
checkMove(direction); checkMove();
}
} }
T * pid_data; T * pid_data;
@@ -976,6 +2416,8 @@ private:
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
//! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream).
//! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream).
template<typename T> template<typename T>
inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) { inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {
s << "{"; s << "{";
@@ -988,6 +2430,10 @@ inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {
} }
#endif #endif
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename T> template<typename T>
inline PICout operator <<(PICout s, const PIDeque<T> & v) { inline PICout operator <<(PICout s, const PIDeque<T> & v) {
s.space(); s.space();
@@ -1002,7 +2448,8 @@ inline PICout operator <<(PICout s, const PIDeque<T> & v) {
return s; return s;
} }
template<typename T> inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);} template<typename T>
inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);}
#endif // PIDEQUE_H #endif // PIDEQUE_H

View File

@@ -30,41 +30,6 @@
#include "pipair.h" #include "pipair.h"
template<class T>
void piQuickSort(T * a, ssize_t N) {
if (N < 1) return;
if (N < 46) {
T tmp;
ssize_t i,j;
for(i=1; i<=N; i++) {
tmp = a[i];
j = i-1;
while(tmp<a[j] && j>=0) {
a[j+1] = a[j];
j = j-1;
}
a[j+1] = tmp;
}
} else {
ssize_t i = 0, j = N;
T & p(a[N >> 1]);
do {
while (a[i] < p) i++;
while (a[j] > p) j--;
if (i <= j) {
if (i != j) {
//piCout << "swap" << i << j << a[i] << a[j];
piSwap<T>(a[i], a[j]);
}
i++; j--;
}
} while (i <= j);
if (j > 0) piQuickSort(a, j);
if (N > i) piQuickSort(a + i, N - i);
}
}
template <typename Key, typename T> template <typename Key, typename T>
class PIMapIterator; class PIMapIterator;
@@ -75,16 +40,19 @@ class PIMap {
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v); template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v);
template <typename Key1, typename T1> friend class PIMapIterator; template <typename Key1, typename T1> friend class PIMapIterator;
public: public:
PIMap() {;} PIMap() {}
PIMap(const PIMap<Key, T> & other) {*this = other;} PIMap(const PIMap<Key, T> & other) {*this = other;}
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {} PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)) {}
PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
for (auto i: init_list)
insert(std::get<0>(i), std::get<1>(i));
}
virtual ~PIMap() {;} virtual ~PIMap() {;}
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) { PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
if (this == &other) return *this; if (this == &other) return *this;
clear(); clear();
pim_content = other.pim_content; pim_content = other.pim_content;
pim_index = other.pim_index;
return *this; return *this;
} }
@@ -199,12 +167,15 @@ public:
T & operator [](const Key & key) { T & operator [](const Key & key) {
bool f(false); bool f(false);
ssize_t i = _find(key, f); ssize_t i = _find(key, f);
if (f) return pim_content[pim_index[i].index]; if (!f) pim_content.insert(i, PIPair<Key, T>(key, T()));
pim_content.push_back(T()); return pim_content[i].second;
pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); }
return pim_content.back(); const T operator [](const Key & key) const {
bool f(false);
ssize_t i = _find(key, f);
if (f) return pim_content[i].second;
return T();
} }
const T operator [](const Key & key) const {bool f(false); ssize_t i = _find(key, f); if (f) return pim_content[pim_index[i].index]; return T();}
const T at(const Key & key) const {return (*this)[key];} const T at(const Key & key) const {return (*this)[key];}
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) { PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
@@ -215,27 +186,26 @@ public:
#endif #endif
assert(&other != this); assert(&other != this);
if (other.isEmpty()) return *this; if (other.isEmpty()) return *this;
if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;} // if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;} // if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
for (int i = 0; i < other.pim_index.size_s(); ++i) for (int i = 0; i < other.pim_content.size_s(); ++i)
insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]); insert(other.pim_content[i].first, other.pim_content[i].second);
return *this; return *this;
} }
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);} bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content);}
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);} bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content);}
bool contains(const Key & key) const {bool f(false); _find(key, f); return f;} bool contains(const Key & key) const {bool f(false); _find(key, f); return f;}
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;} PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size);return *this;}
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;} PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;}
PIMap<Key, T> & remove(const Key & key) {return removeOne(key);} PIMap<Key, T> & remove(const Key & key) {return removeOne(key);}
PIMap<Key, T> & erase(const Key & key) {return removeOne(key);} PIMap<Key, T> & erase(const Key & key) {return removeOne(key);}
PIMap<Key, T> & clear() {pim_content.clear(); pim_index.clear(); return *this;} PIMap<Key, T> & clear() {pim_content.clear(); return *this;}
void swap(PIMap<Key, T> & other) { void swap(PIMap<Key, T> & other) {
pim_content.swap(other.pim_content); pim_content.swap(other.pim_content);
pim_index.swap(other.pim_index);
} }
PIMap<Key, T> & insert(const Key & key, const T & value) { PIMap<Key, T> & insert(const Key & key, const T & value) {
@@ -243,10 +213,9 @@ public:
ssize_t i = _find(key, f); ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value; //piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) { if (f) {
pim_content[pim_index[i].index] = value; pim_content[i].second = value;
} else { } else {
pim_content.push_back(value); pim_content.insert(i, PIPair<Key, T>(key, value));
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
} }
return *this; return *this;
} }
@@ -255,20 +224,34 @@ public:
ssize_t i = _find(key, f); ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value; //piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) { if (f) {
pim_content[pim_index[i].index] = std::move(value); pim_content[i].second = std::move(value);
} else { } else {
pim_content.push_back(std::move(value)); // pim_content.push_back(std::move(value));
pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); // pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
pim_content.insert(i, PIPair<Key, T>(key, std::move(value)));
} }
return *this; return *this;
} }
const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];} const T value(const Key & key, const T & default_ = T()) const {
PIVector<T> values() const {return pim_content;} bool f(false);
Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;} ssize_t i = _find(key, f);
if (!f) return default_;
return pim_content[i].second;
}
PIVector<T> values() const {
PIVector<T> ret;
for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].second;
return ret;
}
Key key(const T & value_, const Key & default_ = Key()) const {
for (int i = 0; i < pim_content.size_s(); ++i)
if (pim_content[i].second == value_)
return pim_content[i].first;
return default_;
}
PIVector<Key> keys() const { PIVector<Key> keys() const {
PIVector<Key> ret; PIVector<Key> ret;
for (int i = 0; i < pim_index.size_s(); ++i) for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].first;
ret << pim_index[i].key;
return ret; return ret;
} }
@@ -276,66 +259,53 @@ public:
piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:"; piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:";
for (size_t i = 0; i < pim_content.size(); ++i) for (size_t i = 0; i < pim_content.size(); ++i)
piCout << PICoutManipulators::Tab << i << ":" << pim_content[i]; piCout << PICoutManipulators::Tab << i << ":" << pim_content[i];
piCout << "index:"; // piCout << "index:";
for (size_t i = 0; i < pim_index.size(); ++i) // for (size_t i = 0; i < pim_index.size(); ++i)
piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index; // piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index;
} }
protected: protected:
struct MapIndex { // struct MapIndex {
MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;} // MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;}
Key key; // Key key;
size_t index; // size_t index;
bool operator ==(const MapIndex & s) const {return key == s.key;} // bool operator ==(const MapIndex & s) const {return key == s.key;}
bool operator !=(const MapIndex & s) const {return key != s.key;} // bool operator !=(const MapIndex & s) const {return key != s.key;}
bool operator <(const MapIndex & s) const {return key < s.key;} // bool operator <(const MapIndex & s) const {return key < s.key;}
bool operator >(const MapIndex & s) const {return key > s.key;} // bool operator >(const MapIndex & s) const {return key > s.key;}
}; // };
template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v); // template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v); // template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const { ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
ssize_t mid; ssize_t mid;
while (first <= last) { while (first <= last) {
mid = (first + last) / 2; mid = (first + last) / 2;
if (key > pim_index[mid].key) first = mid + 1; if (key > pim_content[mid].first) first = mid + 1;
else if (key < pim_index[mid].key) last = mid - 1; else if (key < pim_content[mid].first) last = mid - 1;
else {found = true; return mid;} else {found = true; return mid;}
} }
found = false; found = false;
return first; return first;
} }
void _sort() {piQuickSort<MapIndex>(pim_index.data(), pim_index.size_s() - 1);}
ssize_t _find(const Key & k, bool & found) const { ssize_t _find(const Key & k, bool & found) const {
if (pim_index.isEmpty()) { if (pim_content.isEmpty()) {
found = false; found = false;
return 0; return 0;
} }
return binarySearch(0, pim_index.size_s() - 1, k, found); return binarySearch(0, pim_content.size_s() - 1, k, found);
} }
void _remove(ssize_t index) { void _remove(ssize_t index) {
//if (index >= pim_index.size()) return; pim_content.remove(index);
size_t ci = pim_index[index].index, bi = pim_index.size() - 1;
pim_index.remove(index);
for (size_t i = 0; i < pim_index.size(); ++i)
if (pim_index[i].index == bi) {
pim_index[i].index = ci;
break;
}
piSwap<T>(pim_content[ci], pim_content.back());
pim_content.resize(pim_index.size());
} }
const value_type _pair(ssize_t index) const { const value_type _pair(ssize_t index) const {
if (index < 0 || index >= pim_index.size_s()) if (index < 0 || index >= pim_content.size_s()) return value_type();
return value_type(); return pim_content[index];
//piCout << "_pair" << index << pim_index[index].index;
return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
} }
Key & _key(ssize_t index) {return pim_index[index].key;} Key & _key(ssize_t index) {return pim_content[index].first;}
T & _value(ssize_t index) {return pim_content[pim_index[index].index];} T & _value(ssize_t index) {return pim_content[index].second;}
PIVector<T> pim_content; PIDeque<PIPair<Key, T>> pim_content;
PIDeque<MapIndex> pim_index;
}; };

View File

@@ -1,8 +1,17 @@
/*! \file pipair.h //! \addtogroup Containers
* \brief pair //! \{
* //! \file pipair.h
* This file declare PIPair //! \brief
*/ //! \~english Declares \a PIPair
//! \~russian Объявление \a PIPair
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
pair pair
@@ -27,30 +36,109 @@
#include "picout.h" #include "picout.h"
class PICout;
//! \addtogroup Containers
//! \{
//! \class PIPair
//! \brief
//! \~english Class template that provides a way to store two heterogeneous objects as a single unit.
//! \~russian Класс, который позволяет хранить два разнородных объекта как единое целое.
//! \~\}
//! \details
//! \~english
//! \~russian
//! \~\sa \a PIMap
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
class PIPair { class PIPair {
public: public:
PIPair() {first = Type0(); second = Type1();}
PIPair(std::tuple<Type0, Type1> tuple) {first = std::get<0>(tuple); second = std::get<1>(tuple);} //! \~english Constructs an empty PIPair.
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} //! \~russian Создает пустой PIPair.
PIPair() : first(), second() {}
//! \~english Constructs PIPair from [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple).
//! \~russian Создает PIPair из [std::tuple](https://ru.cppreference.com/w/cpp/utility/tuple).
PIPair(std::tuple<Type0, Type1> tuple) {
first = std::get<0>(tuple);
second = std::get<1>(tuple);
}
//! \~english Constructs PIPair from values `value0` and `value1`.
//! \~russian Создает PIPair из `value0` и `value1`.
PIPair(const Type0 & value0, const Type1 & value1) {
first = value0;
second = value1;
}
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
PIPair(Type0 && value0, Type1 && value1) {
first = std::move(value0);
second = std::move(value1);
}
//! \~english First element.
//! \~russian Первый элемент.
Type0 first; Type0 first;
//! \~english Second element.
//! \~russian Второй элемент.
Type1 second; Type1 second;
}; };
//! \~english Compare operator with PIPair.
//! \~russian Оператор сравнения с PIPair.
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;} inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {
return (value0.first == value1.first) && (value0.second == value1.second);
}
//! \~english Compare operator with PIPair.
//! \~russian Оператор сравнения с PIPair.
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first == value1.first) && (value0.second == value1.second);} inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {
template<typename Type0, typename Type1> return (value0.first != value1.first) || (value0.second != value1.second);
inline bool operator !=(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first != value1.first) || (value0.second != value1.second);} }
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;} inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {
s << "(" << v.first << ", " << v.second << ")";
return s;
}
#endif #endif
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename Type0, typename Type1> template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {
s.space();
s.setControl(0, true);
s << "(" << v.first << ", " << v.second << ")";
s.restoreControl();
return s;
}
//! \~english Creates \a PIPair object, deducing the target type from the types of arguments.
//! \~russian Создает \a PIPair выводя типы из аргументов.
//! \~\details
//! \~\code
//! auto p = createPIPair(1, 'a');
//! piCout << p; // (1, a)
//! \endcode
template< class T1, class T2 >
PIPair<T1,T2> createPIPair(const T1 & f, const T2 & s) {
return PIPair<T1,T2>(f, s);
}
//! \~english Creates \a PIPair object, deducing the target type from the types of arguments.
//! \~russian Создает \a PIPair выводя типы из аргументов.
//! \sa \a createPIPair()
template< class T1, class T2 >
PIPair<T1,T2> createPIPair(T1 && f, T2 && s) {
return PIPair<T1,T2>(std::move(f), std::move(s));
}
#endif // PIPAIR_H #endif // PIPAIR_H

View File

@@ -1,4 +1,4 @@
/*! \file pideque.h /*! \file piqueue.h
* \brief Queue container * \brief Queue container
* *
* This file declare PIQueue * This file declare PIQueue

View File

@@ -49,42 +49,56 @@
//! The elements are stored contiguously, //! The elements are stored contiguously,
//! which means that elements can be accessed not only through iterators, //! which means that elements can be accessed not only through iterators,
//! but also using offsets to regular pointers to elements. //! but also using offsets to regular pointers to elements.
//! This means that a pointer to an element of a vector may be passed to any function //! This means that a pointer to an element of a PIVector may be passed to any function
//! that expects a pointer to an element of an array. //! that expects a pointer to an element of an array.
//! To add elements you can use functions \a append() and \a insert(), //! To add elements you can use functions \a append() and \a insert(),
//! to remove elements you can use functions \a remove() and \a clear(). //! to remove elements you can use functions \a remove() and \a removeOne(), \a removeWhere().
//! Change size by function \a resize(). //! Change size by function \a resize() and \a assign().
//! Items in an array are numbered, starting from zero.
//! This number is called the item's index.
//! So the first item has index 0, the last has index `size() - 1`.
//! A set of various convenient functions is also available for the array,
//! for example: \a indexOf(), \a contains(), \a entries(), \a isEmpty(), \a isNotEmpty(),
//! \a every(), \a any(), \a forEach(), \a indexWhere(), \a getRange(), \a sort(),
//! \a map(), \a reduce(), \a filter(), \a flatten(), \a reshape() and others.
//! //!
//! The storage of the vector is handled automatically, //! The storage of the PIVector is handled automatically,
//! being expanded as needed. //! being expanded as needed.
//! Vectors usually occupy more space than static arrays, //! PIVector usually occupy more space than static arrays,
//! because more memory is allocated to handle future growth. //! because more memory is allocated to handle future growth.
//! This way a vector does not need to reallocate each time an element is inserted, //! This way a PIVector does not need to reallocate each time an element is inserted,
//! but only when the additional memory is exhausted. //! but only when the additional memory is exhausted.
//! The total amount of allocated memory can be queried using \a capacity() function. //! The total amount of allocated memory can be queried using \a capacity() function.
//! Reallocations are usually costly operations in terms of performance. //! Reallocations are usually costly operations in terms of performance.
//! The \a reserve() function can be used to eliminate reallocations //! The \a reserve() function can be used to eliminate reallocations
//! if the number of elements is known beforehand. //! if the number of elements is known beforehand.
//! //!
//! The complexity (efficiency) of common operations on vectors is as follows: //! The complexity (efficiency) of common operations on PIVector is as follows:
//! - Random access - constant 𝓞(1) //! - Random access - constant 𝓞(1)
//! - Insertion or removal of elements at the end - amortized constant 𝓞(1) //! - Insertion or removal of elements at the end - amortized constant 𝓞(1)
//! - Insertion or removal of elements - linear in the distance to the end of the vector 𝓞(n) //! - Insertion or removal of elements - linear in the distance to the end of the array 𝓞(n)
//! //!
//! \~russian //! \~russian
//! Элементы хранятся непрерывно, а значит доступны не только через итераторы, //! Элементы хранятся непрерывно, а значит доступны не только через итераторы,
//! но и с помощью смещений для обычных указателей на элементы. //! но и с помощью смещений для обычных указателей на элементы.
//! Это означает, что указатель на элемент вектора может передаваться в любую функцию, //! Это означает, что указатель на элемент PIVector может передаваться в любую функцию,
//! ожидающую указатель на элемент массива. //! ожидающую указатель на элемент массива.
//! Добавить элементы можно с помощью функции \a append() или \a insert(), //! Добавить элементы можно с помощью функции \a append() или \a insert(),
//! а удалить с помощью \a remove() или \a clear(). //! а удалить с помощью \a remove() или \a removeOne(), \a removeWhere().
//! Изменить размер можно функцией \a resize(). //! Изменить размер можно функцией \a resize() или \a assign().
//! Массив индексируется с нуля:
//! первый элемент массива имеет индекс, равный `0`,
//! а индекс последнего элемента равен `size() - 1`.
//! Также для массива доступен набор различных удобных функций,
//! например: \a indexOf(), \a contains(), \a entries(), \a isEmpty(), \a isNotEmpty(),
//! \a every(), \a any(), \a forEach(), \a indexWhere(), \a getRange(), \a sort(),
//! \a map(), \a reduce(), \a filter(), \a flatten(), \a reshape() и другие.
//! //!
//! Память вектора обрабатывается автоматически, //! Память PIVector обрабатывается автоматически,
//! расширяясь по мере необходимости. //! расширяясь по мере необходимости.
//! Векторы обычно занимают больше места, чем статические массивы, //! Векторы обычно занимают больше места, чем статические массивы,
//! поскольку больше памяти выделяется для обработки будущего роста. //! поскольку больше памяти выделяется для обработки будущего роста.
//! Таким образом, память для вектора требуется выделять //! Таким образом, память для PIVector требуется выделять
//! не при каждой вставке элемента, //! не при каждой вставке элемента,
//! а только после исчерпания дополнительной памяти. //! а только после исчерпания дополнительной памяти.
//! Общий объём выделенной памяти можно получить с помощью функции \a capacity(). //! Общий объём выделенной памяти можно получить с помощью функции \a capacity().
@@ -94,26 +108,30 @@
//! Функцию \a reserve() можно использовать для исключения выделения памяти, //! Функцию \a reserve() можно использовать для исключения выделения памяти,
//! если количество элементов известно заранее. //! если количество элементов известно заранее.
//! //!
//! Сложность (эффективность) обычных операций над векторами следующая: //! Сложность (эффективность) обычных операций над PIVector следующая:
//! - Произвольный доступ — постоянная 𝓞(1) //! - Произвольный доступ — постоянная 𝓞(1)
//! - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1) //! - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1)
//! - Вставка и удаление элементов — линейная по расстоянию до конца вектора 𝓞(n) //! - Вставка и удаление элементов — линейная по расстоянию до конца массива 𝓞(n)
//! //!
//! \~\sa \a PIDeueue, \a PIMap //! \~\sa \a PIDeque, \a PIMap
template <typename T> template <typename T>
class PIVector { class PIVector {
public: public:
typedef bool (*CompareFunc)(const T & , const T & ); typedef bool (*CompareFunc)(const T & , const T & );
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
//! \~\brief //! \~english Constructs an empty array.
//! \~english Constructs an empty vector.
//! \~russian Создает пустой массив. //! \~russian Создает пустой массив.
inline PIVector(): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
} }
//! \~\brief //! \~english Contructs array from raw `data`.
//! \~english Contructs vector from raw `data`.
//! This constructor reserve `size` and copy from `data` pointer. //! This constructor reserve `size` and copy from `data` pointer.
//! \~russian Создает массив из указателя на данные `data` и размер `size`. //! \~russian Создает массив из указателя на данные `data` и размер `size`.
//! То есть выделяет память для `size` элементов и копирует данные из указателя `data`. //! То есть выделяет память для `size` элементов и копирует данные из указателя `data`.
@@ -123,7 +141,6 @@ public:
newT(piv_data, data, piv_size); newT(piv_data, data, piv_size);
} }
//! \~\brief
//! \~english Copy constructor. //! \~english Copy constructor.
//! \~russian Копирующий конструктор. //! \~russian Копирующий конструктор.
inline PIVector(const PIVector<T> & v): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(const PIVector<T> & v): piv_data(0), piv_size(0), piv_rsize(0) {
@@ -132,8 +149,7 @@ public:
newT(piv_data, v.piv_data, piv_size); newT(piv_data, v.piv_data, piv_size);
} }
//! \~\brief //! \~english Contructs array from
//! \~english Contructs vector from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list). //! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Создает массив из //! \~russian Создает массив из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list). //! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
@@ -148,16 +164,14 @@ public:
newT(piv_data, init_list.begin(), init_list.size()); newT(piv_data, init_list.begin(), init_list.size());
} }
//! \~\brief //! \~english Contructs array with size `size` filled elements `e`.
//! \~english Contructs vector with size `size` filled elements `e`.
//! \~russian Создает массив из `size` элементов заполненных `e`. //! \~russian Создает массив из `size` элементов заполненных `e`.
inline PIVector(size_t size, const T & e = T()): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(size_t size, const T & e = T()): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(size, e); resize(size, e);
} }
//! \~\brief //! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
//! \~english Contructs vector with size `size` and elements created by function `f(size_t i)`.
//! \~russian Создает массив из `size` элементов созданных функцией `f(size_t i)`. //! \~russian Создает массив из `size` элементов созданных функцией `f(size_t i)`.
//! \~\details //! \~\details
//! \~english Can use //! \~english Can use
@@ -175,7 +189,6 @@ public:
resize(size, f); resize(size, f);
} }
//! \~\brief
//! \~english Move constructor. //! \~english Move constructor.
//! \~russian Перемещающий конструктор. //! \~russian Перемещающий конструктор.
inline PIVector(PIVector<T> && v): piv_data(v.piv_data), piv_size(v.piv_size), piv_rsize(v.piv_rsize) { inline PIVector(PIVector<T> && v): piv_data(v.piv_data), piv_size(v.piv_size), piv_rsize(v.piv_rsize) {
@@ -191,7 +204,6 @@ public:
_reset(); _reset();
} }
//! \~\brief
//! \~english Assign operator. //! \~english Assign operator.
//! \~russian Оператор присваивания. //! \~russian Оператор присваивания.
inline PIVector<T> & operator =(const PIVector<T> & v) { inline PIVector<T> & operator =(const PIVector<T> & v) {
@@ -203,7 +215,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Assign move operator. //! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания. //! \~russian Оператор перемещающего присваивания.
inline PIVector<T> & operator =(PIVector<T> && v) { inline PIVector<T> & operator =(PIVector<T> && v) {
@@ -211,14 +222,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Reshape order enum for \a reshape() function.
//! \~russian Порядок обхода для функции изменения размерности \a reshape().
enum ReshapeOrder {
byRow,
byColumn
};
class iterator { class iterator {
friend class PIVector<T>; friend class PIVector<T>;
private: private:
@@ -239,30 +242,73 @@ public:
inline T & operator ->() {return (*parent)[pos];} inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline iterator & operator ++() {++pos; return *this;} inline iterator & operator ++() {
inline iterator & operator ++(int) {const auto tmp = *this; ++*this; return tmp;} ++pos;
inline iterator & operator --() {--pos; return *this;} return *this;
inline iterator & operator --(int) {const auto tmp = *this; --*this; return tmp;} }
inline iterator operator ++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline iterator & operator --() {
--pos;
return *this;
}
inline iterator operator --(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline iterator & operator +=(const iterator & it) {pos += it.pos; return *this;} inline iterator & operator +=(const iterator & it) {
inline iterator & operator +=(size_t p) {pos += p; return *this;} pos += it.pos;
inline iterator & operator -=(const iterator & it) {pos -= it.pos; return *this;} return *this;
inline iterator & operator -=(size_t p) {pos -= p; return *this;} }
inline iterator & operator +=(size_t p) {
pos += p;
return *this;
}
inline iterator & operator -=(const iterator & it) {
pos -= it.pos;
return *this;
}
inline iterator & operator -=(size_t p) {
pos -= p;
return *this;
}
friend inline iterator operator -(const iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
friend inline iterator operator -(size_t p, const iterator & it) {return it - p;} friend inline iterator operator -(size_t p, const iterator & it) {return it - p;}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {return it1.pos - it2.pos;} friend inline iterator operator -(const iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
return it1.pos - it2.pos;
}
friend inline iterator operator +(const iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;} friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
friend inline iterator operator +(const iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const iterator & it) const {return (pos == it.pos);} inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const iterator & it) const {return (pos != it.pos);} inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const iterator & it1, const iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const iterator & it1, const iterator & it2) {
friend inline bool operator <=(const iterator & it1, const iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const iterator & it1, const iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const iterator & it1, const iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const iterator & it1, const iterator & it2) {
void dump() {piCout << parent << pos;} return it1.pos <= it2.pos;
}
friend inline bool operator >(const iterator & it1, const iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const iterator & it1, const iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
class const_iterator { class const_iterator {
@@ -283,29 +329,73 @@ public:
inline const T & operator *() const {return (*parent)[pos];} inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline const_iterator & operator ++() {++pos; return *this;} inline const_iterator & operator ++() {
inline const_iterator & operator ++(int) {const auto tmp = *this; ++*this; return tmp;} ++pos;
inline const_iterator & operator --() {--pos; return *this;} return *this;
inline const_iterator & operator --(int) {const auto tmp = *this; --*this; return tmp;} }
inline const_iterator operator ++(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_iterator & operator --() {
--pos;
return *this;
}
inline const_iterator operator --(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_iterator & operator +=(const const_iterator & it) {pos += it.pos; return *this;} inline const_iterator & operator +=(const const_iterator & it) {
inline const_iterator & operator +=(size_t p) {pos += p; return *this;} pos += it.pos;
inline const_iterator & operator -=(const const_iterator & it) {pos -= it.pos; return *this;} return *this;
inline const_iterator & operator -=(size_t p) {pos -= p; return *this;} }
inline const_iterator & operator +=(size_t p) {
pos += p;
return *this;
}
inline const_iterator & operator -=(const const_iterator & it) {
pos -= it.pos;
return *this;
}
inline const_iterator & operator -=(size_t p) {
pos -= p;
return *this;
}
friend inline const_iterator operator -(const const_iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
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;}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {return it1.pos - it2.pos;} friend inline const_iterator operator -(const const_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
return it1.pos - it2.pos;
}
friend inline const_iterator operator +(const const_iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
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;}
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);} inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);} inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {
friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
class reverse_iterator { class reverse_iterator {
@@ -328,29 +418,73 @@ public:
inline T & operator ->() {return (*parent)[pos];} inline T & operator ->() {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline reverse_iterator & operator ++() {--pos; return *this;} inline reverse_iterator & operator ++() {
inline reverse_iterator & operator ++(int) {const auto tmp = *this; --*this; return tmp;} --pos;
inline reverse_iterator & operator --() {++pos; return *this;} return *this;
inline reverse_iterator & operator --(int) {const auto tmp = *this; ++*this; return tmp;} }
inline reverse_iterator operator ++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline reverse_iterator & operator --() {
++pos;
return *this;
}
inline reverse_iterator operator --(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline reverse_iterator & operator +=(const reverse_iterator & it) {pos -= it.pos; return *this;} inline reverse_iterator & operator +=(const reverse_iterator & it) {
inline reverse_iterator & operator +=(size_t p) {pos -= p; return *this;} pos -= it.pos;
inline reverse_iterator & operator -=(const reverse_iterator & it) {pos += it.pos; return *this;} return *this;
inline reverse_iterator & operator -=(size_t p) {pos += p; return *this;} }
inline reverse_iterator & operator +=(size_t p) {
pos -= p;
return *this;
}
inline reverse_iterator & operator -=(const reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline reverse_iterator & operator -=(size_t p) {
pos += p;
return *this;
}
friend inline reverse_iterator operator -(const reverse_iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
friend inline reverse_iterator operator -(size_t p, const reverse_iterator & it) {return it - p;} friend inline reverse_iterator operator -(size_t p, const reverse_iterator & it) {return it - p;}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {return it2.pos - it1.pos;} friend inline reverse_iterator operator -(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;} friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {
friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
class const_reverse_iterator { class const_reverse_iterator {
@@ -370,43 +504,85 @@ public:
inline const T & operator *() const {return (*parent)[pos];} inline const T & operator *() const {return (*parent)[pos];}
inline const T & operator ->() const {return (*parent)[pos];} inline const T & operator ->() const {return (*parent)[pos];}
inline const_reverse_iterator & operator ++() {--pos; return *this;} inline const_reverse_iterator & operator ++() {
inline const_reverse_iterator & operator ++(int) {const auto tmp = *this; --*this; return tmp;} --pos;
inline const_reverse_iterator & operator --() {++pos; return *this;} return *this;
inline const_reverse_iterator & operator --(int) {const auto tmp = *this; ++*this; return tmp;} }
inline const_reverse_iterator operator ++(int) {
auto tmp = *this;
--*this;
return tmp;
}
inline const_reverse_iterator & operator --() {
++pos;
return *this;
}
inline const_reverse_iterator operator --(int) {
auto tmp = *this;
++*this;
return tmp;
}
inline const_reverse_iterator & operator +=(const const_reverse_iterator & it) {pos -= it.pos; return *this;} inline const_reverse_iterator & operator +=(const const_reverse_iterator & it) {
inline const_reverse_iterator & operator +=(size_t p) {pos -= p; return *this;} pos -= it.pos;
inline const_reverse_iterator & operator -=(const const_reverse_iterator & it) {pos += it.pos; return *this;} return *this;
inline const_reverse_iterator & operator -=(size_t p) {pos += p; return *this;} }
inline const_reverse_iterator & operator +=(size_t p) {
pos -= p;
return *this;
}
inline const_reverse_iterator & operator -=(const const_reverse_iterator & it) {
pos += it.pos;
return *this;
}
inline const_reverse_iterator & operator -=(size_t p) {
pos += p;
return *this;
}
friend inline const_reverse_iterator operator -(const const_reverse_iterator & it, size_t p) {auto tmp = it; tmp -= p; return tmp;}
friend inline const_reverse_iterator operator -(size_t p, const const_reverse_iterator & it) {return it - p;} friend inline const_reverse_iterator operator -(size_t p, const const_reverse_iterator & it) {return it - p;}
friend inline std::ptrdiff_t operator -(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it2.pos - it1.pos;} friend inline const_reverse_iterator operator -(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp -= p;
return tmp;
}
friend inline std::ptrdiff_t operator -(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it2.pos - it1.pos;
}
friend inline const_reverse_iterator operator +(const const_reverse_iterator & it, size_t p) {auto tmp = it; tmp += p; return tmp;}
friend inline const_reverse_iterator operator +(size_t p, const const_reverse_iterator & it) {return it + p;} friend inline const_reverse_iterator operator +(size_t p, const const_reverse_iterator & it) {return it + p;}
friend inline const_reverse_iterator operator +(const const_reverse_iterator & it, size_t p) {
auto tmp = it;
tmp += p;
return tmp;
}
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos < it2.pos;} friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos <= it2.pos;} return it1.pos < it2.pos;
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos > it2.pos;} }
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {return it1.pos >= it2.pos;} friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos <= it2.pos;
}
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos > it2.pos;
}
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
return it1.pos >= it2.pos;
}
}; };
//! \~\brief
//! \~english Iterator to the first element. //! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент. //! \~russian Итератор на первый элемент.
//! \~\details ![begin, end](doc/images/pivector_begin.png) //! \~\details ![begin, end](doc/images/pivector_begin.png)
//! //!
//! \~english If the vector is empty, the returned iterator is equal to \a end(). //! \~english If the array is empty, the returned iterator is equal to \a end().
//! \~russian Если массив - пуст, возвращаемый итератор будет равен \a end(). //! \~russian Если массив пустой, возвращаемый итератор будет равен \a end().
//! \~\return \ref stl_iterators //! \~\return \ref stl_iterators
//! \~\sa \a end(), \a rbegin(), \a rend() //! \~\sa \a end(), \a rbegin(), \a rend()
inline iterator begin() {return iterator(this, 0);} inline iterator begin() {return iterator(this, 0);}
//! \~\brief
//! \~english Iterator to the element following the last element. //! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом. //! \~russian Итератор на элемент, следующий за последним элементом.
//! \~\details ![begin, end](doc/images/pivector_begin.png) //! \~\details ![begin, end](doc/images/pivector_begin.png)
@@ -422,13 +598,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, piv_size);} inline const_iterator end() const {return const_iterator(this, piv_size);}
//! \~\brief //! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~english Returns a reverse iterator to the first element of the reversed vector.
//! \~russian Обратный итератор на первый элемент. //! \~russian Обратный итератор на первый элемент.
//! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png) //! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png)
//! //!
//! \~english It corresponds to the last element of the non-reversed vector. //! \~english It corresponds to the last element of the non-reversed array.
//! If the vector is empty, the returned iterator is equal to \a rend(). //! If the array is empty, the returned iterator is equal to \a rend().
//! \~russian Итератор для прохода массива в обратном порядке. //! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на последний элемент. //! Указывает на последний элемент.
//! Если массив пустой, то совпадает с итератором \a rend(). //! Если массив пустой, то совпадает с итератором \a rend().
@@ -436,13 +611,12 @@ public:
//! \~\sa \a rend(), \a begin(), \a end() //! \~\sa \a rend(), \a begin(), \a end()
inline reverse_iterator rbegin() {return reverse_iterator(this, piv_size - 1);} inline reverse_iterator rbegin() {return reverse_iterator(this, piv_size - 1);}
//! \~\brief
//! \~english Returns a reverse iterator to the element //! \~english Returns a reverse iterator to the element
//! following the last element of the reversed vector. //! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент, следующий за последним элементом. //! \~russian Обратный итератор на элемент, следующий за последним элементом.
//! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png) //! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png)
//! //!
//! \~english It corresponds to the element preceding the first element of the non-reversed vector. //! \~english It corresponds to the element preceding the first element of the non-reversed array.
//! This element acts as a placeholder, attempting to access it results in undefined behavior. //! This element acts as a placeholder, attempting to access it results in undefined behavior.
//! \~russian Итератор для прохода массива в обратном порядке. //! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на элемент, предшествующий первому элементу. //! Указывает на элемент, предшествующий первому элементу.
@@ -455,25 +629,21 @@ public:
inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, piv_size - 1);} inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, piv_size - 1);}
inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
//! \~\brief
//! \~english Number of elements in the container. //! \~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 piv_size;} inline size_t size() const {return piv_size;}
//! \~\brief
//! \~english Number of elements in the container as 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 ssize_t size_s() const {return piv_size;} inline ssize_t size_s() const {return piv_size;}
//! \~\brief
//! \~english Same as \a size(). //! \~english Same as \a size().
//! \~russian Синоним \a size(). //! \~russian Синоним \a size().
//! \~\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 piv_size;} inline size_t length() const {return piv_size;}
//! \~\brief
//! \~english Number of elements that the container has currently allocated space for. //! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память контейнером. //! \~russian Количество элементов, для которого сейчас выделена память контейнером.
//! \~\details //! \~\details
@@ -482,7 +652,6 @@ public:
//! \~\sa \a reserve(), \a size(), \a size_s() //! \~\sa \a reserve(), \a size(), \a size_s()
inline size_t capacity() const {return piv_rsize;} inline size_t capacity() const {return piv_rsize;}
//! \~\brief
//! \~english Checks if the container has no elements. //! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли контейнер. //! \~russian Проверяет пуст ли контейнер.
//! \~\return //! \~\return
@@ -491,7 +660,6 @@ public:
//! \~\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 (piv_size == 0);} inline bool isEmpty() const {return (piv_size == 0);}
//! \~\brief
//! \~english Checks if the container has elements. //! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли контейнер. //! \~russian Проверяет не пуст ли контейнер.
//! \~\return //! \~\return
@@ -500,7 +668,6 @@ public:
//! \~\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 (piv_size > 0);} inline bool isNotEmpty() const {return (piv_size > 0);}
//! \~\brief
//! \~english Tests whether at least one element in the array //! \~english Tests whether at least one element in the array
//! passes the test implemented by the provided function `test`. //! passes the test implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяет ли какой-либо элемент массива условию, //! \~russian Проверяет, удовлетворяет ли какой-либо элемент массива условию,
@@ -518,7 +685,7 @@ public:
//! piCout << v.any([](int e){return e % 2 == 0;}); // true //! piCout << v.any([](int e){return e % 2 == 0;}); // true
//! piCout << v.any([](int e){return e == 3;}); // false //! piCout << v.any([](int e){return e == 3;}); // false
//! \endcode //! \endcode
//! \~\sa \a every(), \a contains(), \a etries(), \a forEach() //! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
inline bool any(std::function<bool(const T & e)> test) const { inline bool any(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
if (test(piv_data[i])) return true; if (test(piv_data[i])) return true;
@@ -526,7 +693,6 @@ public:
return false; return false;
} }
//! \~\brief
//! \~english Tests whether all elements in the array passes the test //! \~english Tests whether all elements in the array passes the test
//! implemented by the provided function `test`. //! implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяют ли все элементы массива условию, //! \~russian Проверяет, удовлетворяют ли все элементы массива условию,
@@ -552,7 +718,6 @@ public:
return true; return true;
} }
//! \brief
//! \~english Full access to element by `index`. //! \~english Full access to element by `index`.
//! \~russian Полный доступ к элементу по индексу `index`. //! \~russian Полный доступ к элементу по индексу `index`.
//! \~\details //! \~\details
@@ -572,7 +737,6 @@ public:
inline T & operator [](size_t index) {return piv_data[index];} inline T & operator [](size_t index) {return piv_data[index];}
inline const T & operator [](size_t index) const {return piv_data[index];} inline const T & operator [](size_t index) const {return piv_data[index];}
//! \brief
//! \~english Read only access to element by `index`. //! \~english Read only access to element by `index`.
//! \~russian Доступ исключительно на чтение к элементу по индексу `index`. //! \~russian Доступ исключительно на чтение к элементу по индексу `index`.
//! \~\details //! \~\details
@@ -584,12 +748,11 @@ public:
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти. //! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const T & at(size_t index) const {return piv_data[index];} inline const T & at(size_t index) const {return piv_data[index];}
//! \brief
//! \~english Last element. //! \~english Last element.
//! \~russian Последний элемент массива. //! \~russian Последний элемент массива.
//! \~\details //! \~\details
//! \~english Returns a reference to the last item in the vector. //! \~english Returns a reference to the last item in the array.
//! This function assumes that the vector isn't empty. //! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior. //! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на последний элемент в массиве. //! \~russian Возвращает ссылку на последний элемент в массиве.
//! Эта функция предполагает, что массив не пустой. //! Эта функция предполагает, что массив не пустой.
@@ -597,12 +760,11 @@ public:
inline T & back() {return piv_data[piv_size - 1];} inline T & back() {return piv_data[piv_size - 1];}
inline const T & back() const {return piv_data[piv_size - 1];} inline const T & back() const {return piv_data[piv_size - 1];}
//! \brief
//! \~english Last element. //! \~english Last element.
//! \~russian Первый элемент массива. //! \~russian Первый элемент массива.
//! \~\details //! \~\details
//! \~english Returns a reference to the last item in the vector. //! \~english Returns a reference to the last item in the array.
//! This function assumes that the vector isn't empty. //! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior. //! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на пенрвый элемент в массиве. //! \~russian Возвращает ссылку на пенрвый элемент в массиве.
//! Эта функция предполагает, что массив не пустой. //! Эта функция предполагает, что массив не пустой.
@@ -610,27 +772,20 @@ public:
inline T & front() {return piv_data[0];} inline T & front() {return piv_data[0];}
inline const T & front() const {return piv_data[0];} inline const T & front() const {return piv_data[0];}
//! \brief //! \~english Compare operator with array `v`.
//! \~english Compare operator with vector `t`. //! \~russian Оператор сравнения с массивом `v`.
//! \~russian Оператор сравнения с массивом `t`. inline bool operator ==(const PIVector<T> & v) const {
inline bool operator ==(const PIVector<T> & t) const { if (piv_size != v.piv_size) return false;
if (piv_size != t.piv_size) {
return false;
}
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
if (t[i] != piv_data[i]) { if (v[i] != piv_data[i]) return false;
return false;
}
} }
return true; return true;
} }
//! \brief //! \~english Compare operator with array `v`.
//! \~english Compare operator with vector `t`. //! \~russian Оператор сравнения с массивом `v`.
//! \~russian Оператор сравнения с массивом `t`. inline bool operator !=(const PIVector<T> & v) const {return !(*this == v);}
inline bool operator !=(const PIVector<T> & t) const {return !(*this == t);}
//! \~\brief
//! \~english Tests if element `e` exists in the array. //! \~english Tests if element `e` exists in the array.
//! \~russian Проверяет наличие элемента `e` в массиве. //! \~russian Проверяет наличие элемента `e` в массиве.
//! \~\details //! \~\details
@@ -662,7 +817,7 @@ public:
//! otherwise it returns **false**. //! otherwise it returns **false**.
//! \~russian **true** если элемент `e` присутствует в массиве, //! \~russian **true** если элемент `e` присутствует в массиве,
//! в остальных случаях **false**. //! в остальных случаях **false**.
//! \~\sa \a every(), \a any(), \a etries(), \a forEach() //! \~\sa \a every(), \a any(), \a entries(), \a forEach()
inline bool contains(const T & e, ssize_t start = 0) const { inline bool contains(const T & e, ssize_t start = 0) const {
if (start < 0) { if (start < 0) {
start = piv_size + start; start = piv_size + start;
@@ -674,7 +829,6 @@ public:
return false; return false;
} }
//! \~\brief
//! \~english Count elements equal `e` in the array. //! \~english Count elements equal `e` in the array.
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. //! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
//! \~\details //! \~\details
@@ -712,7 +866,6 @@ public:
return ec; return ec;
} }
//! \~\brief
//! \~english Count elements in the array passes the test implemented by the provided function `test`. //! \~english Count elements in the array passes the test implemented by the provided function `test`.
//! \~russian Подсчитывает количество элементов в массиве, //! \~russian Подсчитывает количество элементов в массиве,
//! проходящих по условию, заданному в передаваемой функции `test`. //! проходящих по условию, заданному в передаваемой функции `test`.
@@ -747,7 +900,6 @@ public:
return ec; return ec;
} }
//! \~\brief
//! \~english Returns the first index at which a given element `e` //! \~english Returns the first index at which a given element `e`
//! can be found in the array, or `-1` if it is not present. //! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает первый индекс, по которому данный элемент `e` //! \~russian Возвращает первый индекс, по которому данный элемент `e`
@@ -788,7 +940,6 @@ public:
return -1; return -1;
} }
//! \~\brief
//! \~english Returns the first index passes the test implemented by the provided function `test`, //! \~english Returns the first index passes the test implemented by the provided function `test`,
//! or `-1` if it is not present. //! or `-1` if it is not present.
//! can be found in the array, or `-1` if it is not present. //! can be found in the array, or `-1` if it is not present.
@@ -828,7 +979,6 @@ public:
return -1; return -1;
} }
//! \~\brief
//! \~english Returns the last index at which a given element `e` //! \~english Returns the last index at which a given element `e`
//! can be found in the array, or `-1` if it is not present. //! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает последний индекс, по которому данный элемент `e` //! \~russian Возвращает последний индекс, по которому данный элемент `e`
@@ -872,7 +1022,6 @@ public:
return -1; return -1;
} }
//! \~\brief
//! \~english Returns the last index passes the test implemented by the provided function `test`, //! \~english Returns the last index passes the test implemented by the provided function `test`,
//! or `-1` if it is not present. //! or `-1` if it is not present.
//! \~russian Возвращает последний индекс элемента проходящего по условию, //! \~russian Возвращает последний индекс элемента проходящего по условию,
@@ -907,7 +1056,6 @@ public:
return -1; return -1;
} }
//! \~\brief
//! \~english Pointer to array //! \~english Pointer to array
//! \~russian Указатель на память массива //! \~russian Указатель на память массива
//! \~\details //! \~\details
@@ -918,17 +1066,16 @@ public:
//! \~\code //! \~\code
//! PIVector<int> v{2, 5, 9, 2}; //! PIVector<int> v{2, 5, 9, 2};
//! int a[2] = {12, 13}; //! int a[2] = {12, 13};
//! memcpy(vec.data(1), carr, 2 * sizeof(int)); //! memcpy(vec.data(1), a, 2 * sizeof(int));
//! piCout << v; // {2, 12, 13, 2} //! piCout << v; // {2, 12, 13, 2}
//! \endcode //! \endcode
inline T * data(size_t index = 0) {return &(piv_data[index]);} inline T * data(size_t index = 0) {return &(piv_data[index]);}
//! \~\brief
//! \~english Read only pointer to array //! \~english Read only pointer to array
//! \~russian Указатель на память массива только для чтения. //! \~russian Указатель на память массива только для чтения.
//! \~\details //! \~\details
//! \~english The pointer can be used to access and modify the items in the vector. //! \~english The pointer can be used to access and modify the items in the array.
//! The pointer remains valid as long as the vector isn't reallocated. //! The pointer remains valid as long as the array isn't reallocated.
//! Optional argument `index` the position in this array, //! Optional argument `index` the position in this array,
//! where is pointer. Default: start of array. //! where is pointer. Default: start of array.
//! \~russian Указатель можно использовать для доступа и изменения элементов в массиве. //! \~russian Указатель можно использовать для доступа и изменения элементов в массиве.
@@ -943,7 +1090,6 @@ public:
//! \endcode //! \endcode
inline const T * data(size_t index = 0) const {return &(piv_data[index]);} inline const T * data(size_t index = 0) const {return &(piv_data[index]);}
//! \~\brief
//! \~english Creates sub-array of this array. //! \~english Creates sub-array of this array.
//! \~russian Создает подмассив, то есть кусок из текущего массива. //! \~russian Создает подмассив, то есть кусок из текущего массива.
//! \~english //! \~english
@@ -959,19 +1105,19 @@ public:
//! \~russian //! \~russian
//! Индекс начала должен лежать в диапазоне от `0` до `size()-1`. //! Индекс начала должен лежать в диапазоне от `0` до `size()-1`.
//! Если заданный размер подмассива превышает размер текущего массива, //! Если заданный размер подмассива превышает размер текущего массива,
//! то вернется подмассив меншего размера (`size()-index-1`). //! то вернется подмассив меньшего размера (`size()-index-1`).
PIVector<T> getRange(size_t index, size_t count) const { PIVector<T> getRange(size_t index, size_t count) const {
if (index >= piv_size || count == 0) return PIVector<T>(); if (index >= piv_size || count == 0) return PIVector<T>();
if (index + count > piv_size) count = piv_size - index; if (index + count > piv_size) count = piv_size - index;
return PIVector(&(piv_data[index]), count); return PIVector(&(piv_data[index]), count);
} }
//! \~\brief
//! \~english Clear array, remove all elements. //! \~english Clear array, remove all elements.
//! \~russian Очищает массив, удаляет все элементы. //! \~russian Очищает массив, удаляет все элементы.
//! \~\details //! \~\details
//! \~english Note: reserved memory will not be released. //! \~\note
//! \~russian Замечание: зарезервированная память не освободится. //! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize() //! \~\sa \a resize()
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value !std::is_trivially_copyable<T1>::value
@@ -989,9 +1135,8 @@ public:
return *this; return *this;
} }
//! \~\brief //! \~english Assigns element 'e' to all items in the array.
//! \~english Assigns element 'f' to all items in the array. //! \~russian Заполняет весь массив копиями элемента 'e'.
//! \~russian Заполняет весь массив копиями элемента 'f'.
//! \~\details //! \~\details
//! \code //! \code
//! PIVector<int> v{1, 3, 5}; //! PIVector<int> v{1, 3, 5};
@@ -999,16 +1144,15 @@ public:
//! piCout << v; // {7, 7, 7} //! piCout << v; // {7, 7, 7}
//! \endcode //! \endcode
//! \~\sa \a resize() //! \~\sa \a resize()
inline PIVector<T> & fill(const T & f = T()) { inline PIVector<T> & fill(const T & e = T()) {
deleteT(piv_data, piv_size); deleteT(piv_data, piv_size);
PIINTROSPECTION_CONTAINER_USED(T, piv_size) PIINTROSPECTION_CONTAINER_USED(T, piv_size)
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
elementNew(piv_data + i, f); elementNew(piv_data + i, e);
} }
return *this; return *this;
} }
//! \~\brief
//! \~english Assigns result of function 'f(size_t i)' to all items in the array. //! \~english Assigns result of function 'f(size_t i)' to all items in the array.
//! \~russian Заполняет весь массив результатом вызова функции 'f(size_t i)'. //! \~russian Заполняет весь массив результатом вызова функции 'f(size_t i)'.
//! \~\details //! \~\details
@@ -1027,16 +1171,13 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Same as \a fill(). //! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill(). //! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize() //! \~\sa \a fill(), \a resize()
inline PIVector<T> & assign(const T & f = T()) {return fill(f);} inline PIVector<T> & assign(const T & e = T()) {return fill(e);}
//! \~english First does `resize(new_size)` then `fill(e)`.
//! \~\brief //! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
//! \~english First does `resize(new_size)` then `fill(f)`.
//! \~russian Сначала делает `resize(new_size)` затем `fill(f)`.
//! \~\sa \a fill(), \a resize() //! \~\sa \a fill(), \a resize()
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value !std::is_trivially_copyable<T1>::value
@@ -1053,19 +1194,18 @@ public:
return fill(f); return fill(f);
} }
//! \~\brief //! \~english Sets size of the array, new elements are copied from `e`.
//! \~english Sets size of the array, new elements are copied from `f`. //! \~russian Устанавливает размер массива, новые элементы копируются из `e`.
//! \~russian Устанавливает размер массива, новые элементы копируются из `f`.
//! \~\details //! \~\details
//! \~english If `new_size` is greater than the current \a size(), //! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements are initialized from `f`. //! elements are added to the end; the new elements are initialized from `e`.
//! If `new_size` is less than the current \a size(), elements are removed from the end. //! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(), //! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и создаются из `f`. //! новые элементы добавляются в конец массива и создаются из `e`.
//! Если `new_size` меньше чем текущий размер массива \a size(), //! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива. //! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear() //! \~\sa \a size(), \a clear()
inline PIVector<T> & resize(size_t new_size, const T & f = T()) { inline PIVector<T> & resize(size_t new_size, const T & e = T()) {
if (new_size < piv_size) { if (new_size < piv_size) {
T * de = &(piv_data[new_size]); T * de = &(piv_data[new_size]);
deleteT(de, piv_size - new_size); deleteT(de, piv_size - new_size);
@@ -1076,13 +1216,12 @@ public:
alloc(new_size); alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os)) PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os; i < new_size; ++i) { for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, f); elementNew(piv_data + i, e);
} }
} }
return *this; return *this;
} }
//! \~\brief
//! \~english Sets size of the array, new elements created by function `f(size_t i)`. //! \~english Sets size of the array, new elements created by function `f(size_t i)`.
//! \~russian Устанавливает размер массива, новые элементы создаются функцией `f(size_t i)`. //! \~russian Устанавливает размер массива, новые элементы создаются функцией `f(size_t i)`.
//! \~\details //! \~\details
@@ -1129,7 +1268,6 @@ public:
newT(dst, src, size); newT(dst, src, size);
} }
//! \~\brief
//! \~english Attempts to allocate memory for at least `new_size` elements. //! \~english Attempts to allocate memory for at least `new_size` elements.
//! \~russian Резервируется память под как минимум `new_size` элементов. //! \~russian Резервируется память под как минимум `new_size` элементов.
//! \~\details //! \~\details
@@ -1152,7 +1290,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Inserts value `e` at `index` position in the array. //! \~english Inserts value `e` at `index` position in the array.
//! \~russian Вставляет значение `e` в позицию `index` в массиве. //! \~russian Вставляет значение `e` в позицию `index` в массиве.
//! \~\details //! \~\details
@@ -1175,7 +1312,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Inserts value `e` at `index` position in the array. //! \~english Inserts value `e` at `index` position in the array.
//! \~russian Вставляет значение `e` в позицию `index` в массиве. //! \~russian Вставляет значение `e` в позицию `index` в массиве.
//! \~\details //! \~\details
@@ -1193,7 +1329,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Inserts array `v` at `index` position in the array. //! \~english Inserts array `v` at `index` position in the array.
//! \~russian Вставляет массив `v` в позицию `index` в массиве. //! \~russian Вставляет массив `v` в позицию `index` в массиве.
//! \~\details //! \~\details
@@ -1217,9 +1352,28 @@ public:
return *this; return *this;
} }
//! \~\brief //! \~english Inserts the given elements at `index` position in the array.
//! \~russian Вставляет элементы в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
//! Inserts the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
//! Вставляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIVector<T> & insert(size_t index, std::initializer_list<T> init_list) {
ssize_t os = piv_size - index;
alloc(piv_size + init_list.size());
if (os > 0) {
memmove((void*)(&(piv_data[index + init_list.size()])), (const void*)(&(piv_data[index])), os * sizeof(T));
}
newT(piv_data + index, init_list.begin(), init_list.size());
return *this;
}
//! \~english Removes `count` elements from the middle of the array, starting at `index` position. //! \~english Removes `count` elements from the middle of the array, starting at `index` position.
//! \~russian Удаляет элементы из массива, начиная с позиции `index`, в количестве `count`. //! \~russian Удаляет элементы из массива, начиная с позиции `index` в количестве `count`.
//! \~\details //! \~\details
//! \code //! \code
//! PIVector<int> v{1, 3, 7, 5}; //! PIVector<int> v{1, 3, 7, 5};
@@ -1240,7 +1394,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Swaps array `v` other with this array. //! \~english Swaps array `v` other with this array.
//! \~russian Меняет местами массив `v` с этим массивом. //! \~russian Меняет местами массив `v` с этим массивом.
//! \~\details //! \~\details
@@ -1252,7 +1405,6 @@ public:
piSwap<size_t>(piv_rsize, v.piv_rsize); piSwap<size_t>(piv_rsize, v.piv_rsize);
} }
//! \~\brief
//! \~english Sorts the elements in non-descending order. //! \~english Sorts the elements in non-descending order.
//! \~russian Сортировка элементов в порядке возрастания. //! \~russian Сортировка элементов в порядке возрастания.
//! \~\details //! \~\details
@@ -1275,7 +1427,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Sorts the elements in non-descending order. //! \~english Sorts the elements in non-descending order.
//! \~russian Сортировка элементов в порядке возрастания. //! \~russian Сортировка элементов в порядке возрастания.
//! \~\details //! \~\details
@@ -1287,6 +1438,8 @@ public:
//! bool comp(const T &a, const T &b); //! bool comp(const T &a, const T &b);
//! \endcode //! \endcode
//! While the signature does not need to have const &, the function must not modify the objects passed to it. //! While the signature does not need to have const &, the function must not modify the objects passed to it.
//! The function must return `false` for identical elements,
//! otherwise, it will lead to undefined program behavior and memory errors.
//! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort). //! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort).
//! Complexity `O(N·log(N))`. //! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется. //! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
@@ -1297,6 +1450,8 @@ public:
//! bool comp(const T &a, const T &b); //! bool comp(const T &a, const T &b);
//! \endcode //! \endcode
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты. //! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
//! Функция обязана возвращать `false` для одинаковых элементов,
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). //! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`. //! Сложность сортировки `O(N·log(N))`.
//! \~\code //! \~\code
@@ -1310,8 +1465,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Reverses this array. //! \~english Reverses this array.
//! \~russian Обращает порядок следования элементов этого массива. //! \~russian Обращает порядок следования элементов этого массива.
//! \~\details //! \~\details
@@ -1336,7 +1489,6 @@ public:
return *this; return *this;
} }
//! \~\brief
//! \~english Returns reversed array. //! \~english Returns reversed array.
//! \~russian Возвращает перевернутый массив. //! \~russian Возвращает перевернутый массив.
//! \~\details //! \~\details
@@ -1350,15 +1502,14 @@ public:
return ret.reverse(); return ret.reverse();
} }
//! \~\brief
//! \~english Increases or decreases the size of the array by `add_size` elements. //! \~english Increases or decreases the size of the array by `add_size` elements.
//! \~russian Увеличивает или уменьшает размер массива на `add_size` элементов. //! \~russian Увеличивает или уменьшает размер массива на `add_size` элементов.
//! \~\details //! \~\details
//! \~english If `add_size > 0` then elements are added to the end of the array. //! \~english If `add_size > 0` then elements are added to the end of the array.
//! If `add_size < 0` then elements are removed from the end of the array. //! If `add_size < 0` then elements are removed from the end of the array.
//! If `add_size < 0` and there are fewer elements in the array than specified, then the array becomes empty. //! If `add_size < 0` and there are fewer elements in the array than specified, then the array becomes empty.
//! \~russian Если `add_size > 0` то в конец массива добавляются элементы. //! \~russian Если `add_size > 0`, то в конец массива добавляются элементы.
//! Если `add_size < 0` то с конца массива удаляются элементы. //! Если `add_size < 0`, то с конца массива удаляются элементы.
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым. //! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
//! \~\sa \a resize() //! \~\sa \a resize()
inline PIVector<T> & enlarge(llong add_size, const T & e = T()) { inline PIVector<T> & enlarge(llong add_size, const T & e = T()) {
@@ -1368,7 +1519,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Remove no more than one element equal `e`. //! \~english Remove no more than one element equal `e`.
//! \~russian Удаляет первый элемент, который равен элементу `e`. //! \~russian Удаляет первый элемент, который равен элементу `e`.
//! \~\details //! \~\details
@@ -1388,7 +1538,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Remove all elements equal `e`. //! \~english Remove all elements equal `e`.
//! \~russian Удаляет все элементы, равные элементу `e`. //! \~russian Удаляет все элементы, равные элементу `e`.
//! \~\details //! \~\details
@@ -1408,7 +1557,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Remove all elements in the array //! \~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 Удаляет все элементы, удовлетворяющие условию,
@@ -1430,21 +1578,22 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Appends the given element `e` to the end of the array. //! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива. //! \~russian Добавляет элемент `e` в конец массива.
//! \~\details //! \~\details
//! \~english If size() is less than capacity(), which is most often //! \~english If size() is less than capacity(), which is most often
//! then the addition will be very fast, and does not depend on the size of the array. //! then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If the new size() is greater than capacity() //! If the new size() is greater than capacity()
//! then all iterators and references //! then all iterators and references
//! (including the past-the-end iterator) are invalidated. //! (including the past-the-end iterator) are invalidated.
//! Otherwise only the past-the-end iterator is invalidated. //! Otherwise only the past-the-end iterator is invalidated.
//! \~russian Если size() меньше capacity(), что чаше всего, //! \~russian Если size() меньше capacity(), что часто бывает,
//! то добавление будет очень быстрым, и не зависит от размера массива. //! то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если новый size() больше, чем capacity(), //! Если новый size() больше, чем capacity(),
//! то все итераторы и указатели становятся нерабочими. //! то все итераторы и указатели становятся нерабочими.
//! В противном случае, все, кроме итераторов указывающих на конец массива, //! В противном случае все, кроме итераторов, указывающих на конец массива,
//! остаются в рабочем состоянии. //! остаются в рабочем состоянии.
//! \~\code //! \~\code
//! PIVector<int> v{1, 2, 3}; //! PIVector<int> v{1, 2, 3};
@@ -1460,7 +1609,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Appends the given element `e` to the end of the array. //! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива. //! \~russian Добавляет элемент `e` в конец массива.
//! \~\details //! \~\details
@@ -1474,7 +1622,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Appends the given elements to the end of the array. //! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива. //! \~russian Добавляет элементы в конец массива.
//! \~\details //! \~\details
@@ -1492,7 +1639,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Appends the given array `v` to the end of the array. //! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива. //! \~russian Добавляет массив `v` в конец массива.
//! \~\details //! \~\details
@@ -1512,21 +1658,23 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Appends the given element `e` to the end of the array. //! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива. //! \~russian Добавляет элемент `e` в конец массива.
//! \~\details //! \~\details
//! \~\details
//! \~english If size() is less than capacity(), which is most often //! \~english If size() is less than capacity(), which is most often
//! then the addition will be very fast, and does not depend on the size of the array. //! then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If the new size() is greater than capacity() //! If the new size() is greater than capacity()
//! then all iterators and references //! then all iterators and references
//! (including the past-the-end iterator) are invalidated. //! (including the past-the-end iterator) are invalidated.
//! Otherwise only the past-the-end iterator is invalidated. //! Otherwise only the past-the-end iterator is invalidated.
//! \~russian Если size() меньше capacity(), что чаше всего, //! \~russian Если size() меньше capacity(), что часто бывает,
//! то добавление будет очень быстрым, и не зависит от размера массива. //! то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если новый size() больше, чем capacity(), //! Если новый size() больше, чем capacity(),
//! то все итераторы и указатели становятся нерабочими. //! то все итераторы и указатели становятся нерабочими.
//! В противном случае, все, кроме итераторов указывающих на конец массива, //! В противном случае все, кроме итераторов, указывающих на конец массива,
//! остаются в рабочем состоянии. //! остаются в рабочем состоянии.
//! \~\code //! \~\code
//! PIVector<int> v{1, 2, 3}; //! PIVector<int> v{1, 2, 3};
@@ -1537,7 +1685,6 @@ public:
//! \~\sa \a prepend(), \a push_front(), \a push_back(), \a insert() //! \~\sa \a prepend(), \a push_front(), \a push_back(), \a insert()
inline PIVector<T> & append(const T & e) {return push_back(e);} inline PIVector<T> & append(const T & e) {return push_back(e);}
//! \brief
//! \~english Appends the given element `e` to the end of the array. //! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива. //! \~russian Добавляет элемент `e` в конец массива.
//! \~\details //! \~\details
@@ -1546,7 +1693,6 @@ public:
//! \~\sa \a append() //! \~\sa \a append()
inline PIVector<T> & append(T && e) {return push_back(std::move(e));} inline PIVector<T> & append(T && e) {return push_back(std::move(e));}
//! \brief
//! \~english Appends the given elements to the end of the array. //! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива. //! \~russian Добавляет элементы в конец массива.
//! \~\details //! \~\details
@@ -1559,7 +1705,6 @@ public:
//! \~\sa \a append() //! \~\sa \a append()
inline PIVector<T> & append(std::initializer_list<T> init_list) {return push_back(init_list);} inline PIVector<T> & append(std::initializer_list<T> init_list) {return push_back(init_list);}
//! \brief
//! \~english Appends the given array `v` to the end of the array. //! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива. //! \~russian Добавляет массив `v` в конец массива.
//! \~\details //! \~\details
@@ -1573,7 +1718,6 @@ public:
//! \~\sa \a append() //! \~\sa \a append()
inline PIVector<T> & append(const PIVector<T> & v) {return push_back(v);} inline PIVector<T> & append(const PIVector<T> & v) {return push_back(v);}
//! \brief
//! \~english Appends the given element `e` to the end of the array. //! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива. //! \~russian Добавляет элемент `e` в конец массива.
//! \~\details //! \~\details
@@ -1585,7 +1729,6 @@ public:
//! \~\sa \a append() //! \~\sa \a append()
inline PIVector<T> & operator <<(const T & e) {return push_back(e);} inline PIVector<T> & operator <<(const T & e) {return push_back(e);}
//! \brief
//! \~english Appends the given element `e` to the end of the array. //! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива. //! \~russian Добавляет элемент `e` в конец массива.
//! \~\details //! \~\details
@@ -1597,7 +1740,6 @@ public:
//! \~\sa \a append() //! \~\sa \a append()
inline PIVector<T> & operator <<(T && e) {return push_back(std::move(e));} inline PIVector<T> & operator <<(T && e) {return push_back(std::move(e));}
//! \brief
//! \~english Appends the given array `v` to the end of the array. //! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива. //! \~russian Добавляет массив `v` в конец массива.
//! \~\details //! \~\details
@@ -1609,14 +1751,13 @@ public:
//! \~\sa \a append() //! \~\sa \a append()
inline PIVector<T> & operator <<(const PIVector<T> & v) {return push_back(v);} inline PIVector<T> & operator <<(const PIVector<T> & v) {return push_back(v);}
//! \brief
//! \~english Appends the given element `e` to the begin of the array. //! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива. //! \~russian Добавляет элемент `e` в начало массива.
//! \~\details //! \~\details
//! \~english Adding an element to the beginning takes longer than to the end. //! \~english Adding an element to the beginning takes longer than to the end.
//! This time is directly proportional to the size of the array. //! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated. //! All iterators and references are invalidated.
//! \~russian Добавление элемента в начало выполняется дольше чем в конец. //! \~russian Добавление элемента в начало выполняется дольше, чем в конец.
//! Это время прямопропорционально размеру массива. //! Это время прямопропорционально размеру массива.
//! При добавлении элемента все итераторы и указатели становятся нерабочими. //! При добавлении элемента все итераторы и указатели становятся нерабочими.
//! \~\code //! \~\code
@@ -1631,7 +1772,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Appends the given element `e` to the begin of the array. //! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива. //! \~russian Добавляет элемент `e` в начало массива.
//! \~\details //! \~\details
@@ -1643,7 +1783,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Appends the given array `v` to the begin of the array. //! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива. //! \~russian Добавляет массив `v` в начало массива.
//! \~\details //! \~\details
@@ -1660,14 +1799,28 @@ public:
return *this; return *this;
} }
//! \brief //! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIVector<T> & push_front(std::initializer_list<T> init_list) {
insert(0, init_list);
return *this;
}
//! \~english Appends the given element `e` to the begin of the array. //! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива. //! \~russian Добавляет элемент `e` в начало массива.
//! \~\details //! \~\details
//! \~english Adding an element to the beginning takes longer than to the end. //! \~english Adding an element to the beginning takes longer than to the end.
//! This time is directly proportional to the size of the array. //! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated. //! All iterators and references are invalidated.
//! \~russian Добавление элемента в начало выполняется дольше чем в конец. //! \~russian Добавление элемента в начало выполняется дольше, чем в конец.
//! Это время прямопропорционально размеру массива. //! Это время прямопропорционально размеру массива.
//! При добавлении элемента все итераторы и указатели становятся нерабочими. //! При добавлении элемента все итераторы и указатели становятся нерабочими.
//! \~\code //! \~\code
@@ -1679,7 +1832,6 @@ public:
//! \~\sa \a append(), \a push_back(), \a push_front(), \a insert() //! \~\sa \a append(), \a push_back(), \a push_front(), \a insert()
inline PIVector<T> & prepend(const T & e) {return push_front(e);} inline PIVector<T> & prepend(const T & e) {return push_front(e);}
//! \brief
//! \~english Appends the given element `e` to the begin of the array. //! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива. //! \~russian Добавляет элемент `e` в начало массива.
//! \~\details //! \~\details
@@ -1688,7 +1840,6 @@ public:
//! \~\sa \a prepend() //! \~\sa \a prepend()
inline PIVector<T> & prepend(T && e) {return push_front(std::move(e));} inline PIVector<T> & prepend(T && e) {return push_front(std::move(e));}
//! \brief
//! \~english Appends the given array `v` to the begin of the array. //! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива. //! \~russian Добавляет массив `v` в начало массива.
//! \~\details //! \~\details
@@ -1702,7 +1853,18 @@ public:
//! \~\sa \a prepend() //! \~\sa \a prepend()
inline PIVector<T> & prepend(const PIVector<T> & v) {return push_front(v);} inline PIVector<T> & prepend(const PIVector<T> & v) {return push_front(v);}
//! \brief //! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIVector<T> & prepend(std::initializer_list<T> init_list) {return prepend(init_list);}
//! \~english Remove one element from the end of the array. //! \~english Remove one element from the end of the array.
//! \~russian Удаляет один элемент с конца массива. //! \~russian Удаляет один элемент с конца массива.
//! \~\details //! \~\details
@@ -1722,14 +1884,13 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Remove one element from the begining of the array. //! \~english Remove one element from the begining of the array.
//! \~russian Удаляет один элемент с начала массива. //! \~russian Удаляет один элемент с начала массива.
//! \~\details //! \~\details
//! \~english Removing an element from the beginning takes longer than from the end. //! \~english Removing an element from the beginning takes longer than from the end.
//! This time is directly proportional to the size of the array. //! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated. //! All iterators and references are invalidated.
//! \~russian Удаление элемента с начала выполняется дольше чем с конца. //! \~russian Удаление элемента с начала выполняется дольше, чем с конца.
//! Это время прямопропорционально размеру массива. //! Это время прямопропорционально размеру массива.
//! При удалении элемента все итераторы и указатели становятся нерабочими. //! При удалении элемента все итераторы и указатели становятся нерабочими.
//! \~\code //! \~\code
@@ -1744,7 +1905,6 @@ public:
return *this; return *this;
} }
//! \brief
//! \~english Remove one element from the end of the array and return it. //! \~english Remove one element from the end of the array and return it.
//! \~russian Удаляет один элемент с начала массива и возвращает его. //! \~russian Удаляет один элемент с начала массива и возвращает его.
//! \~\details //! \~\details
@@ -1760,7 +1920,6 @@ public:
return e; return e;
} }
//! \brief
//! \~english Remove one element from the begining of the array and return it. //! \~english Remove one element from the begining of the array and return it.
//! \~russian Удаляет один элемент с конца массива и возвращает его. //! \~russian Удаляет один элемент с конца массива и возвращает его.
//! \~\details //! \~\details
@@ -1776,7 +1935,6 @@ public:
return e; return e;
} }
//! \brief
//! \~english Returns an array converted to another type. //! \~english Returns an array converted to another type.
//! \~russian Возвращает конвертированный в другой тип массив. //! \~russian Возвращает конвертированный в другой тип массив.
//! \~\details //! \~\details
@@ -1785,7 +1943,7 @@ public:
//! PIVector<int> v2 = v.toType<int>(); //! PIVector<int> v2 = v.toType<int>();
//! piCout << v2; // {1, 2, 3} //! piCout << v2; // {1, 2, 3}
//! \endcode //! \endcode
//! \~\sa \a take_front(), \a pop_back(), \a pop_front() //! \~\sa \a map()
template <typename ST> template <typename ST>
inline PIVector<ST> toType() const { inline PIVector<ST> toType() const {
PIVector<ST> ret; ret.reserve(piv_size); PIVector<ST> ret; ret.reserve(piv_size);
@@ -1795,6 +1953,17 @@ public:
return ret; return ret;
} }
//! \~english Returns a new array with all elements
//! that pass the test implemented by the provided function `test`.
//! \~russian Возвращает новый массив со всеми элементами,
//! прошедшими проверку, задаваемую в передаваемой функции `test`.
//! \~\details
//! \~\code
//! PIVector<int> v{3, 2, 5, 2, 7};
//! PIVector<int> v2 = v.filter([](const int & i){return i > 2;});
//! piCout << v2; // {3, 5, 7}
//! \endcode
//! \~\sa \a map(), \a any(), \a every()
inline PIVector<T> filter(std::function<bool(const T & e)> test) const { inline PIVector<T> filter(std::function<bool(const T & e)> test) const {
PIVector<T> ret; PIVector<T> ret;
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
@@ -1803,12 +1972,39 @@ public:
return ret; return ret;
} }
//! \~english Execute function `void f(const T & e)` for every element in array.
//! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива.
//! \~\details
//! \~russian Не позволяет изменять элементы массива.
//! Для редактирования элементов используйте функцию вида `void f(T & e)`.
//! \~english Does not allow changing array elements.
//! To edit elements, use the function like `void f(T & e)`
//! \~\code
//! PIVector<int> v{1, 2, 3, 4, 5};
//! int s = 0;
//! v.forEach([&s](const int & e){s += e;});
//! piCout << s; // 15
//! \endcode
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
inline void forEach(std::function<void(const T & e)> f) const { inline void forEach(std::function<void(const T & e)> f) const {
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
f(piv_data[i]); f(piv_data[i]);
} }
} }
//! \~english Execute function `void f(T & e)` for every element in array.
//! \~russian Выполняет функцию `void f(T & e)` для каждого элемента массива.
//! \~\details
//! \~english Overloaded function.
//! Allows you to change the elements of the array.
//! \~russian Перегруженая функция.
//! Позволяет изменять элементы массива.
//! \~\code
//! PIVector<int> v{1, 2, 3, 4, 5};
//! v.forEach([](int & e){e++;});
//! piCout << v; // {2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
inline PIVector<T> & forEach(std::function<void(T & e)> f) { inline PIVector<T> & forEach(std::function<void(T & e)> f) {
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
f(piv_data[i]); f(piv_data[i]);
@@ -1816,6 +2012,23 @@ public:
return *this; return *this;
} }
//! \~english Сreates a new array populated with the results
//! of calling a provided function `ST f(const T & e)` on every element in the calling array.
//! \~russian Создаёт новый массив с результатом вызова указанной функции
//! `ST f(const T & e)` для каждого элемента массива.
//! \~\details
//! \~english Calls a provided function`ST f(const T & e)`
//! once for each element in an array, in order,
//! and constructs a new array from the results.
//! \~russian Метод `map` вызывает переданную функцию `ST f(const T & e)`
//! один раз для каждого элемента в порядке их появления
//! и конструирует новый массив из результатов её вызова.
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! PIVector<PIString> sl = v.map<PIString>([](const int & i){return PIString::fromNumber(i);});
//! piCout << sl; {"1", "2", "3"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST> template <typename ST>
inline PIVector<ST> map(std::function<ST(const T & e)> f) const { inline PIVector<ST> map(std::function<ST(const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size); PIVector<ST> ret; ret.reserve(piv_size);
@@ -1825,6 +2038,47 @@ public:
return ret; return ret;
} }
//! \~english Applies the function `ST f(const T & e, const ST & acc)`
//! to each element of the array (from left to right), returns one value.
//! \~russian Применяет функцию `ST f(const T & e, const ST & acc)`
//! к каждому элементу массива (слева-направо), возвращает одно значение.
//! \~\details
//! \~english The reduce() method performs the `f` function
//! once for each element in the array.
//! If the `initial` argument is passed when calling reduce(),
//! then when the function `f` is called for the first time,
//! the value of `acc` will be assigned to `initial`.
//! If the array is empty, the value `initial` will be returned.
//! \param f is a function like `ST f(const T & e, const ST & acc)`,
//! executed for each element of the array. It takes two arguments:
//! * **e** - current element of the array
//! * **acc** - accumulator accumulating the value
//! which this function returns after visiting the next element
//!
//! \param initial _optional_ Object used as the second argument
//! when the `f` function is first called.
//! \~russian Метод reduce() выполняет функцию `f`
//! один раз для каждого элемента, присутствующего в массиве.
//! Если при вызове reduce() передан аргумент `initial`,
//! то при первом вызове функции `f` значение `acc`
//! будет равным значению `initial`.
//! Если массив пустой то будет возвращено значение `initial`.
//! \param f Функция, вида `ST f(const T & e, const ST & acc)`,
//! выполняющаяся для каждого элемента массива.
//! Она принимает два аргумента:
//! * **e** - текущий элемент массива
//! * **acc** - аккумулятор, аккумулирующий значение
//! которое возвращает эта функция после посещения очередного элемента
//!
//! \param initial _опциональный_ Объект,
//! используемый в качестве второго аргумента при первом вызове функции `f`.
//!
//! \~\code
//! PIVector<int> v{1, 2, 3, 4, 5};
//! int s = v.reduce<int>([](const int & e, const int & acc){return e + acc;});
//! piCout << s; // 15
//! \endcode
//! \~\sa \a forEach(), \a map()
template <typename ST> template <typename ST>
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const { inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial); ST ret(initial);
@@ -1834,22 +2088,41 @@ public:
return ret; return ret;
} }
inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = byRow) const { //! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
PIVector<PIVector<T>> ret; //! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
if (isEmpty()) return ret; //! \~\details
//! \~russian
//! \param rows размер внешнего массива
//! \param cols размер внутренних массивов
//! \param order порядок обхода исходного массива, задаётся с помощью \a ReshapeOrder
//! \~english
//! \param rows size external array
//! \param cols size internal arrays
//! \param order the order of traversing the source array is set using \a ReshapeOrder
//! \~\code
//! PIVector<int> v{1, 2, 3, 4};
//! PIVector<PIVector<int>> m1 = v.reshape(2,2);
//! piCout << m1; // {{1, 2}, {3, 4}}
//! PIVector<PIVector<int>> m2 = v.reshape(2,2, ReshapeByColumn);
//! piCout << m2; // {{1, 3}, {2, 4}}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a flatten()
inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
#ifndef NDEBUG #ifndef NDEBUG
if (rows*cols != piv_size) { if (rows*cols != piv_size) {
printf("error with PIVector<%s>::reshape\n", __PIP_TYPENAME__(T)); printf("error with PIVector<%s>::reshape\n", __PIP_TYPENAME__(T));
} }
#endif #endif
assert(rows*cols == piv_size); assert(rows*cols == piv_size);
PIVector<PIVector<T>> ret;
if (isEmpty()) return ret;
ret.resize(rows); ret.resize(rows);
if (order == byRow) { if (order == ReshapeByRow) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret[r] = PIVector<T>(&(piv_data[r*cols]), cols); ret[r] = PIVector<T>(&(piv_data[r*cols]), cols);
} }
} }
if (order == byColumn) { if (order == ReshapeByColumn) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret[r].resize(cols); ret[r].resize(cols);
for (size_t c = 0; c < cols; c++) { for (size_t c = 0; c < cols; c++) {
@@ -1860,21 +2133,35 @@ public:
return ret; return ret;
} }
//! \~english Changes the dimension of the array, creates a one-dimensional array from a two-dimensional array.
//! \~russian Изменяет размерность массива, из двухмерный массива создает одномерный.
//! \~\details
//! \~russian Делает массив плоским.
//! Порядок обхода исходного массива задаётся с помощью \a ReshapeOrder.
//! \~english Makes the array flat.
//! Еhe order of traversing the source array is set using \a ReshapeOrder.
//! \~\code
//! PIVector<int> v{1, 2, 3, 4, 5, 6};
//! PIVector<PIVector<int>> xv = v.reshape(3,2);
//! piCout << xv; // {{1, 2}, {3, 4}, {5, 6}}
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if< template<typename C, typename std::enable_if<
std::is_same<T, PIVector<C>>::value std::is_same<T, PIVector<C>>::value
, int>::type = 0> , int>::type = 0>
inline PIVector<C> reshape(ReshapeOrder order = byRow) const { inline PIVector<C> flatten(ReshapeOrder order = ReshapeByRow) const {
PIVector<C> ret; PIVector<C> ret;
if (isEmpty()) return ret; if (isEmpty()) return ret;
size_t rows = size(); size_t rows = size();
size_t cols = at(0).size(); size_t cols = at(0).size();
ret.reserve(rows * cols); ret.reserve(rows * cols);
if (order == byRow) { if (order == ReshapeByRow) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret.append(at(r)); ret.append(at(r));
} }
} }
if (order == byColumn) { if (order == ReshapeByColumn) {
for (size_t c = 0; c < cols; c++) { for (size_t c = 0; c < cols; c++) {
for (size_t r = 0; r < rows; r++) { for (size_t r = 0; r < rows; r++) {
ret << at(r)[c]; ret << at(r)[c];
@@ -1885,6 +2172,32 @@ public:
return ret; return ret;
} }
//! \~english Changes the dimension of the two-dimensional array.
//! \~russian Изменяет размерность двухмерного массива.
//! \~\details
//! \~russian
//! \param rows размер внешнего массива
//! \param cols размер внутренних массивов
//! \param order порядок обхода исходного массива, задаётся с помощью \a ReshapeOrder
//! \~english
//! \param rows size external array
//! \param cols size internal arrays
//! \param order the order of traversing the source array is set using \a ReshapeOrder
//! \~\code
//! PIVector<int> v{1, 2, 3, 4, 5, 6};
//! PIVector<PIVector<int>> xv = v.reshape(3,2);
//! piCout << xv; // {{1, 2}, {3, 4}, {5, 6}}
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
//! \endcode
//! \~\sa \a map(), \a reduce(), \a reshape()
template<typename C, typename std::enable_if<
std::is_same<T, PIVector<C>>::value
, int>::type = 0>
inline PIVector<PIVector<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
PIVector<C> fl = flatten<C>();
return fl.reshape(rows, cols, order);
}
private: private:
inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;} inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;}
inline size_t asize(size_t s) { inline size_t asize(size_t s) {
@@ -1892,8 +2205,9 @@ private:
if (piv_rsize + piv_rsize >= s && piv_rsize < s) { if (piv_rsize + piv_rsize >= s && piv_rsize < s) {
return piv_rsize + piv_rsize; return piv_rsize + piv_rsize;
} }
ssize_t t = 0, s_ = s - 1; ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
while (s_ >> t) ++t; while (s_ >> t)
++t;
return (1 << t); return (1 << t);
} }
template<typename T1 = T, typename std::enable_if< template<typename T1 = T, typename std::enable_if<
@@ -1981,7 +2295,6 @@ private:
}; };
#ifdef PIP_STD_IOSTREAM #ifdef PIP_STD_IOSTREAM
//! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream). //! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream).
//! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream). //! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream).
@@ -2019,5 +2332,4 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
template<typename T> template<typename T>
inline void piSwap(PIVector<T> & f, PIVector<T> & s) {f.swap(s);} inline void piSwap(PIVector<T> & f, PIVector<T> & s) {f.swap(s);}
#endif // PIVECTOR_H #endif // PIVECTOR_H

View File

@@ -246,6 +246,10 @@
extern char ** environ; extern char ** environ;
#endif #endif
#ifndef NO_UNUSED
# define NO_UNUSED(x) (void)x
#endif
#ifndef assert #ifndef assert
# define assert(x) # define assert(x)
# define assertm(exp, msg) # define assertm(exp, msg)
@@ -387,12 +391,12 @@
//! \~\brief //! \~\brief
//! \~english Macro used for infinite wait //! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания //! \~russian Макрос для бесконечного ожидания
#define FOREVER_WAIT FOREVER piMinSleep; #define FOREVER_WAIT FOREVER piMinSleep();
//! \~\brief //! \~\brief
//! \~english Macro used for infinite wait //! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания //! \~russian Макрос для бесконечного ожидания
#define WAIT_FOREVER FOREVER piMinSleep; #define WAIT_FOREVER FOREVER piMinSleep();
//! \~\brief //! \~\brief

View File

@@ -21,14 +21,7 @@
#include "pistringlist.h" #include "pistringlist.h"
#include <iostream> #include <iostream>
//! \addtogroup Core
//! \{
//! \class PIByteArray pibytearray.h //! \class PIByteArray pibytearray.h
//!
//! \~\brief
//! \~english The %PIByteArray class provides an array of bytes
//! \~russian Класс %PIByteArray представляет собой массив байтов
//!
//! \~\details //! \~\details
//! \~english //! \~english
//! %PIByteArray used to store raw bytes. //! %PIByteArray used to store raw bytes.
@@ -98,7 +91,6 @@
//! метов \a append(). //! метов \a append().
//! \~\snippet pibytearray.cpp 3 //! \~\snippet pibytearray.cpp 3
//! //!
//! \}
static const uchar base64Table[64] = { static const uchar base64Table[64] = {

View File

@@ -36,6 +36,10 @@ class PIString;
class PIByteArray; class PIByteArray;
//! \ingroup Core
//! \~\brief
//! \~english The %PIByteArray class provides an array of bytes.
//! \~russian Класс %PIByteArray представляет собой массив байтов.
class PIP_EXPORT PIByteArray: public PIDeque<uchar> class PIP_EXPORT PIByteArray: public PIDeque<uchar>
{ {
public: public:
@@ -268,8 +272,8 @@ inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v); PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
//! \relatesalso PIByteArray //! \relatesalso PIByteArray
//! \~english Store operator, see \ref PIByteArray_sec1 for details //! \~english Store operator
//! \~russian Оператор сохранения, подробнее в \ref PIByteArray_sec1 //! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
int os = s.size_s(); int os = s.size_s();
if (v.s > 0) { if (v.s > 0) {
@@ -402,8 +406,8 @@ inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v); PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
//! \relatesalso PIByteArray //! \relatesalso PIByteArray
//! \~english Restore operator, see \ref PIByteArray_sec1 for details //! \~english Restore operator
//! \~russian Оператор извлечения, подробнее в \ref PIByteArray_sec1 //! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) { inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
if (s.size_s() < v.s) { if (s.size_s() < v.s) {
printf("error with RawData %d < %d\n", (int)s.size_s(), v.s); printf("error with RawData %d < %d\n", (int)s.size_s(), v.s);
@@ -626,9 +630,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
//! \~russian Оператор сохранения //! \~russian Оператор сохранения
template <typename Key, typename T> template <typename Key, typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
s << int(v.pim_index.size_s()); // s << int(v.pim_index.size_s());
for (uint i = 0; i < v.size(); ++i) // for (uint i = 0; i < v.size(); ++i)
s << int(v.pim_index[i].index) << v.pim_index[i].key; // s << int(v.pim_index[i].index) << v.pim_index[i].key;
s << v.pim_content; s << v.pim_content;
return s; return s;
} }
@@ -643,17 +647,17 @@ inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T)); printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; v.pim_index.resize(sz); // int sz; s >> sz; v.pim_index.resize(sz);
int ind = 0; // int ind = 0;
for (int i = 0; i < sz; ++i) { // for (int i = 0; i < sz; ++i) {
s >> ind >> v.pim_index[i].key; // s >> ind >> v.pim_index[i].key;
v.pim_index[i].index = ind; // v.pim_index[i].index = ind;
} // }
s >> v.pim_content; s >> v.pim_content;
if (v.pim_content.size_s() != v.pim_index.size_s()) { // if (v.pim_content.size_s() != v.pim_index.size_s()) {
piCout << "Warning: loaded invalid PIMap, clear"; // piCout << "Warning: loaded invalid PIMap, clear";
v.clear(); // v.clear();
} // }
return s; return s;
} }

View File

@@ -18,7 +18,7 @@
*/ */
#include "piincludes_p.h" #include "piincludes_p.h"
#include "pibytearray.h" #include "pistring.h"
#ifdef PIP_ICU #ifdef PIP_ICU
# define U_NOEXCEPT # define U_NOEXCEPT
# include "unicode/ucnv.h" # include "unicode/ucnv.h"
@@ -35,21 +35,8 @@ char * __utf8name__ = 0;
# include <ctype.h> # include <ctype.h>
#endif #endif
#include <wchar.h> #include <wchar.h>
#ifdef ANDROID
# if __ANDROID_API__ < 21
# define wctomb(s, wc) wcrtomb(s, wc, NULL)
# define mbtowc(pwc, s, n) mbrtowc(pwc, s, n, NULL)
# endif
#endif
//! \addtogroup Core
//! \{
//! \class PIChar pichar.h //! \class PIChar pichar.h
//!
//! \~\brief
//! \~english %PIChar represents a single character
//! \~russian %PIChar представляет собой один символ строки
//!
//! \~\details //! \~\details
//! \~english //! \~english
//! This class is wrapper around UTF16. //! This class is wrapper around UTF16.
@@ -59,7 +46,6 @@ char * __utf8name__ = 0;
//! %PIChar хранит один сивол в UTF16. Имеет много контрукторов, геттеров в различные //! %PIChar хранит один сивол в UTF16. Имеет много контрукторов, геттеров в различные
//! кодировки (системную, консольную, UTF8) и информационных функций. //! кодировки (системную, консольную, UTF8) и информационных функций.
//! //!
//! \}
ushort charFromCodepage(const char * c, int size, const char * codepage, int * taken = 0) { ushort charFromCodepage(const char * c, int size, const char * codepage, int * taken = 0) {
@@ -86,10 +72,12 @@ ushort charFromCodepage(const char * c, int size, const char * codepage, int * t
if (taken) *taken = ret; if (taken) *taken = ret;
return buffer; return buffer;
# else # else
wchar_t wc(0); mbstate_t state;
mbtowc(0, 0, 0); // reset mbtowc memset(&state, 0, sizeof(state));
ret = mbtowc(&wc, c, size); wchar_t wc;
ret = mbrtowc(&wc, c, size, &state);
//printf("mbtowc = %d\n", ret); //printf("mbtowc = %d\n", ret);
//piCout << errorString();
if (ret < 1) return 0; if (ret < 1) return 0;
return ushort(wc); return ushort(wc);
# endif # endif
@@ -389,13 +377,7 @@ PICout operator <<(PICout s, const PIChar & v) {
#ifdef WINDOWS #ifdef WINDOWS
s << v.toSystem(); s << v.toSystem();
#else #else
{ s << PIString(v);
char tc[8];
wctomb(0, 0);
int sz = wctomb(tc, v.ch);
for (int b = 0; b < sz; ++b)
s << tc[b];
}
#endif #endif
} }
s.restoreControl(); s.restoreControl();

View File

@@ -32,6 +32,10 @@ extern PIP_EXPORT char * __syslocname__;
extern PIP_EXPORT char * __sysoemname__; extern PIP_EXPORT char * __sysoemname__;
extern PIP_EXPORT char * __utf8name__; extern PIP_EXPORT char * __utf8name__;
//! \ingroup Core
//! \~\brief
//! \~english %PIChar represents a single character.
//! \~russian %PIChar представляет собой один символ строки.
class PIP_EXPORT PIChar class PIP_EXPORT PIChar
{ {
friend class PIString; friend class PIString;
@@ -61,6 +65,10 @@ public:
//! \~russian Оператор присваивания //! \~russian Оператор присваивания
PIChar & operator =(const char v) {ch = v; return *this;} PIChar & operator =(const char v) {ch = v; return *this;}
//! \~english Copy operator
//! \~russian Оператор присваивания
PIChar & operator =(const wchar_t v) {ch = v; return *this;}
//! \~english Compare operator //! \~english Compare operator
//! \~russian Оператор сравнения //! \~russian Оператор сравнения
bool operator ==(const PIChar & o) const; bool operator ==(const PIChar & o) const;

View File

@@ -19,13 +19,8 @@
#include "pichunkstream.h" #include "pichunkstream.h"
//! \addtogroup Core
//! \{
//! \class PIChunkStream pichunkstream.h //! \class PIChunkStream pichunkstream.h
//! \brief //! \details
//! \~english Class for binary de/serialization
//! \~russian Класс для бинарной де/сериализации
//!
//! \~english \section PIChunkStream_sec0 Synopsis //! \~english \section PIChunkStream_sec0 Synopsis
//! \~russian \section PIChunkStream_sec0 Краткий обзор //! \~russian \section PIChunkStream_sec0 Краткий обзор
//! \~english //! \~english
@@ -89,7 +84,6 @@
//! \~russian ... и десериализовать: //! \~russian ... и десериализовать:
//! \~\snippet pichunkstream.cpp read_new //! \~\snippet pichunkstream.cpp read_new
//! //!
//! \}
void PIChunkStream::setSource(const PIByteArray & data) { void PIChunkStream::setSource(const PIByteArray & data) {

View File

@@ -29,6 +29,10 @@
#include "pibytearray.h" #include "pibytearray.h"
//! \ingroup Core
//! \~\brief
//! \~english Class for binary de/serialization.
//! \~russian Класс для бинарной де/сериализации.
class PIP_EXPORT PIChunkStream class PIP_EXPORT PIChunkStream
{ {
public: public:

View File

@@ -21,13 +21,8 @@
#include "pisysteminfo.h" #include "pisysteminfo.h"
//! \addtogroup Core
//! \{
//! \class PICLI picli.h //! \class PICLI picli.h
//! \~\brief //! \details
//! \~english Command-Line parser
//! \~russian Парсер командной строки
//!
//! \~english \section PICLI_sec0 Synopsis //! \~english \section PICLI_sec0 Synopsis
//! \~russian \section PICLI_sec0 Краткий обзор //! \~russian \section PICLI_sec0 Краткий обзор
//! \~english //! \~english
@@ -43,7 +38,7 @@
//! а также получить их значения при помощи \a argumentValue(). //! а также получить их значения при помощи \a argumentValue().
//! //!
//! \~english \section PICLI_sec1 Example //! \~english \section PICLI_sec1 Example
//! \~russian \section PICLI_sec0 Пример //! \~russian \section PICLI_sec1 Пример
//! \~\code //! \~\code
//! int main(int argc, char ** argv) { //! int main(int argc, char ** argv) {
//! PICLI cli(argc, argv); //! PICLI cli(argc, argv);
@@ -66,12 +61,10 @@
//! a.out --debug -c --value 10 //! a.out --debug -c --value 10
//! \endcode //! \endcode
//! //!
//! /}
PICLI::PICLI(int argc, char * argv[]) { PICLI::PICLI(int argc, char * argv[]) {
setName("CLI"); needParse = debug_ = true;
needParse = true;
_prefix_short = "-"; _prefix_short = "-";
_prefix_full = "--"; _prefix_full = "--";
_count_opt = 0; _count_opt = 0;

View File

@@ -26,11 +26,15 @@
#ifndef PICLI_H #ifndef PICLI_H
#define PICLI_H #define PICLI_H
#include "piobject.h" #include "pistringlist.h"
#include "piset.h"
class PIP_EXPORT PICLI: public PIObject //! \ingroup Core
//! \~\brief
//! \~english Command-Line parser.
//! \~russian Парсер командной строки.
class PIP_EXPORT PICLI
{ {
PIOBJECT_SUBCLASS(PICLI, PIObject)
public: public:
//! \~english Constructor //! \~english Constructor
@@ -94,6 +98,11 @@ public:
void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;} void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;}
void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;} void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;}
bool debug() const {return debug_;}
void setDebug(bool debug) {debug_ = debug;}
PIConstChars className() const {return "PICLI";}
PIString name() const {return PIStringAscii("CLI");}
private: private:
struct Argument { struct Argument {
Argument() {has_value = found = false;} Argument() {has_value = found = false;}
@@ -112,7 +121,7 @@ private:
PISet<PIString> keys_full, keys_short; PISet<PIString> keys_full, keys_short;
PIVector<Argument> _args; PIVector<Argument> _args;
int _count_mand, _count_opt; int _count_mand, _count_opt;
bool needParse; bool needParse, debug_;
}; };

View File

@@ -20,13 +20,7 @@
#include "picollection.h" #include "picollection.h"
//! \addtogroup Core
//! \{
//! \~\class PICollection picollection.h //! \~\class PICollection picollection.h
//! \~\brief
//! \~english Helper to collect and retrieve classes to groups
//! \~russian Помощник для создания и получения классов в группы
//!
//! \~\details //! \~\details
//! \~english \section PICollection_sec0 Synopsis //! \~english \section PICollection_sec0 Synopsis
//! \~russian \section PICollection_sec0 Краткий обзор //! \~russian \section PICollection_sec0 Краткий обзор
@@ -41,7 +35,6 @@
//! объектов в глобальные группы. Затем можно получить их список в любом месте программы. //! объектов в глобальные группы. Затем можно получить их список в любом месте программы.
//! \~\snippet picollection.cpp main //! \~\snippet picollection.cpp main
//! //!
//! \}
PIStringList PICollection::groups() { PIStringList PICollection::groups() {

View File

@@ -100,6 +100,10 @@
#endif #endif
//! \ingroup Core
//! \~\brief
//! \~english Helper to collect and retrieve classes to groups.
//! \~russian Помощник для создания и получения классов в группы.
class PIP_EXPORT PICollection class PIP_EXPORT PICollection
{ {
friend class __PICollectionInitializer; friend class __PICollectionInitializer;

View File

@@ -0,0 +1,164 @@
/*
PIP - Platform Independent Primitives
C-String class
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is 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 "piconstchars.h"
#include "pistring.h"
//! \~\class PIConstChars piconstchars.h
//! \~\details
//! \~english \section PIConstChars_sec0 Synopsis
//! \~russian \section PIConstChars_sec0 Краткий обзор
//! \~english
//! This is wrapper around \c const char * string. %PIConstChars doesn`t
//! copy string, just save pointer and size.
//!
//! Provides API similar to string, with information and compare methods.
//!
//! Used to more handly works with ordinary C-strings.
//!
//! \~russian
//! Это обертка вокруг \c const char * строки. %PIConstChars не скопирует
//! строку, а хранит только указатель и размер.
//!
//! Предоставляет API схожий с обычной строкой, с методами сравнения и информационными.
//!
//! Используется для более удобной работы с обычными C-строками.
//!
bool PIConstChars::startsWith(const PIConstChars & str) const {
if (size() < str.size()) return false;
return str == left(str.size());
}
bool PIConstChars::startsWith(const char c) const {
if (size() < 1) return false;
return str[0] == c;
}
bool PIConstChars::endsWith(const PIConstChars & str) const {
if (size() < str.size()) return false;
return str == right(str.size());
}
bool PIConstChars::endsWith(const char c) const {
if (size() < 1) return false;
return str[len - 1] == c;
}
PIConstChars PIConstChars::mid(const int start, const int len) const {
int s = start, l = len;
if (l == 0 || s >= (int)size() || isEmpty()) return PIConstChars("");
if (s < 0) {
l += s;
s = 0;
}
if (l < 0) {
return PIConstChars(str + s, (int)size() - s);
} else {
if (l > (int)size() - s)
l = (int)size() - s;
return PIConstChars(str + s, l);
}
return PIConstChars("");
}
PIConstChars PIConstChars::left(const int l) const {
if (l <= 0) return PIConstChars("");
return mid(0, l);
}
PIConstChars PIConstChars::right(const int l) const {
if (l <= 0) return PIConstChars("");
return mid((int)size() - l, l);
}
PIConstChars & PIConstChars::cutLeft(const int l) {
if (l <= 0) return *this;
if (l >= (int)size())
*this = PIConstChars("");
else {
str += l;
len -= l;
}
return *this;
}
PIConstChars & PIConstChars::cutRight(const int l) {
if (l <= 0) return *this;
if (l >= (int)size())
*this = PIConstChars("");
else {
len -= l;
}
return *this;
}
PIConstChars PIConstChars::takeLeft(const int len) {
PIConstChars ret(left(len));
cutLeft(len);
return ret;
}
PIConstChars PIConstChars::takeRight(const int len) {
PIConstChars ret(right(len));
cutRight(len);
return ret;
}
PIConstChars & PIConstChars::trim() {
if (isEmpty()) return *this;
int st = -1, fn = 0;
for (int i = 0; i < (int)len; ++i) {
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) {
st = i;
break;
}
}
if (st < 0) {
*this = PIConstChars("");
return *this;
}
for (int i = (int)len - 1; i >= 0; --i) {
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) {
fn = i;
break;
}
}
if (fn < (int)len - 1) cutRight((int)len - fn - 1);
if (st > 0) cutLeft(st);
return *this;
}
PIString PIConstChars::toString() const {
if (isEmpty()) return PIString();
return PIString::fromAscii(str, len);
}

View File

@@ -0,0 +1,262 @@
/*! \file piconstchars.h
* \ingroup Core
* \brief
* \~english C-String class
* \~russian Класс C-строки
*/
/*
PIP - Platform Independent Primitives
C-String class
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is 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 PICONSTCHARS_H
#define PICONSTCHARS_H
#include "picout.h"
//! \ingroup Core
//! \~\brief
//! \~english C-String class.
//! \~russian Класс C-строки.
class PIP_EXPORT PIConstChars {
public:
//! \~english Contructs an null string.
//! \~russian Создает нулевую строку.
PIConstChars() {}
//! \~english Contructs string from C-string "string".
//! \~russian Создает строку из C-строки "string".
PIConstChars(const char * string) {
str = string;
len = strlen(string);
}
//! \~english Contructs string from "size" characters of buffer "data".
//! \~russian Создает строку из "size" символов массива "data".
PIConstChars(const char * data, size_t size) {
str = data;
len = size;
}
//! \~english Contructs a copy of string.
//! \~russian Создает копию строки.
PIConstChars(const PIConstChars & o) {
str = o.str;
len = o.len;
}
//! \~english Read-only access to character by `index`.
//! \~russian Доступ на чтение к символу по индексу `index`.
inline char operator [](size_t index) const {return str[index];}
//! \~english Read-only access to character by `index`.
//! \~russian Доступ на чтение к символу по индексу `index`.
inline char at(size_t index) const {return str[index];}
//! \~english Returns \c char * string pointer.
//! \~russian Возвращает \c char * указатель строки.
inline const char * data() const {return str;}
//! \~english Returns \c true if string doesn`t have any data.
//! \~russian Возвращает \c true если строка не имеет данных.
inline bool isNull() const {return !str;}
//! \~english Returns \c true if string is empty, i.e. length = 0, or null.
//! \~russian Возвращает \c true если строка пустая, т.е. длина = 0, или нулевая.
inline bool isEmpty() const {return len == 0;}
//! \~english Returns \c true if string is not empty, i.e. length > 0.
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
inline bool isNotEmpty() const {return len > 0;}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
inline size_t length() const {return len;}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
inline size_t size() const {return len;}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
inline ssize_t size_s() const {return len;}
//! \~english Returns if string starts with "str".
//! \~russian Возвращает начинается ли строка со "str".
bool startsWith(const PIConstChars & str) const;
//! \~english Returns if string starts with "c".
//! \~russian Возвращает начинается ли строка с "c".
bool startsWith(const char c) const;
//! \~english Returns if string ends with "str".
//! \~russian Возвращает оканчивается ли строка на "str".
bool endsWith(const PIConstChars & str) const;
//! \~english Returns if string ends with "c".
//! \~russian Возвращает оканчивается ли строка "c".
bool endsWith(const char c) const;
//! \~english Returns part of string from character at index "start" and maximum length "len".
//! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len".
//! \~\sa \a left(), \a right()
PIConstChars mid(const int start, const int len = -1) const;
//! \~english Returns part of string from start and maximum length "len".
//! \~russian Возвращает подстроку от начала и максимальной длиной "len".
//! \~\sa \a mid(), \a right()
PIConstChars left(const int len) const;
//! \~english Returns part of string at end and maximum length "len".
//! \~russian Возвращает подстроку максимальной длиной "len" и до конца.
//! \~\sa \a mid(), \a left()
PIConstChars right(const int len) const;
//! \~english Remove part of string from start and maximum length "len" and return this string.
//! \~russian Удаляет часть строки от начала и максимальной длины "len", возвращает эту строку.
//! \~\sa \a cutRight()
PIConstChars & cutLeft(const int len);
//! \~english Remove part of string at end and maximum length "len" and return this string.
//! \~russian Удаляет часть строки максимальной длины "len" от конца, возвращает эту строку.
//! \~\sa \a cutLeft()
PIConstChars & cutRight(const int len);
//! \~english Take a part from the begin of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки от начала максимальной длины "len" и возвращает её.
//! \~\sa \a takeRight()
PIConstChars takeLeft(const int len);
//! \~english Take a part from the end of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки с конца максимальной длины "len" и возвращает её.
//! \~\sa \a takeLeft()
PIConstChars takeRight(const int len);
//! \~english Remove spaces at the start and at the end of string and return this string.
//! \~russian Удаляет пробельные символы с начала и конца строки и возвращает эту строку.
//! \~\sa \a trimmed()
PIConstChars & trim();
//! \~english Returns copy of this string without spaces at the start and at the end.
//! \~russian Возвращает копию этой строки без пробельных символов с начала и конца.
//! \~\sa \a trim()
PIConstChars trimmed() const {return PIConstChars(*this).trim();}
//! \~english Returns as PIString.
//! \~russian Возвращает как PIString.
PIString toString() const;
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIConstChars & operator =(const PIConstChars & s) {
if (this == &s) return *this;
len = s.len;
str = s.str;
return *this;
}
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIConstChars & operator =(PIConstChars && s) {
swap(s);
return *this;
}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIConstChars & operator =(const char * s) {
str = s;
len = strlen(s);
return *this;
}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator ==(const PIConstChars & s) const {
if (isNull() && s.isNull()) return true;
if (isNull() xor s.isNull()) return false;
if (size() != s.size()) return false;
return strcmp(str, s.str) == 0;
}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator !=(const PIConstChars & s) const {return !(*this == s);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator <(const PIConstChars & s) const {
if ( isNull() && s.isNull()) return false;
if ( isNull() && !s.isNull()) return true ;
if (!isNull() && s.isNull()) return false;
if (size() == s.size())
return strcmp(str, s.str) < 0;
return size() < s.size();
}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator >(const PIConstChars & s) const {
if ( isNull() && s.isNull()) return false;
if ( isNull() && !s.isNull()) return false;
if (!isNull() && s.isNull()) return true ;
if (size() == s.size())
return strcmp(str, s.str) > 0;
return size() > s.size();
}
//! \~english Returns hash of string content.
//! \~russian Возвращает хэш содержимого строки.
inline uint hash() const {
if (isEmpty()) return 0;
return piHashData((const uchar *)str, len);
}
inline void swap(PIConstChars& v) {
piSwap<const char *>(str, v.str);
piSwap<size_t>(len, v.len);
}
private:
const char * str = nullptr;
size_t len = 0;
};
//! \relatesalso PICout
//! \~english Output operator to \a PICout.
//! \~russian Оператор вывода в \a PICout.
inline PICout operator <<(PICout s, const PIConstChars & v) {
s.space();
if (v.isNull())
s.write("(null)");
else {
s.quote();
s.write(v.data(), v.size());
s.quote();
}
return s;
}
template<> inline uint piHash(const PIConstChars & s) {return s.hash();}
#endif // PICONSTCHARS_H

View File

@@ -16,16 +16,16 @@
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 Core //! \defgroup Core Core
//! \~\brief //! \~\brief
//! \~english Basic functionality. //! \~english Basic functionality.
//! \~russian Базовая функциональность. //! \~russian Базовая функциональность.
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Core Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Core Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP) //! target_link_libraries([target] PIP)
//! \endcode //! \endcode

View File

@@ -22,6 +22,10 @@
#include "pistack.h" #include "pistack.h"
#include "piobject.h" #include "piobject.h"
#include "pistring_std.h" #include "pistring_std.h"
#ifdef HAS_LOCALE
# include <locale>
# include <codecvt>
#endif
#ifdef WINDOWS #ifdef WINDOWS
# include <windows.h> # include <windows.h>
# include <wingdi.h> # include <wingdi.h>
@@ -30,13 +34,8 @@
#endif #endif
//! \addtogroup Core
//! \{
//! \~\class PICout picout.h //! \~\class PICout picout.h
//! \~\brief //! \~\details
//! \~english Universal output to console class
//! \~russian Универсальный вывод в консоль
//!
//! \~english \section PICout_sec0 Synopsis //! \~english \section PICout_sec0 Synopsis
//! \~russian \section PICout_sec0 Краткий обзор //! \~russian \section PICout_sec0 Краткий обзор
//! \~english //! \~english
@@ -75,7 +74,6 @@
//! \~russian \section PICout_ex1 Создание своего оператора вывода //! \~russian \section PICout_ex1 Создание своего оператора вывода
//! \~\snippet picout.cpp own //! \~\snippet picout.cpp own
//! //!
//! \}
//! \addtogroup Core //! \addtogroup Core
@@ -85,8 +83,8 @@
//! \~english Class for emit notifications of PICout //! \~english Class for emit notifications of PICout
//! \~russian Класс для посылки событий от PICout //! \~russian Класс для посылки событий от PICout
//! //!
//! \~english \section PICout_sec0 Synopsis //! \~english \section PICoutNotifier_sec0 Synopsis
//! \~russian \section PICout_sec0 Краткий обзор //! \~russian \section PICoutNotifier_sec0 Краткий обзор
//! \~english //! \~english
//! This class used as PICout events emitter. When //! This class used as PICout events emitter. When
//! PICout constructs with external PIString* buffer //! PICout constructs with external PIString* buffer
@@ -333,12 +331,12 @@ PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v)
if (!act_) return *this; \ if (!act_) return *this; \
space(); \ space(); \
if (cnb_ == 10) PICOUTTOTARGET(v) \ if (cnb_ == 10) PICOUTTOTARGET(v) \
else writePIString(PIString::fromNumber(v, cnb_)); \ else write(PIString::fromNumber(v, cnb_)); \
return *this; \ return *this; \
} }
PICout PICout::operator <<(const char * v) {if (!act_) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} PICout PICout::operator <<(const char * v) {if (!act_ || !v) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;} PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
@@ -366,7 +364,7 @@ PICout PICout::operator <<(const float v) {if (!act_) return *this; space(); PIC
PICout PICout::operator <<(const double v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;} PICout PICout::operator <<(const double v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const void * v) {if (!act_) return *this; space(); PICOUTTOTARGET("0x") writePIString(PIString::fromNumber(ullong(v), 16)); return *this;} PICout PICout::operator <<(const void * v) {if (!act_) return *this; space(); PICOUTTOTARGET("0x") write(PIString::fromNumber(ullong(v), 16)); return *this;}
PICout PICout::operator <<(const PIObject * v) { PICout PICout::operator <<(const PIObject * v) {
if (!act_) return *this; if (!act_) return *this;
@@ -375,9 +373,9 @@ PICout PICout::operator <<(const PIObject * v) {
else { else {
PICOUTTOTARGET(v->className()) PICOUTTOTARGET(v->className())
PICOUTTOTARGET("*(0x") PICOUTTOTARGET("*(0x")
writePIString(PIString::fromNumber(ullong(v), 16)); write(PIString::fromNumber(ullong(v), 16));
PICOUTTOTARGET(", \"") PICOUTTOTARGET(", \"")
writePIString(v->name()); write(v->name());
PICOUTTOTARGET("\")") PICOUTTOTARGET("\")")
} }
return *this; return *this;
@@ -522,8 +520,14 @@ PICout & PICout::newLine() {
} }
PICout & PICout::write(const char * str) {
if (!act_ || !str) return *this;
return write(str, strlen(str));
}
PICout & PICout::write(const char * str, int len) { PICout & PICout::write(const char * str, int len) {
if (!act_) return *this; if (!act_ || !str) return *this;
if (buffer_) { if (buffer_) {
buffer_->append(PIString(str, len)); buffer_->append(PIString(str, len));
} else { } else {
@@ -534,20 +538,29 @@ PICout & PICout::write(const char * str, int len) {
} }
PICout & PICout::writePIString(const PIString & s) { PICout & PICout::write(const PIString & s) {
if (!act_) return *this; if (!act_) return *this;
if (buffer_) { if (buffer_) {
buffer_->append(s); buffer_->append(s);
} else { } else {
if (PICout::isOutputDeviceActive(PICout::StdOut)) { if (PICout::isOutputDeviceActive(PICout::StdOut))
for (const PIChar & c: s) std::wcout.put(c.toWChar()); stdoutPIString(s);
}
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s); if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s);
} }
return *this; return *this;
} }
void PICout::stdoutPIString(const PIString & s) {
#ifdef HAS_LOCALE
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> utf8conv;
std::cout << utf8conv.to_bytes((char16_t*)&(const_cast<PIString&>(s).front()), (char16_t*)&(const_cast<PIString&>(s).front()) + s.size());
#else
for (PIChar c: s) std::wcout.put(c.toWChar());
#endif
}
void PICout::init() { void PICout::init() {
#ifdef WINDOWS #ifdef WINDOWS
if (__Private__::hOut == 0) { if (__Private__::hOut == 0) {

View File

@@ -60,7 +60,7 @@ namespace PICoutManipulators {
NewLine /*! \~english New line character, '\\n' \~russian Новая строка, '\\n' */, NewLine /*! \~english New line character, '\\n' \~russian Новая строка, '\\n' */,
Tab /*! \~english Tab character, '\\t' \~russian Табуляция, '\\t' */, Tab /*! \~english Tab character, '\\t' \~russian Табуляция, '\\t' */,
Esc /*! \~english Escape character, '\\e' \~russian Esc-символ, '\\e' */, Esc /*! \~english Escape character, '\\e' \~russian Esc-символ, '\\e' */,
Quote /*! \~english Quote character, '"' \~russian Кавычки, '"' */ Quote /*! \~english Quote character, '\"' \~russian Кавычки, '\"' */
}; };
//! \~english Enum contains immediate action //! \~english Enum contains immediate action
@@ -125,6 +125,10 @@ namespace PICoutManipulators {
//! \ingroup Core
//! \~\brief
//! \~english Universal output to console class.
//! \~russian Универсальный вывод в консоль.
class PIP_EXPORT PICout { class PIP_EXPORT PICout {
public: public:
@@ -283,13 +287,21 @@ public:
//! \~russian Условно добавляет новую строку //! \~russian Условно добавляет новую строку
PICout & newLine(); PICout & newLine();
//! \~english Write raw data
//! \~russian Пишет сырые символы
PICout & write(const char * str);
//! \~english Write raw data //! \~english Write raw data
//! \~russian Пишет сырые символы //! \~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
PICout & writePIString(const PIString & s); PICout & write(const PIString & s);
//! \~english Output \a PIString to stdout
//! \~russian Вывод \a PIString в stdout
static void stdoutPIString(const PIString & s);
//! \~english Set output device to \a PICout::Buffer and if "clear" clear it //! \~english Set output device to \a PICout::Buffer and if "clear" clear it
//! \~russian Устанавливает устройство вывода на \a PICout::Buffer и если "clear" то очищает его //! \~russian Устанавливает устройство вывода на \a PICout::Buffer и если "clear" то очищает его

View File

@@ -35,20 +35,12 @@
//! \addtogroup Core //! \addtogroup Core
//! \{ //! \{
//!
//! \~\class PITime pidatetime.h //! \~\class PITime pidatetime.h
//! \brief
//! \~english Calendar time
//! \~russian Календарное время
//! //!
//! \~\class PIDate pidatetime.h //! \~\class PIDate pidatetime.h
//! \brief
//! \~english Calendar date
//! \~russian Календарная дата
//! //!
//! \~\class PIDateTime pidatetime.h //! \~\class PIDateTime pidatetime.h
//! \brief
//! \~english Calendar date and time
//! \~russian Календарное дата и время
//! //!
//! \} //! \}

View File

@@ -30,6 +30,10 @@
#include "pisystemtime.h" #include "pisystemtime.h"
//! \ingroup Core
//! \~\brief
//! \~english Calendar time.
//! \~russian Календарное время.
class PIP_EXPORT PITime { class PIP_EXPORT PITime {
public: public:
//! \~english Construct %PITime from hours, minutes, seconds and milliseconds //! \~english Construct %PITime from hours, minutes, seconds and milliseconds
@@ -102,6 +106,10 @@ PIP_EXPORT PICout operator <<(PICout s, const PITime & v);
//! \ingroup Core
//! \~\brief
//! \~english Calendar date.
//! \~russian Календарная дата.
class PIP_EXPORT PIDate { class PIP_EXPORT PIDate {
public: public:
//! \~english Construct %PIDate from year, month and day //! \~english Construct %PIDate from year, month and day
@@ -162,6 +170,10 @@ PIP_EXPORT PICout operator <<(PICout s, const PIDate & v);
//! \ingroup Core
//! \~\brief
//! \~english Calendar date and time.
//! \~russian Календарное дата и время.
class PIP_EXPORT PIDateTime { class PIP_EXPORT PIDateTime {
public: public:
//! \~english Construct null %PIDateTime //! \~english Construct null %PIDateTime

View File

@@ -64,10 +64,16 @@ void errorClear() {
PIString errorString() { PIString errorString() {
#ifdef WINDOWS #ifdef WINDOWS
char * msg; char * msg = nullptr;
int err = GetLastError(); int err = GetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
return "code " + PIString::fromNumber(err) + " - " + PIString(msg); PIString ret = PIStringAscii("code ") + PIString::fromNumber(err) + PIStringAscii(" - ");
if (msg) {
ret += PIString::fromSystem(msg).trim();
LocalFree(msg);
} else
ret += '?';
return ret;
#else #else
int e = errno; int e = errno;
return PIString("code ") + PIString::fromNumber(e) + " - " + PIString(strerror(e)); return PIString("code ") + PIString::fromNumber(e) + " - " + PIString(strerror(e));
@@ -88,237 +94,3 @@ void randomize() {
int randomi() { int randomi() {
return rand(); return rand();
} }
/*! \~english \mainpage What is PIP
* \~russian \mainpage Что такое PIP
*
* \~english
* PIP - Platform-Independent Primitives - is crossplatform library for C++ developers.
* It is wrap around STL and pure C++. This library can help developers write non-GUI
* projects much more quickly, efficiently and customizable than on pure C++.
* Library contains many classes, some of them are pure abstract, some classes
* can be used as they are, some classes should be inherited to new classes.
* PIP provide classes:
* * direct output to console (\a PICout)
* * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack)
* * byte array (\a PIByteArray)
* * string (\a PIString, \a PIStringList)
* * base object (events and handlers) (\a PIObject)
* * multithreading
* * thread (\a PIThread)
* * executor (\a PIThreadPoolExecutor)
* * blocking dequeue (\a PIBlockingDequeue)
* * timer (\a PITimer)
* * tiling console (with widgets) (\a PIScreen)
* * simple text rows
* * scroll bar
* * list
* * button
* * buttons group
* * check box
* * progress bar
* * PICout output
* * text input
* * I/O devices
* * base class (\a PIIODevice)
* * file (\a PIFile)
* * serial port (\a PISerial)
* * ethernet (\a PIEthernet)
* * USB (\a PIUSB)
* * packets extractor (\a PIPacketExtractor)
* * binary log (\a PIBinaryLog)
* * complex I/O point (\a PIConnection)
* * Run-time libraries
* * abstract (\a PILibrary)
* * plugin (\a PIPluginLoader)
* * connection quality diagnotic (\a PIDiagnostics)
* * command-line arguments parser (\a PICLI)
* * math evaluator (\a PIEvaluator)
* * peering net node (\a PIPeer)
* * process (\a PIProcess)
* * state machine (\a PIStateMachine)
* \n \n Basic using of PIP described at page \ref using_basic
*
* \~russian
* PIP - Platform-Independent Primitives - кроссплатформенная библиотека для разработчиков на C++.
* It is wrap around STL and pure C++. This library can help developers write non-GUI
* projects much more quickly, efficiently and customizable than on pure C++.
* PIP предоставляет следующие классы:
* * общение с консолью (\a PICout)
* * контейнеры (\a PIVector, \a PIList, \a PIMap, \a PIStack)
* * байтовый массив (\a PIByteArray)
* * строка (\a PIString, \a PIStringList)
* * базовый объект (события и обработчики) (\a PIObject)
* * многопоточность
* * поток (\a PIThread)
* * исполнитель (\a PIThreadPoolExecutor)
* * блокирующая очередь (\a PIBlockingDequeue)
* * таймер (\a PITimer)
* * тайлинговая консоль (с виджетами) (\a PIScreen)
* * простой вывод строк
* * скроллбар
* * лист
* * кнопка
* * группа кнопок
* * галочка
* * прогрессбар
* * вывод PICout
* * текстовый ввод
* * устройства ввода/вывода
* * базовый класс (\a PIIODevice)
* * файл (\a PIFile)
* * последовательный порт (\a PISerial)
* * ethernet (\a PIEthernet)
* * USB (\a PIUSB)
* * packets extractor (\a PIPacketExtractor)
* * бинарный логфайл (\a PIBinaryLog)
* * сложное составное устройство (\a PIConnection)
* * поддержка библиотек времени выполнения
* * базовая функциональность (\a PILibrary)
* * плагин (\a PIPluginLoader)
* * диагностика качества связи (\a PIDiagnostics)
* * парсер аргументов командной строки (\a PICLI)
* * вычислитель (\a PIEvaluator)
* * пиринговая сеть (\a PIPeer)
* * процесс (\a PIProcess)
* * машина состояний (\a PIStateMachine)
* \n \n Базовое использование PIP описано на странице \ref using_basic
*/
/*! \~english \page using_basic Getting started
* \~russian \page using_basic Простые начала
*
* \~english
* Many novice programmers are solved many common task with system integrity: output to console,
* keyboard buttons press detecting, working with serial ports, ethernet or files, and many other.
* These tasks can solve this library, and code, based only on PIP will be compile and work
* similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX.
* Typical application on PIP looks like this: \n
*
* \~russian
* Многие начинающие программисты решают общие задачи взаимодействия с операционной системой:
* вывод в консоль, определение нажатия клавиш, работа с последовательными портами, сетью или файлами,
* и многое другое. Эти задачи решены в библиотеке, и код, основанный на PIP будет компилироваться
* и работать одинаково на многих системах: Windows, любой Linux, Red Hat, FreeBSD, MacOS X и QNX.
* Типовое приложение на PIP выглядит примерно так: \n
*
\code{.cpp}
#include <pip.h>
// declare key press handler
void key_event(char key, void * );
PIConsole console(false, key_event); // don`t start now, key handler is "key_event"
// some vars
int i = 2, j = 3;
// implicit key press handler
void key_event(char key, void * ) {
switch (key) {
case '-':
i--;
break;
case '+':
i++;
break;
case '(':
j--;
break;
case ')':
j++;
break;
};
};
class MainClass: public PITimer {
PIOBJECT(MainClass)
public:
MainClass() {}
protected:
void tick(void * data, int delimiter) {
piCout << "timer tick";
// timer tick
}
};
MainClass main_class;
int main(int argc, char * argv[]) {
// enabling auto-detection of exit button press, by default 'Q' (shift+q)
console.enableExitCapture();
// if we want to parse command-line arguments
PICLI cli(argc, argv);
cli.addArgument("console"); // "-c" or "--console"
cli.addArgument("debug"); // "-d" or "--debug"
// enabling or disabling global debug flag
piDebug = cli.hasArgument("debug");
// configure console
console.addTab("first tab", '1');
console.addString("PIP console", 1, PIConsole::Bold);
console.addVariable("int var (i)", &i, 1);
console.addVariable("int green var (j)", &j, 1, PIConsole::Green);
console.addString("'-' - i--", 2);
console.addString("'+' - i++", 2);
console.addString("'(' - j--", 2);
console.addString("')' - j++", 2);
console.addTab("second tab", '2');
console.addString("col 1", 1);
console.addString("col 2", 2);
console.addString("col 3", 3);
console.setTab("first tab");
// start output to console if "console" argument exists
if (cli.hasArgument("console"))
console.start();
// start main class, e.g. 40 Hz
main_class.start(25.);
// wait for 'Q' press, independently if console is started or not
console.waitForFinish();
return 0;
};
\endcode
*
* \~english
* 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
* \a PIThread and reimplement \a run() function.
* \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).
* \n To configure your program from file use \a PIConfig.
* \n If you want more information see \ref using_advanced
*
* \~russian
* Этот код демонстрирует простую конфигурируемую программу, которая может быть запущена с
* 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
* \a PIThread and reimplement \a run() function.
* \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).
* \n To configure your program from file use \a PIConfig.
*/
/*! \page using_advanced Advanced using
* Sorry, creativity crysis xD
*/
/*
* \~english
* \~russian
*/

View File

@@ -152,12 +152,16 @@ PIInit::PIInit() {
} }
# endif //WINDOWS # endif //WINDOWS
# ifdef HAS_LOCALE # ifdef HAS_LOCALE
//cout << "has locale" << endl; //std::cout << "has locale" << std::endl;
if (currentLocale_t != 0) { if (currentLocale_t != 0) {
freelocale(currentLocale_t); freelocale(currentLocale_t);
currentLocale_t = 0; currentLocale_t = 0;
} }
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0); currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, "C"), 0);
setlocale(LC_CTYPE, "en_US.UTF-8");
//std::ios_base::sync_with_stdio(false);
//std::locale utf8( std::locale(), new std::codecvt_utf8<wchar_t> );
//std::wcout.imbue(utf8);
# else //HAS_LOCALE # else //HAS_LOCALE
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
@@ -212,9 +216,6 @@ PIInit::PIInit() {
if (gethostname(cbuff, 1023) == 0) { if (gethostname(cbuff, 1023) == 0) {
sinfo->hostname = cbuff; sinfo->hostname = cbuff;
} }
// std::ios_base::sync_with_stdio(false);
// std::locale utf8( std::locale(), new std::codecvt_utf8<wchar_t> );
// std::wcout.imbue(utf8);
#ifdef WINDOWS #ifdef WINDOWS
SYSTEM_INFO sysinfo; SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo); GetSystemInfo(&sysinfo);

View File

@@ -26,13 +26,7 @@
#endif #endif
//! \addtogroup Core
//! \{
//! \~\class PIObject piobject.h //! \~\class PIObject piobject.h
//! \~\brief
//! \~english This is base class for any classes which use events -> handlers mechanism
//! \~russian Этот класс является базовым для использования механизма события -> обработчики
//!
//! \~\details //! \~\details
//! \~english \section PIObject_sec0 Events and Event handlers //! \~english \section PIObject_sec0 Events and Event handlers
//! \~russian \section PIObject_sec0 События и Обработчики событий //! \~russian \section PIObject_sec0 События и Обработчики событий
@@ -98,34 +92,88 @@
//! handler A: event to event //! handler A: event to event
//! event to lambda //! event to lambda
//! \endcode //! \endcode
//! \} //!
//! \addtogroup Core
//! \{
//! \~\class PIObject::Connection piobject.h //! \~\class PIObject::Connection piobject.h
//! \~\brief //! \~\details
//! \~english Helper class for obtain info about if connection successful and disconnect single connection //!
//! \~russian Вспомогательный класс для получения информации об успешности соединения и возможности его разрыва
//! \}
PIObject::__MetaFunc::__MetaFunc() {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
types[i] = names[i] = nullptr;
types_id[i] = 0;
}
}
int PIObject::__MetaFunc::argumentsCount() const {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i)
if (!types[i])
return i;
return __PIOBJECT_MAX_ARGS__;
}
PIString PIObject::__MetaFunc::arguments() const { PIString PIObject::__MetaFunc::arguments() const {
return types.join(","); PIString ret;
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (!types[i]) break;
if (!ret.isEmpty()) ret += ',';
ret += PIStringAscii(types[i]);
}
return ret;
} }
PIString PIObject::__MetaFunc::fullFormat() const { PIString PIObject::__MetaFunc::fullFormat() const {
PIString ret = type_ret + " " + scope + "::" + func_name +"("; PIString ret = PIStringAscii(type_ret) + " " +
for (int i = 0; i < types.size_s(); ++i) { PIStringAscii(scope) + "::" +
PIStringAscii(func_name) +"(";
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (!types[i]) break;
if (i > 0) ret += ", "; if (i > 0) ret += ", ";
ret += types[i] + " " + names[i]; ret += PIStringAscii(types[i]) + " " + PIStringAscii(names[i]);
} }
ret += ")"; ret += ")";
return ret; return ret;
} }
void PIObject::__MetaFunc::__setFuncName(const char * n) {
func_name = n;
func_name_id = PIStringAscii(n).hash();
}
void PIObject::__MetaFunc::__addArgument(const char * t, const char * n) {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (types[i]) continue;
types[i] = t;
names[i] = n;
types_id[i] = PIObject::simplifyType(t, false).hash();
break;
}
//PICout(PICoutManipulators::DefaultControls | PICoutManipulators::AddQuotes)
// << "__addArgument" << t << n << PIObject::simplifyType(t) << types_id.back();
}
bool PIObject::__MetaFunc::canConnectTo(const __MetaFunc & dst, int & args_count) const {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
//piCout << "canConnectTo" << i << types[i] << dst.types[i];
args_count = i;
if (!dst.types[i]) break;
if (!types[i]) return false;
if (types_id[i] != dst.types_id[i])
return false;
}
return true;
}
PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false), proc_event_queue(false) { PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false), proc_event_queue(false) {
in_event_cnt = 0; in_event_cnt = 0;
setName(name); setName(name);
@@ -148,15 +196,6 @@ PIObject::~PIObject() {
} }
PIMap<PIString, PIVariant> PIObject::properties() const {
PIMap<PIString, PIVariant> ret;
piForeachC (PropertyHash p, properties_)
ret[p.second.first] = p.second.second;
return ret;
}
bool PIObject::execute(const PIString & method, const PIVector<PIVariantSimple> & vl) { bool PIObject::execute(const PIString & method, const PIVector<PIVariantSimple> & vl) {
@@ -196,8 +235,13 @@ bool PIObject::executeQueued(PIObject * performer, const PIString & method, cons
PIStringList PIObject::scopeList() const { PIStringList PIObject::scopeList() const {
PIStringList ret;
ret.reserve(2);
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
return __meta_data()[classNameID()].scope_list; const PIVector<const char *> & scope(__meta_data()[classNameID()].scope_list);
for (const char * c: scope)
ret << PIStringAscii(c);
return ret;
} }
@@ -212,10 +256,11 @@ PIStringList PIObject::methodsEH() const {
bool PIObject::isMethodEHContains(const PIString & name) const { bool PIObject::isMethodEHContains(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
return true; return true;
} }
return false; return false;
@@ -223,10 +268,11 @@ bool PIObject::isMethodEHContains(const PIString & name) const {
PIString PIObject::methodEHArguments(const PIString & name) const { PIString PIObject::methodEHArguments(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
return eh.value().arguments(); return eh.value().arguments();
} }
return PIString(); return PIString();
@@ -234,10 +280,11 @@ PIString PIObject::methodEHArguments(const PIString & name) const {
PIString PIObject::methodEHFullFormat(const PIString & name) const { PIString PIObject::methodEHFullFormat(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
return eh.value().fullFormat(); return eh.value().fullFormat();
} }
return PIString(); return PIString();
@@ -250,10 +297,11 @@ PIString PIObject::methodEHFromAddr(const void * addr) const {
PIVector<PIObject::__MetaFunc> PIObject::findEH(const PIString & name) const { PIVector<PIObject::__MetaFunc> PIObject::findEH(const PIString & name) const {
uint search_id = name.hash();
PIVector<__MetaFunc> ret; PIVector<__MetaFunc> ret;
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
ret << eh.value(); ret << eh.value();
} }
return ret; return ret;
@@ -313,10 +361,9 @@ PIObject::Connection PIObject::piConnectU(PIObject * src, const PIString & sig,
if (addr_src != 0) break; if (addr_src != 0) break;
piForeachC (__MetaFunc & fd, m_dest) { piForeachC (__MetaFunc & fd, m_dest) {
if (addr_src != 0) break; if (addr_src != 0) break;
if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) { if (fs.canConnectTo(fd, args)) {
addr_src = fs.addr; addr_src = fs.addr;
addr_dest = que ? fd.addrV : fd.addr; addr_dest = que ? fd.addrV : fd.addr;
args = fd.names.size_s();
} }
} }
} }
@@ -528,7 +575,7 @@ bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_
int mfi = -1, ac = -1, mac = -1; int mfi = -1, ac = -1, mac = -1;
for (int i = 0; i < ml.size_s(); ++i) { for (int i = 0; i < ml.size_s(); ++i) {
__MetaFunc & m(ml[i]); __MetaFunc & m(ml[i]);
int j = m.names.size_s(); int j = m.argumentsCount();
if (mac < 0 || mac > j) mac = j; if (mac < 0 || mac > j) mac = j;
if ((j <= args) && (ac < j)) { if ((j <= args) && (ac < j)) {
ac = j; ac = j;
@@ -570,8 +617,9 @@ void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector<PIVar
} }
PIString PIObject::simplifyType(const char * a) { PIString PIObject::simplifyType(const char * a, bool readable) {
PIString ret = PIStringAscii(a).trim(); PIString ret = PIStringAscii(a).trim();
if (readable) {
int white = -1; int white = -1;
for (int i = 0; i < ret.size_s(); ++i) { for (int i = 0; i < ret.size_s(); ++i) {
bool iw = ret[i] == ' ' || ret[i] == '\t' || ret[i] == '\r' || ret[i] == '\n'; bool iw = ret[i] == ' ' || ret[i] == '\t' || ret[i] == '\r' || ret[i] == '\n';
@@ -590,10 +638,25 @@ PIString PIObject::simplifyType(const char * a) {
} }
} }
} }
ret.replaceAll(" &", "&"); ret.replaceAll(" [", '[');
ret.replaceAll(" *", "*"); ret.replaceAll(" ]", ']');
ret.replaceAll(" <", '<');
ret.replaceAll(" >", '>');
ret.replaceAll(" &", '&');
ret.replaceAll(" *", '*');
ret.replaceAll("[ ", '[');
ret.replaceAll("] ", ']');
ret.replaceAll("< ", '<');
ret.replaceAll("> ", '>');
ret.replaceAll("& ", '&');
ret.replaceAll("* ", '*');
if (ret.startsWith("const ") && ret.endsWith("&")) if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim(); ret.cutLeft(6).cutRight(1).trim();
} else {
if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim();
ret.removeAll(' ').removeAll('\t').removeAll('\r').removeAll('\n');
}
return ret; return ret;
} }
@@ -611,9 +674,12 @@ void PIObject::dump(const PIString & line_prefix) const {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " properties {"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " properties {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << properties_.size_s(); PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << properties_.size_s();
//printf("dump %d properties\n", properties_.size()); //printf("dump %d properties\n", properties_.size());
piForeachC (PropertyHash p, properties_) const char * o_name = "name";
if (p.first != PIString("name").hash()) auto it = properties_.makeIterator();
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << p.second.first << ": " << p.second.second; while (it.next()) {
if (it.key() != piHashData((const uchar *)o_name, strlen(o_name)))
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << it.key() << ": " << it.value();
}
//printf("dump %d properties ok\n", properties_.size()); //printf("dump %d properties ok\n", properties_.size());
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " methods {"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " methods {";
@@ -628,17 +694,18 @@ void PIObject::dump(const PIString & line_prefix) const {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " connections {"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " connections {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << connections.size_s(); PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << connections.size_s();
//printf("dump %d connections\n",connections.size()); //printf("dump %d connections\n",connections.size());
piForeachC (Connection & c, connections) { for (const Connection & c : connections) {
PIObject * dst = c.dest_o; PIObject * dst = c.dest_o;
__MetaFunc ef = methodEH(c.signal); __MetaFunc ef = methodEH(c.signal);
PIString src(c.event); PIString src(c.event);
if (!ef.func_name.isEmpty()) if (ef.func_name)
src = ef.func_name + "(" + ef.arguments() + ")"; src = PIStringAscii(ef.func_name) + "(" + ef.arguments() + ")";
if (dst) { if (dst) {
__MetaFunc hf = dst->methodEH(c.slot); __MetaFunc hf = dst->methodEH(c.slot);
if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]"; PIString hf_fn;
else hf.func_name += "(" + hf.arguments() + ")"; if (!hf.func_name) hf_fn = "[BROKEN]";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name; else hf_fn = PIStringAscii(hf.func_name) + "(" + hf.arguments() + ")";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf_fn;
} else { } else {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]";
} }
@@ -650,7 +717,7 @@ void PIObject::dump(const PIString & line_prefix) const {
#ifndef MICRO_PIP #ifndef MICRO_PIP
void dumpApplication() { void dumpApplication(bool with_objects) {
PIMutexLocker _ml(PIObject::mutexObjects()); PIMutexLocker _ml(PIObject::mutexObjects());
//printf("dump application ...\n"); //printf("dump application ...\n");
PIDateTime cd = PIDateTime::current(); PIDateTime cd = PIDateTime::current();
@@ -668,22 +735,24 @@ void dumpApplication() {
PICout(PICoutManipulators::AddNewLine) << " uptime: " << PITime::fromSystemTime(cd.toSystemTime() - pi->execDateTime.toSystemTime()).toString(); PICout(PICoutManipulators::AddNewLine) << " uptime: " << PITime::fromSystemTime(cd.toSystemTime() - pi->execDateTime.toSystemTime()).toString();
PICout(PICoutManipulators::AddNewLine) << " PIObjects {"; PICout(PICoutManipulators::AddNewLine) << " PIObjects {";
PICout(PICoutManipulators::AddNewLine) << " count: " << PIObject::objects().size_s(); PICout(PICoutManipulators::AddNewLine) << " count: " << PIObject::objects().size_s();
piForeachC (PIObject * o, PIObject::objects()) if (with_objects) {
for (const PIObject * o: PIObject::objects())
o->dump(" "); o->dump(" ");
}
PICout(PICoutManipulators::AddNewLine) << " }"; PICout(PICoutManipulators::AddNewLine) << " }";
PICout(PICoutManipulators::AddNewLine) << "}"; PICout(PICoutManipulators::AddNewLine) << "}";
//printf("dump application done\n"); //printf("dump application done\n");
} }
bool dumpApplicationToFile(const PIString & path) { bool dumpApplicationToFile(const PIString & path, bool with_objects) {
PIFile f(path + "_tmp"); PIFile f(path + "_tmp");
f.setName("__S__DumpFile"); f.setName("__S__DumpFile");
f.clear(); f.clear();
if (!f.open(PIIODevice::WriteOnly)) return false; if (!f.open(PIIODevice::WriteOnly)) return false;
bool ba = PICout::isBufferActive(); bool ba = PICout::isBufferActive();
PICout::setBufferActive(true, true); PICout::setBufferActive(true, true);
dumpApplication(); dumpApplication(with_objects);
f << PICout::buffer(); f << PICout::buffer();
f.close(); f.close();
PICout::setBufferActive(ba, true); PICout::setBufferActive(ba, true);
@@ -693,7 +762,7 @@ bool dumpApplicationToFile(const PIString & path) {
#endif #endif
void PIObject::__MetaData::addScope(const PIString & s, uint shash) { void PIObject::__MetaData::addScope(const char * s, uint shash) {
if (!scope_id.contains(shash)) { if (!scope_id.contains(shash)) {
scope_list << s; scope_list << s;
scope_id << shash; scope_id << shash;

View File

@@ -34,13 +34,16 @@
#include "piqueue.h" #include "piqueue.h"
#include "piobject_macros.h" #include "piobject_macros.h"
typedef void (*Handler)(void * ); typedef void (*Handler)(void * );
//! \ingroup Core
//! \~\brief
//! \~english This is base class for any classes which use events -> handlers mechanism.
//! \~russian Этот класс является базовым для использования механизма события -> обработчики.
class PIP_EXPORT PIObject { class PIP_EXPORT PIObject {
#ifndef MICRO_PIP #ifndef MICRO_PIP
friend class PIObjectManager; friend class PIObjectManager;
friend void dumpApplication(); friend void dumpApplication(bool);
friend class PIIntrospection; friend class PIIntrospection;
#endif #endif
typedef PIObject __PIObject__; typedef PIObject __PIObject__;
@@ -54,6 +57,10 @@ public:
virtual ~PIObject(); virtual ~PIObject();
//! \ingroup Core
//! \~\brief
//! \~english Helper class for obtain info about if connection successful and disconnect single connection.
//! \~russian Вспомогательный класс для получения информации об успешности соединения и возможности его разрыва.
class PIP_EXPORT Connection { class PIP_EXPORT Connection {
friend class PIObject; friend class PIObject;
Connection(void * sl, void * si, const PIString & e = PIString(), Connection(void * sl, void * si, const PIString & e = PIString(),
@@ -99,7 +106,7 @@ public:
PIObject * destinationObject() const {return dest_o;} PIObject * destinationObject() const {return dest_o;}
//! \~english Returns performer object or "nullptr" if this is non-queued connection //! \~english Returns performer object or "nullptr" if this is non-queued connection
//! \~russian Возвращает объект-приемник или "nullptr" если это соединение не отложенное //! \~russian Возвращает объект-исполнитель или "nullptr" если это соединение не отложенное
PIObject * performerObject() const {return performer;} PIObject * performerObject() const {return performer;}
//! \~english Disconnect this %Connection, returns if operation successful //! \~english Disconnect this %Connection, returns if operation successful
@@ -114,7 +121,7 @@ public:
//! \~english Returns object name //! \~english Returns object name
//! \~russian Возвращает имя объекта //! \~russian Возвращает имя объекта
PIString name() const {return property(PIStringAscii("name")).toString();} PIString name() const {return property("name").toString();}
//! \~english Returns object class name //! \~english Returns object class name
//! \~russian Возвращает имя класса объекта //! \~russian Возвращает имя класса объекта
@@ -122,7 +129,7 @@ public:
virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;} virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
static const PIString __classNameS() {return PIStringAscii("PIObject");} static const char * __classNameCC() {return "PIObject";}
static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;} static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
//! \~english Returns parent class name //! \~english Returns parent class name
@@ -132,40 +139,28 @@ public:
//! \~english Return if \a piCoutObj of this object is active //! \~english Return if \a piCoutObj of this object is active
//! \~russian Возвращает включен ли вывод \a piCoutObj для этого объекта //! \~russian Возвращает включен ли вывод \a piCoutObj для этого объекта
bool debug() const {return property(PIStringAscii("debug")).toBool();} bool debug() const {return property("debug").toBool();}
//! \~english Set object name //! \~english Set object name
//! \~russian Устанавливает имя объекта //! \~russian Устанавливает имя объекта
void setName(const PIString & name) {setProperty(PIStringAscii("name"), name);} void setName(const PIString & name) {setProperty("name", name);}
void setName(const char * name) {setName(PIStringAscii(name));}
//! \~english Set object \a piCoutObj active //! \~english Set object \a piCoutObj active
//! \~russian Включает или отключает вывод \a piCoutObj для этого объекта //! \~russian Включает или отключает вывод \a piCoutObj для этого объекта
void setDebug(bool debug) {setProperty(PIStringAscii("debug"), debug);} void setDebug(bool debug) {setProperty("debug", debug);}
//! \~english Returns properties of the object
//! \~russian Возвращает словарь свойств объекта
PIMap<PIString, PIVariant> properties() const;
//! \~english Returns properties count of the object
//! \~russian Возвращает количество свойств объекта
int propertiesCount() const {return properties_.size_s();}
//! \~english Returns property with name "name" //! \~english Returns property with name "name"
//! \~russian Возвращает свойство объекта по имени "name" //! \~russian Возвращает свойство объекта по имени "name"
PIVariant property(const PIString & name) const {return properties_.value(name.hash(), Property(PIString(), PIVariant())).second;} PIVariant property(const char * name) const {return properties_.value(piHashData((const uchar *)name, strlen(name)));}
PIVariant property(const char * name) const {return property(PIStringAscii(name));}
//! \~english Set property with name "name" to "value". If there is no such property in object it will be added //! \~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". Если такого свойства нет, оно добавляется
void setProperty(const PIString & name, const PIVariant & value) {properties_[name.hash()] = Property(name, value); propertyChanged(name);} void setProperty(const char * name, const PIVariant & value) {properties_[piHashData((const uchar *)name, strlen(name))] = value; propertyChanged(name);}
void setProperty(const char * name, const PIVariant & value) {setProperty(PIStringAscii(name), value);}
//! \~english Returns if property with name "name" exists //! \~english Returns if property with name "name" exists
//! \~russian Возвращает присутствует ли свойство по имени "name" //! \~russian Возвращает присутствует ли свойство по имени "name"
bool isPropertyExists(const PIString & name) const {return properties_.contains(name.hash());} bool isPropertyExists(const char * name) const {return properties_.contains(piHashData((const uchar *)name, strlen(name)));}
bool isPropertyExists(const char * name) const {return isPropertyExists(PIStringAscii(name));}
void setThreadSafe(bool yes) {thread_safe_ = yes;} void setThreadSafe(bool yes) {thread_safe_ = yes;}
bool isThreadSafe() const {return thread_safe_;} bool isThreadSafe() const {return thread_safe_;}
@@ -437,7 +432,8 @@ public:
template<typename T> template<typename T>
bool isTypeOf() const { bool isTypeOf() const {
if (!isPIObject()) return false; if (!isPIObject()) return false;
return scopeList().contains(T::__classNameS()); PIMutexLocker ml(__meta_mutex());
return __meta_data()[classNameID()].scope_id.contains(T::__classNameIDS());
} }
//! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr" //! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr"
@@ -459,26 +455,32 @@ public:
static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();} static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();}
template<typename T> template<typename T>
static bool isTypeOf(const void * o) {return isTypeOf<T>((PIObject*)o);} static bool isTypeOf(const void * o) {return isTypeOf<T>((PIObject*)o);}
static PIString simplifyType(const char * a); static PIString simplifyType(const char * a, bool readable = true);
struct PIP_EXPORT __MetaFunc { struct PIP_EXPORT __MetaFunc {
__MetaFunc(): addr(0), addrV(0) {;} __MetaFunc();
bool isNull() const {return addr == 0;} bool isNull() const {return addr == nullptr;}
int argumentsCount() const;
PIString arguments() const; PIString arguments() const;
PIString fullFormat() const; PIString fullFormat() const;
void * addr; void __setFuncName(const char * n);
void * addrV; void __addArgument(const char * t, const char * n);
PIString func_name; bool canConnectTo(const __MetaFunc & dst, int & args_count) const;
PIString type_ret; void * addr = nullptr;
PIString scope; void * addrV = nullptr;
PIStringList types; uint func_name_id = 0;
PIStringList names; const char * func_name = nullptr;
const char * type_ret = nullptr;
const char * scope = nullptr;
const char * types[__PIOBJECT_MAX_ARGS__];
const char * names[__PIOBJECT_MAX_ARGS__];
uint types_id[__PIOBJECT_MAX_ARGS__];
}; };
struct PIP_EXPORT __MetaData { struct PIP_EXPORT __MetaData {
__MetaData() {scope_list << PIStringAscii("PIObject"); scope_id << PIStringAscii("PIObject").hash();} __MetaData() {scope_list << "PIObject"; scope_id << PIStringAscii("PIObject").hash();}
void addScope(const PIString & s, uint shash); void addScope(const char * s, uint shash);
PIStringList scope_list; PIVector<const char *> scope_list;
PISet<uint> scope_id; PISet<uint> scope_id;
PISet<const void * > eh_set; PISet<const void * > eh_set;
PIMap<const void * , __MetaFunc> eh_func; PIMap<const void * , __MetaFunc> eh_func;
@@ -514,7 +516,7 @@ protected:
//! \~english Virtual function executes after property with name "name" has been changed //! \~english Virtual function executes after property with name "name" has been changed
//! \~russian Виртуальная функция, вызывается после изменения любого свойства. //! \~russian Виртуальная функция, вызывается после изменения любого свойства.
virtual void propertyChanged(const PIString & name) {} virtual void propertyChanged(const char * name) {}
EVENT1(deleted, PIObject *, o) EVENT1(deleted, PIObject *, o)
@@ -563,9 +565,6 @@ private:
PRIVATE_DECLARATION(PIP_EXPORT) PRIVATE_DECLARATION(PIP_EXPORT)
}; };
typedef PIPair<PIString, PIVariant> Property;
typedef PIPair<uint, PIPair<PIString, PIVariant> > PropertyHash;
bool findSuitableMethodV(const PIString & method, int args, int & ret_args, __MetaFunc & ret); bool findSuitableMethodV(const PIString & method, int args, int & ret_args, __MetaFunc & ret);
PIVector<__MetaFunc> findEH(const PIString & name) const; PIVector<__MetaFunc> findEH(const PIString & name) const;
__MetaFunc methodEH(const void * addr) const; __MetaFunc methodEH(const void * addr) const;
@@ -585,7 +584,7 @@ private:
PIVector<Connection> connections; PIVector<Connection> connections;
PIMap<uint, PIPair<PIString, PIVariant> > properties_; PIMap<uint, PIVariant> properties_;
PISet<PIObject * > connectors; PISet<PIObject * > connectors;
PIVector<__QueuedEvent> events_queue; PIVector<__QueuedEvent> events_queue;
PIMutex mutex_, mutex_connect, mutex_queue; PIMutex mutex_, mutex_connect, mutex_queue;
@@ -596,8 +595,8 @@ private:
}; };
#ifndef MICRO_PIP #ifndef MICRO_PIP
PIP_EXPORT void dumpApplication(); PIP_EXPORT void dumpApplication(bool with_objects = true);
PIP_EXPORT bool dumpApplicationToFile(const PIString & path); PIP_EXPORT bool dumpApplicationToFile(const PIString & path, bool with_objects = true);
#endif #endif
#endif // PIOBJECT_H #endif // PIOBJECT_H

View File

@@ -385,13 +385,14 @@
# define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType # define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType
#endif #endif
#define __VVALUE(t, v) v.value< __PTYPE(t) >() #define __VVALUE(t, v) v.value< __PTYPE(t) >()
#define __PIOBJECT_MAX_ARGS__ 4
#define PIOBJECT(name) \ #define PIOBJECT(name) \
protected: \ protected: \
typedef name __PIObject__; \ typedef name __PIObject__; \
public: \ public: \
static const PIString __classNameS() {static PIString ret = PIStringAscii(#name); return ret;} \ static const char * __classNameCC() {return #name;} \
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \ static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
virtual const char * className() const {return #name;} \ virtual const char * className() const {return #name;} \
virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \ virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \
@@ -411,7 +412,7 @@
__MetaData & eh(__meta_data()[id]); \ __MetaData & eh(__meta_data()[id]); \
eh.eh_set << ehp.eh_set; \ eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \ eh.eh_func << ehp.eh_func; \
eh.addScope(__classNameS(), id); \ eh.addScope(__classNameCC(), id); \
} \ } \
}; \ }; \
__BaseInitializer__ __base_init__; __BaseInitializer__ __base_init__;
@@ -431,7 +432,7 @@
eh.eh_func << ehp.eh_func; \ eh.eh_func << ehp.eh_func; \
eh.scope_id = ehp.scope_id; \ eh.scope_id = ehp.scope_id; \
eh.scope_list = ehp.scope_list; \ eh.scope_list = ehp.scope_list; \
eh.addScope(__classNameS(), id); \ eh.addScope(__classNameCC(), id); \
} \ } \
}; \ }; \
__ParentInitializer__ __parent_init__; \ __ParentInitializer__ __parent_init__; \
@@ -443,92 +444,61 @@
#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent) #define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)
#define EH_INIT0(ret, name) \ #define __EH_INIT_BASE__(ret, name) \
STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \ PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \ __MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
void * fpV = fp; \
if (eh.eh_set[fp]) return; \ if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \ eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \ __MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \ f.scope = __classNameCC(); \
f.func_name = PIStringAscii(#name); \ f.__setFuncName(#name); \
f.addr = fp; \ f.addr = fp; \
f.addrV = fpV; \ f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \ f.type_ret = #ret;
#define EH_INIT0(ret, name) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
void * fpV = fp; \
__EH_INIT_BASE__(ret, name) \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
#define EH_INIT1(ret, name, a0, n0) \ #define EH_INIT1(ret, name, a0, n0) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0); \
f.names << PIStringAscii(#n0); \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
#define EH_INIT2(ret, name, a0, n0, a1, n1) \ #define EH_INIT2(ret, name, a0, n0, a1, n1) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__MetaFunc & f(eh.eh_func[fp]); \ f.__addArgument(#a1, #n1); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1); \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ #define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__MetaFunc & f(eh.eh_func[fp]); \ f.__addArgument(#a1, #n1); \
f.scope = __classNameS(); \ f.__addArgument(#a2, #n2); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2); \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ #define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__MetaFunc & f(eh.eh_func[fp]); \ f.__addArgument(#a1, #n1); \
f.scope = __classNameS(); \ f.__addArgument(#a2, #n2); \
f.func_name = PIStringAscii(#name); \ f.__addArgument(#a3, #n3); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2) << PIObject::simplifyType(#a3); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2) << PIStringAscii(#n3); \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END

View File

@@ -20,13 +20,7 @@
#include "pipropertystorage.h" #include "pipropertystorage.h"
//! \addtogroup Core
//! \{
//! \~\class PIPropertyStorage pipropertystorage.h //! \~\class PIPropertyStorage pipropertystorage.h
//! \~\brief
//! \~english This class provides key-value properties storage
//! \~russian Этот класс предоставляет ключ-значение хранение свойств
//!
//! \~\details //! \~\details
//! \~english \section PIPropertyStorage_sec0 Synopsis //! \~english \section PIPropertyStorage_sec0 Synopsis
//! \~russian \section PIPropertyStorage_sec0 Краткий обзор //! \~russian \section PIPropertyStorage_sec0 Краткий обзор
@@ -45,35 +39,12 @@
//! \~russian Пример: //! \~russian Пример:
//! \~\code{.cpp} //! \~\code{.cpp}
//! \endcode //! \endcode
//! \} //!
//! \addtogroup Core
//! \{
//! \~\class PIPropertyStorage::Property pipropertystorage.h //! \~\class PIPropertyStorage::Property pipropertystorage.h
//! \~\brief
//! \~english PIPropertyStorage element
//! \~russian Элемент PIPropertyStorage
//!
//! \~\details //! \~\details
//! \~english \section PIPropertyStorage_sec0 Synopsis
//! \~russian \section PIPropertyStorage_sec0 Краткий обзор
//! //!
//! \~english
//! Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector
//! contains unique name. You can access property by name with \a propertyValueByName() or \a propertyByName().
//! You can add or replace property by \a addProperty(const Property&) or \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
//!
//! \~russian
//! Хранилище свойств ключ-значние, основанный на PIVector с элементами PIPropertyStorage::Property.
//! Каждый элемент имеет уникальное имя. Доступ к свойствам через \a propertyValueByName() или \a propertyByName().
//! Добавление и перезапись свойств через \a addProperty(const Property&) или \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
//!
//! \~english Example:
//! \~russian Пример:
//! \~\code{.cpp}
//! \endcode
//! \}
bool PIPropertyStorage::isPropertyExists(const PIString & _name) const { bool PIPropertyStorage::isPropertyExists(const PIString & _name) const {

View File

@@ -29,6 +29,10 @@
#include "pivariant.h" #include "pivariant.h"
//! \ingroup Core
//! \~\brief
//! \~english This class provides key-value properties storage.
//! \~russian Этот класс предоставляет ключ-значение хранение свойств.
class PIP_EXPORT PIPropertyStorage { class PIP_EXPORT PIPropertyStorage {
public: public:
@@ -36,6 +40,10 @@ public:
//! \~russian Создает пустой %PIPropertyStorage //! \~russian Создает пустой %PIPropertyStorage
PIPropertyStorage() {} PIPropertyStorage() {}
//! \ingroup Core
//! \~\brief
//! \~english PIPropertyStorage element.
//! \~russian Элемент PIPropertyStorage.
struct PIP_EXPORT Property { struct PIP_EXPORT Property {
//! \~english Contructs %PIPropertyStorage::Property with name "n", comment "c", value "v" and flags "f" //! \~english Contructs %PIPropertyStorage::Property with name "n", comment "c", value "v" and flags "f"
@@ -257,8 +265,6 @@ public:
//! \~russian Возвращает свойство с именем "name" как константу //! \~russian Возвращает свойство с именем "name" как константу
const Property operator[](const PIString & name) const; const Property operator[](const PIString & name) const;
static Property parsePropertyLine(PIString l);
protected: protected:
PIVector<Property> props; PIVector<Property> props;

View File

@@ -27,21 +27,11 @@
#ifdef WINDOWS #ifdef WINDOWS
# include <stringapiset.h> # include <stringapiset.h>
#endif #endif
#include <wchar.h> #include <string>
#ifdef ANDROID #include <locale>
# if __ANDROID_API__ < 21 #include <codecvt>
# define wctomb(s, wc) wcrtomb(s, wc, NULL)
# define mbtowc(pwc, s, n) mbrtowc(pwc, s, n, NULL)
# endif
#endif
//! \addtogroup Core
//! \{
//! \class PIString pistring.h //! \class PIString pistring.h
//! \brief
//! \~english String class
//! \~russian Класс строки
//!
//! \~\details //! \~\details
//! \~english \section PIString_sec0 Synopsis //! \~english \section PIString_sec0 Synopsis
//! \~russian \section PIString_sec0 Краткий обзор //! \~russian \section PIString_sec0 Краткий обзор
@@ -58,7 +48,6 @@
//! создана из множества типов и преобразована в несколько типов. //! создана из множества типов и преобразована в несколько типов.
//! Имеет множество методов для манипуляций. //! Имеет множество методов для манипуляций.
//! //!
//! \}
@@ -67,7 +56,7 @@ const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^'}; 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^'};
const int PIString::fromBaseN[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, const char PIString::fromBaseN[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
@@ -89,11 +78,7 @@ const float PIString::ElideCenter = .5f;
const float PIString::ElideRight = 1.f; const float PIString::ElideRight = 1.f;
#ifndef CC_VC #define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); snprintf(ch, 256, f, v); return PIStringAscii(ch);
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf(ch, f, v); return PIString(ch);
#else
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf_s(ch, 256, f, v); return PIString(ch);
#endif
PIString PIString::itos(const int num) {pisprintf("%d", num);} PIString PIString::itos(const int num) {pisprintf("%d", num);}
PIString PIString::ltos(const long num) {pisprintf("%ld", num);} PIString PIString::ltos(const long num) {pisprintf("%ld", num);}
@@ -101,16 +86,10 @@ PIString PIString::lltos(const llong num) {pisprintf("%lld", num);}
PIString PIString::uitos(const uint num) {pisprintf("%u", num);} PIString PIString::uitos(const uint num) {pisprintf("%u", num);}
PIString PIString::ultos(const ulong num) {pisprintf("%lu", num);} PIString PIString::ultos(const ulong num) {pisprintf("%lu", num);}
PIString PIString::ulltos(const ullong num) {pisprintf("%llu", num);} PIString PIString::ulltos(const ullong num) {pisprintf("%llu", num);}
PIString PIString::ftos(const float num, char format, int precision) {
char f[8] = "%.";
int wr = sprintf(&(f[2]), "%d", precision);
f[2 + wr] = format;
f[3 + wr] = 0;
pisprintf(f, num);
}
PIString PIString::dtos(const double num, char format, int precision) { PIString PIString::dtos(const double num, char format, int precision) {
char f[8] = "%."; char f[8] = "%.";
int wr = sprintf(&(f[2]), "%d", precision); int wr = snprintf(&(f[2]), 4, "%d", precision);
if (wr > 4) wr = 4;
f[2 + wr] = format; f[2 + wr] = format;
f[3 + wr] = 0; f[3 + wr] = 0;
pisprintf(f, num); pisprintf(f, num);
@@ -121,7 +100,7 @@ PIString PIString::dtos(const double num, char format, int precision) {
PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) { PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) {
if (value == 0LL) return PIString('0'); if (value == 0LL) return PIString('0');
if (base < 2 || base > 40) { if ((base < 2) || (base > 40)) {
if (ok != 0) *ok = false; if (ok != 0) *ok = false;
return PIString(); return PIString();
} }
@@ -143,7 +122,7 @@ PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) {
PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) { PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) {
if (value == 0ULL) return PIString('0'); if (value == 0ULL) return PIString('0');
if (base < 2 || base > 40) { if ((base < 2) || (base > 40)) {
if (ok != 0) *ok = false; if (ok != 0) *ok = false;
return PIString(); return PIString();
} }
@@ -174,7 +153,7 @@ llong PIString::toNumberBase(const PIString & value, int base, bool * ok) {
} else { } else {
base = 10; base = 10;
} }
} else if (base < 2 || base > 40) { } else if ((base < 2) || (base > 40)) {
if (ok != 0) *ok = false; if (ok != 0) *ok = false;
return 0; return 0;
} }
@@ -182,7 +161,7 @@ llong PIString::toNumberBase(const PIString & value, int base, bool * ok) {
PIVector<int> digits; PIVector<int> digits;
llong ret = 0, m = 1; llong ret = 0, m = 1;
bool neg = false; bool neg = false;
int cs; char cs;
for (int i = 0; i < v.size_s(); ++i) { for (int i = 0; i < v.size_s(); ++i) {
if (v[i] == PIChar('-')) { if (v[i] == PIChar('-')) {
neg = !neg; neg = !neg;
@@ -205,116 +184,87 @@ llong PIString::toNumberBase(const PIString & value, int base, bool * ok) {
void PIString::appendFromChars(const char * c, int s, const char * codepage) { void PIString::appendFromChars(const char * c, int s, const char * codepage) {
if (s <= 0) return; // piCout << "appendFromChars";
int sz; if (s == 0) return;
int old_sz = size_s();
if (s == -1) s = strlen(c);
#ifdef PIP_ICU #ifdef PIP_ICU
UErrorCode e((UErrorCode)0); UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(codepage, &e); UConverter * cc = ucnv_open(codepage, &e);
if (cc) { if (cc) {
UChar * ucs = new UChar[s]; d.enlarge(s);
memset(ucs, 0, s * sizeof(UChar));
e = (UErrorCode)0; e = (UErrorCode)0;
sz = ucnv_toUChars(cc, ucs, s, c, s, &e); int sz = ucnv_toUChars(cc, (UChar*)(d.data(old_sz)), s, c, s, &e);
//printf("appendFromChars %d -> %d\n", s, sz); d.resize(old_sz+sz);
//printf("PIString %d -> %d\n", c[0], ucs[0]);
reserve(size_s() + sz);
for (int i = 0; i < sz; ++i) {
push_back(PIChar((ushort)ucs[i]));
}
delete[] ucs;
ucnv_close(cc); ucnv_close(cc);
return; return;
} }
#else #else
# ifdef WINDOWS # ifdef WINDOWS
sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0); int sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0);
if (sz <= 0) return; if (sz <= 0) return;
int old_sz = size_s(); d.enlarge(sz);
enlarge(sz); MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, (LPWSTR)d.data(old_sz), sz);
MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, (LPWSTR)PIDeque<PIChar>::data(old_sz), sz);
return;
//printf("request %d\n", sz);
# else # else
wchar_t wc; std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> ucs2conv;
mbtowc(0,0,0); // reset mbtowc std::u16string ucs2 = ucs2conv.from_bytes(c, c+s);
//qDebug() << "FromChars ..."; d.enlarge(ucs2.size());
while (s>0) { ucs2.copy((char16_t *)d.data(old_sz), ucs2.size());
//qDebug() << "0" << s;
sz = mbtowc(&wc, c, s);
//qDebug() << "1" << sz;
if (sz < 1) break;
push_back(PIChar(wc));
c += sz; s -= sz;
//qDebug() << "2" << c;
}
//qDebug() << "FromChars done" << size();
# endif # endif
#endif #endif
} }
PIString PIString::fromConsole(const char * s) { PIString PIString::fromConsole(const char * s) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret; PIString ret;
if (l > 0) ret.appendFromChars(s, l, __sysoemname__); if (!s) return ret;
if (s[0] != '\0') ret.appendFromChars(s, -1, __sysoemname__);
return ret; return ret;
} }
PIString PIString::fromSystem(const char * s) { PIString PIString::fromSystem(const char * s) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret; PIString ret;
if (l > 0) ret.appendFromChars(s, l, __syslocname__); if (!s) return ret;
if (s[0] != '\0') ret.appendFromChars(s, -1, __syslocname__);
return ret; return ret;
} }
PIString PIString::fromUTF8(const char * s) { PIString PIString::fromUTF8(const char * s) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret; PIString ret;
if (l > 0) ret.appendFromChars(s, l, __utf8name__); if (!s) return ret;
if (s[0] != '\0') ret.appendFromChars(s, -1, __utf8name__);
return ret; return ret;
} }
PIString PIString::fromUTF8(const PIByteArray & ba) { PIString PIString::fromUTF8(const PIByteArray & ba) {
PIString ret; PIString ret;
if (ba.isEmpty()) return ret; if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __utf8name__);
ret.appendFromChars((const char*)ba.data(), ba.size(), __utf8name__);
return ret; return ret;
} }
PIString PIString::fromAscii(const char * s) { PIString PIString::fromAscii(const char * s) {
PIString ret; return fromAscii(s, strlen(s));
int l = 0;
while (s[l] != '\0') {
ret.push_back(PIChar(s[l]));
++l;
}
return ret;
} }
PIString PIString::fromAscii(const char * s, int len) { PIString PIString::fromAscii(const char * s, int len) {
PIString ret; PIString ret;
ret.reserve(len); ret.resize(len);
for (int l = 0; l < len; ++l) { for (int l = 0; l < len; ++l) {
ret.push_back(PIChar(s[l])); ret[l] = s[l];
} }
return ret; return ret;
} }
PIString PIString::fromCodepage(const char * s, const char * c) { PIString PIString::fromCodepage(const char * s, const char * c) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret; PIString ret;
if (l > 0) ret.appendFromChars(s, l if (s[0] > '\0') ret.appendFromChars(s, -1
#ifdef PIP_ICU #ifdef PIP_ICU
, c , c
#else #else
@@ -348,72 +298,56 @@ PIString PIString::readableSize(llong bytes) {
void PIString::buildData(const char * cp) const { void PIString::buildData(const char * cp) const {
data_.clear(); deleteData();
int sz = 0;
#ifdef PIP_ICU #ifdef PIP_ICU
UErrorCode e((UErrorCode)0); UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(cp, &e); UConverter * cc = ucnv_open(cp, &e);
if (cc) { if (cc) {
char uc[8]; const size_t len = MB_CUR_MAX*size()+1;
data_.reserve(size_s()); data_ = (char *)malloc(len);
for (int i = 0; i < size_s(); ++i) { int sz = ucnv_fromUChars(cc, data_, len, (const UChar*)(d.data()), d.size_s(), &e);
if (at(i).isAscii()) {
data_.push_back(uchar(at(i).unicode16Code()));
} else {
e = (UErrorCode)0;
sz = ucnv_fromUChars(cc, uc, 8, (const UChar*)(PIDeque<PIChar>::data(i)), 1, &e);
for (int j = 0; j < sz; ++j) {
data_.push_back(uc[j]);
}
}
}
ucnv_close(cc); ucnv_close(cc);
data_.push_back('\0'); data_[sz] = '\0';
return; return;
} }
#else #else
# ifdef WINDOWS # ifdef WINDOWS
sz = WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque<PIChar>::data(), PIDeque<PIChar>::size_s(), 0, 0, NULL, NULL); int sz = WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)d.data(), d.size_s(), 0, 0, NULL, NULL);
//printf("WideCharToMultiByte %d %d\n", (uint)(uintptr_t)cp, sz);
if (sz <= 0) { if (sz <= 0) {
//printf("WideCharToMultiByte erro %d\n", GetLastError()); data_ = (char *)malloc(1);
data_.push_back(uchar('\0')); data_[0] = '\0';
return; return;
} }
data_.resize(sz); data_ = (char *)malloc(sz+1);
WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque<PIChar>::data(), PIDeque<PIChar>::size_s(), (LPSTR)data_.data(), data_.size_s(), NULL, NULL); WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)d.data(), d.size_s(), (LPSTR)data_, sz, NULL, NULL);
data_.push_back(uchar('\0')); data_[sz] = '\0';
return; return;
# else # else
wchar_t wc; std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> ucs2conv;
char tc[8]; std::string u8str = ucs2conv.to_bytes((char16_t*)d.data(), (char16_t*)d.data() + d.size());
wctomb(0, 0); data_ = (char *)malloc(u8str.size()+1);
for (int i = 0; i < size_s(); ++i) { strcpy(data_, u8str.c_str());
if (at(i).isAscii()) {
data_.push_back(uchar(at(i).toAscii()));
continue;
}
wc = at(i).toWChar();
sz = wctomb(tc, wc);
for (int b = 0; b < sz; ++b) {
data_.push_back(uchar(tc[b]));
}
}
data_.push_back(uchar('\0'));
# endif # endif
#endif #endif
} }
void PIString::deleteData() const {
if (!data_) return;
free(data_);
data_ = nullptr;
}
void PIString::trimsubstr(int &st, int &fn) const { void PIString::trimsubstr(int &st, int &fn) const {
for (int i = 0; i < length(); ++i) { for (int i = 0; i < d.size_s(); ++i) {
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) { if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) {
st = i; st = i;
break; break;
} }
} }
if (st < 0) return; if (st < 0) return;
for (int i = length() - 1; i >= 0; --i) { for (int i = d.size_s() - 1; i >= 0; --i) {
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) { if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) {
fn = i; fn = i;
break; break;
@@ -423,19 +357,19 @@ void PIString::trimsubstr(int &st, int &fn) const {
uint PIString::hash() const { uint PIString::hash() const {
return piHashData((const uchar*)PIDeque<PIChar>::data(), size() * sizeof(PIChar)); return piHashData((const uchar*)d.data(), d.size() * sizeof(PIChar));
} }
PIByteArray PIString::toUTF8() const { PIByteArray PIString::toUTF8() const {
if (isEmpty()) return data_.resized(0); if (isEmpty()) return PIByteArray();
buildData(__utf8name__); buildData(__utf8name__);
return data_.resized(data_.size_s() - 1); return PIByteArray(data_, strlen(data_));
} }
PIByteArray PIString::toCharset(const char * c) const { PIByteArray PIString::toCharset(const char * c) const {
if (isEmpty()) return data_.resized(0); if (isEmpty()) return PIByteArray();
buildData( buildData(
#ifdef PIP_ICU #ifdef PIP_ICU
c c
@@ -445,63 +379,67 @@ PIByteArray PIString::toCharset(const char * c) const {
# endif # endif
#endif #endif
); );
return data_.resized(data_.size_s() - 1); return PIByteArray(data_, strlen(data_));
} }
PIString & PIString::operator +=(const char * str) { PIString & PIString::operator +=(const char * str) {
if (!str) return *this; if (!str) return *this;
int l = 0; appendFromChars(str, -1, __syslocname__);
while (str[l] != '\0') ++l;
appendFromChars(str, l, __syslocname__);
return *this; return *this;
} }
PIString::~PIString() {
deleteData();
}
PIString & PIString::operator +=(const wchar_t * str) { PIString & PIString::operator +=(const wchar_t * str) {
if (!str) return *this; if (!str) return *this;
int i = -1; int i = -1;
while (str[++i]) { while (str[++i]) {
push_back(PIChar(str[i])); d.push_back(PIChar(str[i]));
} }
return *this; return *this;
} }
PIString & PIString::operator +=(const PIString & str) { PIString & PIString::operator +=(const PIString & str) {
PIDeque<PIChar>::append(*(const PIDeque<PIChar>*)&str); d.append(str.d);
return *this;
}
PIString & PIString::operator +=(const PIConstChars & str) {
if (!str.isEmpty()) {
size_t os = d.size();
d.enlarge(str.size());
for (size_t l = 0; l < d.size(); ++l) {
d[os + l] = str[l];
}
}
return *this; return *this;
} }
bool PIString::operator ==(const PIString & str) const { bool PIString::operator ==(const PIString & str) const {
uint l = str.size(); return d == str.d;
if (size() != l) return false;
for (uint i = 0; i < l; ++i) {
if (str[i] != at(i)) return false;
}
return true;
} }
bool PIString::operator !=(const PIString & str) const { bool PIString::operator !=(const PIString & str) const {
uint l = str.size(); return d != str.d;
if (size() != l) return true;
for (uint i = 0; i < l; ++i) {
if (str[i] != at(i)) return true;
}
return false;
} }
bool PIString::operator <(const PIString & str) const { bool PIString::operator <(const PIString & str) const {
uint l = str.size(); size_t l = str.size();
if (size() < l) return true; if (size() < l) return true;
if (size() > l) return false; if (size() > l) return false;
for (uint i = 0; i < l; ++i) { for (size_t i = 0; i < l; ++i) {
if (at(i) == str[i]) continue; if (at(i) == str.at(i)) continue;
if (at(i) < str[i]) return true; if (at(i) < str.at(i)) return true;
else return false; else return false;
} }
return false; return false;
@@ -509,12 +447,12 @@ bool PIString::operator <(const PIString & str) const {
bool PIString::operator >(const PIString & str) const { bool PIString::operator >(const PIString & str) const {
uint l = str.size(); size_t l = str.size();
if (size() < l) return false; if (size() < l) return false;
if (size() > l) return true; if (size() > l) return true;
for (uint i = 0; i < l; ++i) { for (size_t i = 0; i < l; ++i) {
if (at(i) == str[i]) continue; if (at(i) == str.at(i)) continue;
if (at(i) < str[i]) return false; if (at(i) < str.at(i)) return false;
else return true; else return true;
} }
return false; return false;
@@ -545,10 +483,10 @@ PIString PIString::mid(const int start, const int len) const {
s = 0; s = 0;
} }
if (l < 0) { if (l < 0) {
return PIString(&(at(s)), size_s() - s); return PIString(d.data(s), size_s() - s);
} else { } else {
if (l > length() - s) l = length() - s; if (l > length() - s) l = length() - s;
return PIString(&(at(s)), l); return PIString(d.data(s), l);
} }
return PIString(); return PIString();
} }
@@ -573,10 +511,10 @@ PIString & PIString::cutMid(const int start, const int len) {
s = 0; s = 0;
} }
if (l < 0) { if (l < 0) {
remove(s, size() - s); d.remove(s, size() - s);
} else { } else {
if (l > length() - s) l = length() - s; if (l > length() - s) l = length() - s;
remove(s, l); d.remove(s, l);
} }
return *this; return *this;
} }
@@ -625,10 +563,10 @@ PIString PIString::trimmed() const {
PIString & PIString::replace(int from, int count, const PIString & with) { PIString & PIString::replace(int from, int count, const PIString & with) {
count = piMini(count, length() - from); count = piMini(count, length() - from);
if (count == with.size_s()) { if (count == with.size_s()) {
memcpy(PIDeque<PIChar>::data(from), static_cast<PIDeque<PIChar>>(with).data(), count * sizeof(PIChar)); memcpy(d.data(from), with.d.data(), count * sizeof(PIChar));
} else { } else {
remove(from, count); d.remove(from, count);
PIDeque<PIChar>::insert(from, with); d.insert(from, with.d);
} }
return *this; return *this;
} }
@@ -680,9 +618,9 @@ PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
} }
} }
if (!match) continue; if (!match) continue;
if (dl > 0) PIDeque<PIChar>::insert(i, PIDeque<PIChar>((size_t)dl)); if (dl > 0) d.insert(i, PIDeque<PIChar>((size_t)dl));
if (dl < 0) PIDeque<PIChar>::remove(i, -dl); if (dl < 0) d.remove(i, -dl);
memcpy(PIDeque<PIChar>::data(i), &(with.at(0)), with.length() * sizeof(PIChar)); memcpy(d.data(i), with.d.data(), with.size() * sizeof(PIChar));
} }
} }
return *this; return *this;
@@ -708,8 +646,8 @@ PIString & PIString::replaceAll(const PIString & what, const char with) {
} }
} }
if (!match) continue; if (!match) continue;
if (dl > 0) PIDeque<PIChar>::remove(i, dl); if (dl > 0) d.remove(i, dl);
(*this)[i] = PIChar(with); d[i] = PIChar(with);
} }
return *this; return *this;
} }
@@ -725,7 +663,7 @@ PIString & PIString::replaceAll(const PIString & what, const char with) {
PIString & PIString::replaceAll(const char what, const char with) { PIString & PIString::replaceAll(const char what, const char with) {
int l = length(); int l = length();
for (int i = 0; i < l; ++i) { for (int i = 0; i < l; ++i) {
if (at(i) == what) (*this)[i] = with; if (at(i) == what) d[i] = with;
} }
return *this; return *this;
} }
@@ -737,13 +675,13 @@ PIString & PIString::removeAll(const PIString & str) {
for (int i = 0; i < length() - l + 1; ++i) { for (int i = 0; i < length() - l + 1; ++i) {
bool match = true; bool match = true;
for (int j = 0; j < l; ++j) { for (int j = 0; j < l; ++j) {
if (at(j + i) != str[j]) { if (d.at(j + i) != str.at(j)) {
match = false; match = false;
break; break;
} }
} }
if (!match) continue; if (!match) continue;
PIDeque<PIChar>::remove(i, l); d.remove(i, l);
i -= l; i -= l;
} }
return *this; return *this;
@@ -751,7 +689,7 @@ PIString & PIString::removeAll(const PIString & str) {
PIString & PIString::insert(int index, const PIString & str) { PIString & PIString::insert(int index, const PIString & str) {
PIDeque<PIChar>::insert(index, *((const PIDeque<PIChar>*)&str)); d.insert(index, str.d);
return *this; return *this;
} }
@@ -766,8 +704,8 @@ PIString & PIString::elide(int size, float pos) {
pos = piClampf(pos, 0.f, 1.f); pos = piClampf(pos, 0.f, 1.f);
int ns = size - 2; int ns = size - 2;
int ls = piRoundf(ns * pos); int ls = piRoundf(ns * pos);
remove(ls, length() - ns); d.remove(ls, length() - ns);
insert(ls, s_dotdot); d.insert(ls, s_dotdot.d);
return *this; return *this;
} }
@@ -853,6 +791,14 @@ int PIString::findLast(const char c, const int start) const {
return -1; return -1;
} }
int PIString::findLast(PIChar c, const int start) const
{
for (int i = length() - 1; i >= start; --i) {
if (at(i) == c) return i;
}
return -1;
}
//! \~\details //! \~\details
//! \~\code //! \~\code
@@ -902,14 +848,14 @@ int PIString::findWord(const PIString & word, const int start) const {
bool ok = true; bool ok = true;
PIChar c; PIChar c;
if (f > 0) { if (f > 0) {
c = (*this)[f - 1]; c = at(f - 1);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) { if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
ok = false; ok = false;
continue; continue;
} }
} }
if (f + wl < tl) { if (f + wl < tl) {
c = (*this)[f + wl]; c = at(f + wl);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) { if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
ok = false; ok = false;
continue; continue;
@@ -936,14 +882,14 @@ int PIString::findCWord(const PIString & word, const int start) const {
bool ok = true; bool ok = true;
PIChar c; PIChar c;
if (f > 0) { if (f > 0) {
c = (*this)[f - 1]; c = at(f - 1);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) { if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {
ok = false; ok = false;
continue; continue;
} }
} }
if (f + wl < tl) { if (f + wl < tl) {
c = (*this)[f + wl]; c = at(f + wl);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) { if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {
ok = false; ok = false;
continue; continue;
@@ -1356,93 +1302,80 @@ PIString PIString::inBrackets(const PIChar start, const PIChar end) const {
} }
//! \~\details
//! \~english It`s equivalent length of char sequence returned by function \a data() - 1, without terminating null-char
//! \~russian Эквивалентно длине данных, возвращаемых \a data() - 1, без завершающего нулевого байта
//! \~\code
//! piCout << PIString("0123456789").lengthAscii(); // 10
//! piCout << PIString("№1").lengthAscii(); // 3
//! \endcode
//! \~\sa \a data()
int PIString::lengthAscii() const {
buildData(__syslocname__);
return data_.size_s() - 1;
}
//! \~\details //! \~\details
//! \~english //! \~english
//! This function fill internal buffer by sequence //! This function fill internal buffer by sequence of chars.
//! of chars. Minimum length of this buffer is count //! Length of this buffer is count of symbols + end byte '\0'.
//! of symbols. Returned pointer is valid until next //! Returned pointer is valid until next execution of this function.
//! execution of this function
//! \~russian //! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Минимальный размер //! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки. Возвращаемый указатель //! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! действителен до следующего вызова этого метода //! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\code //! \~\code
//! piCout << PIString("0123456789").data(); // 0123456789 //! piCout << PIString("0123456789").data(); // 0123456789
//! piCout << PIString("№1").data(); // №1 //! piCout << PIString("№1").data(); // №1
//! \endcode //! \endcode
//! \~\sa \a dataConsole(), \a dataUTF8() //! \~\sa \a dataConsole(), \a dataUTF8()
const char * PIString::data() const { const char * PIString::data() const {
if (isEmpty()) return "";
buildData(__syslocname__); buildData(__syslocname__);
return (const char *)(data_.data()); return data_;
} }
//! \~\details //! \~\details
//! \~english //! \~english
//! This function fill internal buffer by sequence //! This function fill internal buffer by sequence of chars.
//! of chars. Minimum length of this buffer is count //! Length of this buffer is count of symbols + end byte '\0'.
//! of symbols. Returned pointer is valid until next //! Returned pointer is valid until next execution of this function.
//! execution of this function
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Минимальный размер
//! этого буфера равен количеству символов строки. Возвращаемый указатель
//! действителен до следующего вызова этого метода
//! \~\sa \a data(), \a dataUTF8()
const char * PIString::dataConsole() const {
buildData(__sysoemname__ );
return (const char *)(data_.data());
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence
//! of chars. Minimum length of this buffer is count
//! of symbols. Returned pointer is valid until next
//! execution of this function
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Минимальный размер
//! этого буфера равен количеству символов строки. Возвращаемый указатель
//! действителен до следующего вызова этого метода
//! \~\sa \a data(), \a dataConsole()
const char * PIString::dataUTF8() const {
buildData(__utf8name__);
return (const char *)(data_.data());
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence
//! of chars. Length of this buffer is count
//! of symbols. Returned pointer is valid until next
//! execution of this function
//! \~russian //! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Размер //! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки. Возвращаемый указатель //! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! действителен до следующего вызова этого метода //! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\sa \a data(), \a dataUTF8()
const char * PIString::dataConsole() const {
if (isEmpty()) return "";
buildData(__sysoemname__ );
return data_;
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence of chars.
//! Length of this buffer is count of symbols + end byte '\0'.
//! Returned pointer is valid until next execution of this function.
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\sa \a data(), \a dataConsole()
const char * PIString::dataUTF8() const {
if (isEmpty()) return "";
buildData(__utf8name__);
return data_;
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence of chars.
//! Length of this buffer is count of symbols + end byte '\0'.
//! Returned pointer is valid until next execution of this function.
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\sa \a dataConsole(), \a dataUTF8() //! \~\sa \a dataConsole(), \a dataUTF8()
const char * PIString::dataAscii() const { const char * PIString::dataAscii() const {
data_.clear(); if (isEmpty()) return "";
deleteData();
data_ = (char*)malloc(size()+1);
for (int i = 0; i < size_s(); ++i) { for (int i = 0; i < size_s(); ++i) {
data_.push_back(uchar(at(i).ch)); data_[i] = uchar(at(i).ch);
} }
data_.push_back(uchar('\0')); data_[size()] = '\0';
return (const char *)data_.data(); return data_;
} }
@@ -1450,7 +1383,7 @@ PIString PIString::toUpperCase() const {
PIString str(*this); PIString str(*this);
int l = str.size(); int l = str.size();
for (int i = 0; i < l; ++i) { for (int i = 0; i < l; ++i) {
str[i] = str[i].toUpper(); str.d[i] = str.d[i].toUpper();
} }
return str; return str;
} }
@@ -1460,7 +1393,7 @@ PIString PIString::toLowerCase() const {
PIString str(*this); PIString str(*this);
int l = str.size(); int l = str.size();
for (int i = 0; i < l; ++i) { for (int i = 0; i < l; ++i) {
str[i] = str[i].toLower(); str.d[i] = str.d[i].toLower();
} }
return str; return str;
} }
@@ -1729,7 +1662,7 @@ PIString versionNormalize(const PIString & v) {
PICout operator <<(PICout s, const PIString & v) { PICout operator <<(PICout s, const PIString & v) {
s.space(); s.space();
s.quote(); s.quote();
s.writePIString(v); s.write(v);
s.quote(); s.quote();
return s; return s;
} }

View File

@@ -27,56 +27,75 @@
#define PISTRING_H #define PISTRING_H
#include "pibytearray.h" #include "pibytearray.h"
#include "piconstchars.h"
#define PIStringAscii PIString::fromAscii #define PIStringAscii PIString::fromAscii
class PIStringList; class PIStringList;
class PIP_EXPORT PIString: public PIDeque<PIChar> //! \ingroup Core
//! \~\brief
//! \~english String class.
//! \~russian Класс строки.
class PIP_EXPORT PIString
{ {
friend PIByteArray & operator >>(PIByteArray & s, PIString & v); friend PIByteArray & operator >>(PIByteArray & s, PIString & v);
friend PIByteArray & operator <<(PIByteArray & s, const PIString & v);
public: public:
//! \~english Contructs an empty string typedef PIDeque<PIChar>::iterator iterator;
//! \~russian Создает пустую строку typedef PIDeque<PIChar>::const_iterator const_iterator;
PIString(): PIDeque<PIChar>() {} typedef PIDeque<PIChar>::reverse_iterator reverse_iterator;
typedef PIDeque<PIChar>::const_reverse_iterator const_reverse_iterator;
typedef PIChar value_type;
typedef PIChar* pointer;
typedef const PIChar* const_pointer;
typedef PIChar& reference;
typedef const PIChar& const_reference;
typedef size_t size_type;
//! \~english Value for elide at left //! \~english Contructs an empty string.
//! \~russian Значение для пропуска слева //! \~russian Создает пустую строку.
PIString() {}
//! \~english Value for elide at left.
//! \~russian Значение для пропуска слева.
static const float ElideLeft ; static const float ElideLeft ;
//! \~english Value for elide at center //! \~english Value for elide at center.
//! \~russian Значение для пропуска в середине //! \~russian Значение для пропуска в середине.
static const float ElideCenter; static const float ElideCenter;
//! \~english Value for elide at right //! \~english Value for elide at right.
//! \~russian Значение для пропуска справа //! \~russian Значение для пропуска справа.
static const float ElideRight ; static const float ElideRight ;
PIString & operator +=(const PIChar c) {push_back(c); return *this;} PIString & operator +=(const PIChar & c) {d.push_back(c); return *this;}
PIString & operator +=(const char c) {push_back(PIChar(c)); return *this;} PIString & operator +=(const char c) {d.push_back(PIChar(c)); return *this;}
PIString & operator +=(const char * str); PIString & operator +=(const char * str);
PIString & operator +=(const wchar_t * str); PIString & operator +=(const wchar_t * str);
PIString & operator +=(const PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s(), __utf8name__); return *this;} PIString & operator +=(const PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s(), __utf8name__); return *this;}
PIString & operator +=(const PIString & str); PIString & operator +=(const PIString & str);
PIString & operator +=(const PIConstChars & str);
//! \~english Contructs a copy of string //! \~english Contructs a copy of string.
//! \~russian Создает копию строки //! \~russian Создает копию строки.
PIString(const PIString & o): PIDeque<PIChar>(o) {} PIString(const PIString & o) {d = o.d;}
PIString(PIString && o): PIDeque<PIChar>(std::move(o)) {} //! \~english Move constructor.
//! \~russian Перемещающий конструктор.
PIString(PIString && o): d(std::move(o.d)) {piSwap(data_, o.data_);}
//! \~english Contructs string with single character "c".
//! \~russian Создает строку из одного символа "c".
PIString(const PIChar c) {*this += c;}
//! \~english Contructs string with single symbol "c" //! \~english Contructs string with single character "c".
//! \~russian Создает строку из одного символа "c" //! \~russian Создает строку из одного символа "c".
PIString(const PIChar c): PIDeque<PIChar>() {*this += c;} PIString(const char c) {*this += PIChar(c);}
//! \~english Contructs string with single symbol "c" //! \~english Contructs string from C-string "str" (system codepage).
//! \~russian Создает строку из одного символа "c" //! \~russian Создает строку из C-строки "str" (кодировка системы).
PIString(const char c): PIDeque<PIChar>() {*this += PIChar(c);}
//! \~english Contructs string from C-string "str" (system codepage)
//! \~russian Создает строку из C-строки "str" (кодировка системы)
//! \~\details //! \~\details
//! \~english //! \~english
//! "str" should be null-terminated\n //! "str" should be null-terminated\n
@@ -85,10 +104,10 @@ public:
//! \~\code //! \~\code
//! PIString s("string"); //! PIString s("string");
//! \endcode //! \endcode
PIString(const char * str): PIDeque<PIChar>() {*this += str;} PIString(const char * str) {*this += str;}
//! \~english Contructs string from \c wchar_t C-string "str" //! \~english Contructs string from \c wchar_t C-string "str".
//! \~russian Создает строку из \c wchar_t C-строки "str" //! \~russian Создает строку из \c wchar_t C-строки "str".
//! \~\details //! \~\details
//! \~english //! \~english
//! "str" should be null-terminated //! "str" should be null-terminated
@@ -97,123 +116,134 @@ public:
//! \~\code //! \~\code
//! PIString s(L"string"); //! PIString s(L"string");
//! \endcode //! \endcode
PIString(const wchar_t * str): PIDeque<PIChar>() {*this += str;} PIString(const wchar_t * str) {*this += str;}
//! \~english Contructs string from byte array "ba" (as UTF-8) //! \~english Contructs string from byte array "ba" (as UTF-8).
//! \~russian Создает строку из байтового массива "ba" (как UTF-8) //! \~russian Создает строку из байтового массива "ba" (как UTF-8).
PIString(const PIByteArray & ba): PIDeque<PIChar>() {*this += ba;} PIString(const PIByteArray & ba) {*this += ba;}
//! \~english Contructs string from "len" characters of buffer "str" //! \~english Contructs string from "len" characters of buffer "str".
//! \~russian Создает строку из "len" символов массива "str" //! \~russian Создает строку из "len" символов массива "str".
PIString(const PIChar * str, const int len): PIDeque<PIChar>(str, size_t(len)) {} PIString(const PIChar * str, const int len): d(str, size_t(len)) {}
//! \~english Contructs string from "len" characters of buffer "str" (system codepage) //! \~english Contructs string from "len" characters of buffer "str" (system codepage).
//! \~russian Создает строку из "len" символов массива "str" (кодировка системы) //! \~russian Создает строку из "len" символов массива "str" (кодировка системы).
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("string", 3); // s = "str" //! PIString s("string", 3); // s = "str"
//! \endcode //! \endcode
PIString(const char * str, const int len): PIDeque<PIChar>() {appendFromChars(str, len);} PIString(const char * str, const int len) {appendFromChars(str, len);}
//! \~english Contructs string as sequence of characters "c" of buffer with length "len" //! \~english Contructs string as sequence of characters "c" of buffer with length "len".
//! \~russian Создает строку как последовательность длиной "len" символа "c" //! \~russian Создает строку как последовательность длиной "len" символа "c".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s(5, 'p'); // s = "ppppp" //! PIString s(5, 'p'); // s = "ppppp"
//! \endcode //! \endcode
PIString(const int len, const char c): PIDeque<PIChar>() {for (int i = 0; i < len; ++i) push_back(c);} PIString(const int len, const char c) {for (int i = 0; i < len; ++i) d.push_back(PIChar(c));}
//! \~english Contructs string as sequence of symbols "c" of buffer with length "len" //! \~english Contructs string as sequence of characters "c" of buffer with length "len".
//! \~russian Создает строку как последовательность длиной "len" символа "c" //! \~russian Создает строку как последовательность длиной "len" символа "c".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s(5, "№"); // s = "№№№№№" //! PIString s(5, "№"); // s = "№№№№№"
//! \endcode //! \endcode
PIString(const int len, const PIChar c): PIDeque<PIChar>() {for (int i = 0; i < len; ++i) push_back(c);} PIString(const int len, const PIChar c) {for (int i = 0; i < len; ++i) d.push_back(c);}
~PIString() {} PIString(const PIConstChars & c) {*this += c;}
~PIString();
//! \~english Assign operator //! \~english Assign operator.
//! \~russian Оператор присваивания //! \~russian Оператор присваивания.
PIString & operator =(const PIString & o) {if (this == &o) return *this; clear(); *this += o; return *this;} PIString & operator =(const PIString & o) {if (this == &o) return *this; d = o.d; return *this;}
PIString & operator =(PIString && o) {swap(o); return *this;} //! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
PIString & operator =(PIString && o) {d.swap(o.d); piSwap(data_, o.data_); return *this;}
//! \~english Compare operator //! \~english Assign operator.
//! \~russian Оператор сравнения //! \~russian Оператор присваивания.
PIString & operator =(const PIConstChars & o) {d.clear(); *this += o; return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIString & operator =(const char * o) {d.clear(); *this += o; return *this;}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator ==(const PIString & str) const; bool operator ==(const PIString & str) const;
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator ==(const PIChar c) const {if (size_s() != 1) return false; return at(0) == c;} bool operator ==(const PIChar c) const {if (d.size() != 1) return false; return d.at(0) == c;}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator ==(const char * str) const {return *this == PIString(str);} bool operator ==(const char * str) const {return *this == PIString(str);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator !=(const PIString & str) const; bool operator !=(const PIString & str) const;
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator !=(const PIChar c) const {if (size_s() != 1) return true; return at(0) != c;} bool operator !=(const PIChar c) const {if (d.size() != 1) return true; return d.at(0) != c;}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator !=(const char * str) const {return *this != PIString(str);} bool operator !=(const char * str) const {return *this != PIString(str);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator <(const PIString & str) const; bool operator <(const PIString & str) const;
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator <(const PIChar c) const {if (size_s() != 1) return size_s() < 1; return at(0) < c;} bool operator <(const PIChar c) const {if (d.size() != 1) return d.size() < 1; return d.at(0) < c;}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator <(const char * str) const {return *this < PIString(str);} bool operator <(const char * str) const {return *this < PIString(str);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator >(const PIString & str) const; bool operator >(const PIString & str) const;
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator >(const PIChar c) const {if (size_s() != 1) return size_s() > 1; return at(0) > c;} bool operator >(const PIChar c) const {if (d.size() != 1) return d.size() > 1; return d.at(0) > c;}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator >(const char * str) const {return *this > PIString(str);} bool operator >(const char * str) const {return *this > PIString(str);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator <=(const PIString & str) const {return !(*this > str);} bool operator <=(const PIString & str) const {return !(*this > str);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator <=(const PIChar c) const {return !(*this > c);} bool operator <=(const PIChar c) const {return !(*this > c);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator <=(const char * str) const {return *this <= PIString(str);} bool operator <=(const char * str) const {return *this <= PIString(str);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator >=(const PIString & str) const {return !(*this < str);} bool operator >=(const PIString & str) const {return !(*this < str);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator >=(const PIChar c) const {return !(*this < c);} bool operator >=(const PIChar c) const {return !(*this < c);}
//! \~english Compare operator //! \~english Compare operator.
//! \~russian Оператор сравнения //! \~russian Оператор сравнения.
bool operator >=(const char * str) const {return *this >= PIString(str);} bool operator >=(const char * str) const {return *this >= PIString(str);}
//! \~english Append string "str" at the end of string //! \~english Append string "str" at the end of string.
//! \~russian Добавляет в конец строку "str" //! \~russian Добавляет в конец строку "str".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("this"), s1(" is"), s2(" string"); //! PIString s("this"), s1(" is"), s2(" string");
@@ -221,26 +251,26 @@ public:
//! \endcode //! \endcode
PIString & operator <<(const PIString & str) {*this += str; return *this;} PIString & operator <<(const PIString & str) {*this += str; return *this;}
//! \~english Append symbol "c" at the end of string //! \~english Append character "c" at the end of string.
//! \~russian Добавляет в конец символ "c" //! \~russian Добавляет в конец символ "c".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("stri"); //! PIString s("stri");
//! s << PIChar('n') << PIChar('g'); // s = "string" //! s << PIChar('n') << PIChar('g'); // s = "string"
//! \endcode //! \endcode
PIString & operator <<(const PIChar c) {*this += c; return *this;} PIString & operator <<(const PIChar c) {d.append(c); return *this;}
//! \~english Append symbol "c" at the end of string //! \~english Append character `c` at the end of string.
//! \~russian Добавляет в конец символ "c" //! \~russian Добавляет в конец символ `c`.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("stri"); //! PIString s("stri");
//! s << 'n' << 'g'; // s = "string" //! s << 'n' << 'g'; // s = "string"
//! \endcode //! \endcode
PIString & operator <<(const char c) {*this += PIChar(c); return *this;} PIString & operator <<(const char c) {d.append(PIChar(c)); return *this;}
//! \~english Append С-string "str" at the end of string //! \~english Append С-string "str" at the end of string.
//! \~russian Добавляет в конец C-строку "str" //! \~russian Добавляет в конец C-строку "str".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("this"); //! PIString s("this");
@@ -248,8 +278,8 @@ public:
//! \endcode //! \endcode
PIString & operator <<(const char * str) {*this += str; return *this;} PIString & operator <<(const char * str) {*this += str; return *this;}
//! \~english Append \c wchar_t C-string "str" at the end of string //! \~english Append \c wchar_t C-string "str" at the end of string.
//! \~russian Добавляет в конец \c wchar_t C-строку "str" //! \~russian Добавляет в конец \c wchar_t C-строку "str".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -257,8 +287,10 @@ public:
//! \endcode //! \endcode
PIString & operator <<(const wchar_t * str) {*this += str; return *this;} PIString & operator <<(const wchar_t * str) {*this += str; return *this;}
//! \~english Append string representation of "num" at the end of string PIString & operator <<(const PIConstChars & str) {*this += str; return *this;}
//! \~russian Добавляет в конец строковое представление "num"
//! \~english Append string representation of "num" at the end of string.
//! \~russian Добавляет в конец строковое представление "num".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("ten - "); //! PIString s("ten - ");
@@ -267,8 +299,8 @@ public:
PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;}
//! \~english Append string representation of "num" at the end of string //! \~english Append string representation of "num" at the end of string.
//! \~russian Добавляет в конец строковое представление "num" //! \~russian Добавляет в конец строковое представление "num".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("ten - "); //! PIString s("ten - ");
@@ -280,8 +312,8 @@ public:
PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;}
//! \~english Append string representation of "num" at the end of string //! \~english Append string representation of "num" at the end of string.
//! \~russian Добавляет в конец строковое представление "num" //! \~russian Добавляет в конец строковое представление "num".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("1/10 - "); //! PIString s("1/10 - ");
@@ -289,8 +321,8 @@ public:
//! \endcode //! \endcode
PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;}
//! \~english Append string representation of "num" at the end of string //! \~english Append string representation of "num" at the end of string.
//! \~russian Добавляет в конец строковое представление "num" //! \~russian Добавляет в конец строковое представление "num".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("1/10 - "); //! PIString s("1/10 - ");
@@ -298,26 +330,186 @@ public:
//! \endcode //! \endcode
PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;}
//! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент.
//! \~\details
//! \~\return \ref stl_iterators
//! \~\sa \a end(), \a rbegin(), \a rend()
inline iterator begin() {return d.begin();}
//! \~english Insert string "str" at the begin of string //! \~english Iterator to the element following the last element.
//! \~russian Вставляет "str" в начало строки //! \~russian Итератор на элемент, следующий за последним элементом.
PIString & prepend(const PIString & str) {insert(0, str); return *this;} //! \~\details
//! \~\return \ref stl_iterators
//! \~\sa \a begin(), \a rbegin(), \a rend()
inline iterator end() {return d.end();}
//! \~english Insert string "str" at the end of string inline const_iterator begin() const {return d.begin();}
//! \~russian Вставляет "str" в конец строки inline const_iterator end() const {return d.end();}
PIString & append(const PIString & str) {*this += str; return *this;}
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
//! \~\details
//! \~english It corresponds to the last element of the non-reversed array.
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на последний элемент.
//! \~\return \ref stl_iterators
//! \~\sa \a rend(), \a begin(), \a end()
inline reverse_iterator rbegin() {return d.rbegin();}
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент, следующий за последним элементом.
//! \~\details
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на элемент, предшествующий первому элементу.
//! \~\return \ref stl_iterators
//! \~\sa \a rbegin(), \a begin(), \a end()
inline reverse_iterator rend() {return d.rend();}
inline const_reverse_iterator rbegin() const {return d.rbegin();}
inline const_reverse_iterator rend() const {return d.rend();}
//! \~english Full access to character by `index`.
//! \~russian Полный доступ к символу по индексу `index`.
//! \~\details
//! \~english Сharacter index starts from `0`.
//! Сharacter index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс символа должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline PIChar & operator [](size_t index) {return d[index];}
inline PIChar operator [](size_t index) const {return d[index];}
//! \~english Read only access to character by `index`.
//! \~russian Доступ исключительно на чтение к символу по индексу `index`.
//! \~\details
//! \~english Сharacter index starts from `0`.
//! Сharacter index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс символа считается от `0`.
//! Индекс символа должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const PIChar at(size_t index) const {return d.at(index);}
//! \~english Returns the last character of the string.
//! \~russian Возвращает последний символ строки.
inline PIChar & back() {return d.back();}
inline PIChar back() const {return d.back();}
inline PIChar & front() {return d.front();}
inline PIChar front() const {return d.front();}
//! \~english Sets size of the string, new characters are copied from `c`.
//! \~russian Устанавливает размер строки, новые символы копируются из `c`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! characters are added to the end; the new characters are initialized from `c`.
//! If `new_size` is less than the current \a size(), characters are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер строки \a size(),
//! новые символы добавляются в конец строки и создаются из `с`.
//! Если `new_size` меньше чем текущий размер строки \a size(),
//! лишние символы удаляются с конца строки.
//! \~\sa \a size(), \a clear()
inline PIString & resize(size_t new_size, PIChar c = PIChar()) {d.resize(new_size, c); return *this;}
//! \~english Delete one character at the end of string.
//! \~russian Удаляет один символ с конца строки.
inline PIString & pop_back() {d.pop_back(); return *this;}
//! \~english Delete one character at the benig of string.
//! \~russian Удаляет один символ с начала строки.
inline PIString & pop_front() {d.pop_front(); return *this;}
//! \~english Removes `count` characters from the string, starting at `index` position.
//! \~russian Удаляет символы из строки, начиная с позиции `index` в количестве `count`.
inline PIString & remove(size_t index, size_t count = 1) {d.remove(index, count); return *this;}
//! \~english Assigns character 'c' to all string characters.
//! \~russian Заполняет всю строку символами `c`.
inline PIString & fill(PIChar c = PIChar()) {d.fill(c); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & prepend(const char * str) {insert(0, str); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & prepend(const PIString & str) {d.prepend(str.d); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & prepend(const PIChar c) {d.prepend(c); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & prepend(const char c) {d.prepend(PIChar(c)); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & push_front(const char * str) {insert(0, str); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & push_front(const PIString & str) {d.push_front(str.d); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & push_front(const PIChar c) {d.push_front(c); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & push_front(const char c) {d.push_front(PIChar(c)); return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & append(const char * str) {*this += str; return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & append(const PIString & str) {d.append(str.d); return *this;}
PIString & append(const PIConstChars & str) {*this += str; return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & append(const PIChar c) {d.append(c); return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & append(const char c) {d.append(PIChar(c)); return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & push_back(const char * str) {*this += str; return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & push_back(const PIString & str) {d.push_back(str.d); return *this;}
PIString & push_back(const PIConstChars & str) {*this += str; return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & push_back(const PIChar c) {d.push_back(c); return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & push_back(const char c) {d.push_back(PIChar(c)); return *this;}
//! \~english Returns part of string from symbol at index "start" and maximum length "len" //! \~english Returns part of string from character at index "start" and maximum length "len".
//! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len" //! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len".
PIString mid(const int start, const int len = -1) const; PIString mid(const int start, const int len = -1) const;
//! \~english Synonym of \a mid() //! \~english Synonym of \a mid().
//! \~russian Аналог \a mid() //! \~russian Аналог \a mid().
PIString subString(const int start, const int len = -1) const {return mid(start, len);} PIString subString(const int start, const int len = -1) const {return mid(start, len);}
//! \~english Returns part of string from start and maximum length "len" //! \~english Returns part of string from start and maximum length "len".
//! \~russian Возвращает подстроку от начала и максимальной длиной "len" //! \~russian Возвращает подстроку от начала и максимальной длиной "len".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -329,8 +521,8 @@ public:
//! \~\sa \a mid(), \a right() //! \~\sa \a mid(), \a right()
PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);} PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);}
//! \~english Returns part of string at end and maximum length "len" //! \~english Returns part of string at end and maximum length "len".
//! \~russian Возвращает подстроку максимальной длиной "len" и до конца //! \~russian Возвращает подстроку максимальной длиной "len" и до конца.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -342,12 +534,12 @@ public:
//! \~\sa \a mid(), \a left() //! \~\sa \a mid(), \a left()
PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);} PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);}
//! \~english Remove part of string from symbol as index "start" and maximum length "len" and return this string //! \~english Remove part of string from character as index "start" and maximum length "len" and return this string.
//! \~russian Удаляет часть строки от символа "start" и максимальной длины "len", возвращает эту строку //! \~russian Удаляет часть строки от символа "start" и максимальной длины "len", возвращает эту строку.
PIString & cutMid(const int start, const int len); PIString & cutMid(const int start, const int len);
//! \~english Remove part of string from start and maximum length "len" and return this string //! \~english Remove part of string from start and maximum length "len" and return this string.
//! \~russian Удаляет часть строки от начала и максимальной длины "len", возвращает эту строку //! \~russian Удаляет часть строки от начала и максимальной длины "len", возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -361,8 +553,8 @@ public:
//! \~\sa \a cutMid(), \a cutRight() //! \~\sa \a cutMid(), \a cutRight()
PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);} PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);}
//! \~english Remove part of string at end and maximum length "len" and return this string //! \~english Remove part of string at end and maximum length "len" and return this string.
//! \~russian Удаляет часть строки максимальной длины "len" от конца, возвращает эту строку //! \~russian Удаляет часть строки максимальной длины "len" от конца, возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -376,12 +568,12 @@ public:
//! \~\sa \a cutMid(), \a cutLeft() //! \~\sa \a cutMid(), \a cutLeft()
PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);} PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);}
//! \~english Remove spaces at the start and at the end of string and return this string //! \~english Remove spaces at the start and at the end of string and return this string.
//! \~russian Удаляет пробельные символы с начала и конца строки и возвращает эту строку //! \~russian Удаляет пробельные символы с начала и конца строки и возвращает эту строку.
PIString & trim(); PIString & trim();
//! \~english Returns copy of this string without spaces at the start and at the end //! \~english Returns copy of this string without spaces at the start and at the end.
//! \~russian Возвращает копию этой строки без пробельных символов с начала и конца //! \~russian Возвращает копию этой строки без пробельных символов с начала и конца.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s(" \t string \n"); //! PIString s(" \t string \n");
@@ -391,12 +583,12 @@ public:
//! \~\sa \a trim() //! \~\sa \a trim()
PIString trimmed() const; PIString trimmed() const;
//! \~english Replace part of string from index "from" and maximum length "len" with string "with" and return this string //! \~english Replace part of string from index "from" and maximum length "len" with string "with" and return this string.
//! \~russian Заменяет часть строки от символа "from" и максимальной длины "len" строкой "with", возвращает эту строку //! \~russian Заменяет часть строки от символа "from" и максимальной длины "len" строкой "with", возвращает эту строку.
PIString & replace(const int from, const int count, const PIString & with); PIString & replace(const int from, const int count, const PIString & with);
//! \~english Replace part copy of this string from index "from" and maximum length "len" with string "with" //! \~english Replace part copy of this string from index "from" and maximum length "len" with string "with".
//! \~russian Заменяет часть копии этой строки от символа "from" и максимальной длины "len" строкой "with" //! \~russian Заменяет часть копии этой строки от символа "from" и максимальной длины "len" строкой "with".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -406,15 +598,15 @@ public:
//! \~\sa \a replace(), \a replaceAll() //! \~\sa \a replace(), \a replaceAll()
PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;} PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;}
//! \~english Replace first founded substring "what" with string "with" and return this string //! \~english Replace first founded substring "what" with string "with" and return this string.
//! \~russian Заменяет первую найденную подстроку "what" строкой "with", возвращает эту строку //! \~russian Заменяет первую найденную подстроку "what" строкой "with", возвращает эту строку.
PIString & replace(const PIString & what, const PIString & with, bool * ok = 0); PIString & replace(const PIString & what, const PIString & with, bool * ok = 0);
//! \~english Replace in string copy first founded substring "what" with string "with" //! \~english Replace in string copy first founded substring "what" with string "with".
//! \~russian Заменяет в копии строки первую найденную подстроку "what" строкой "with" //! \~russian Заменяет в копии строки первую найденную подстроку "what" строкой "with".
//! \~\details //! \~\details
//! \~english If "ok" is not null, it set to "true" if something was replaced //! \~english If "ok" is not null, it set to "true" if something was replaced.
//! \~russian Если "ok" не null, то устанавливает в "true" если замена произведена //! \~russian Если "ok" не null, то устанавливает в "true" если замена произведена.
//! \~\code //! \~\code
//! PIString s("pip string"); //! PIString s("pip string");
//! bool ok; //! bool ok;
@@ -424,43 +616,43 @@ public:
//! \~\sa \a replaced(), \a replaceAll() //! \~\sa \a replaced(), \a replaceAll()
PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;} PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;}
//! \~english Replace all founded substrings "what" with strings "with" and return this string //! \~english Replace all founded substrings "what" with strings "with" and return this string.
//! \~russian Заменяет все найденные подстроки "what" строками "with", возвращает эту строку //! \~russian Заменяет все найденные подстроки "what" строками "with", возвращает эту строку.
PIString & replaceAll(const PIString & what, const PIString & with); PIString & replaceAll(const PIString & what, const PIString & with);
//! \~english Replace all founded substrings "what" with symbols "with" and return this string //! \~english Replace all founded substrings "what" with characters "with" and return this string.
//! \~russian Заменяет все найденные подстроки "what" символами "with", возвращает эту строку //! \~russian Заменяет все найденные подстроки "what" символами "with", возвращает эту строку.
PIString & replaceAll(const PIString & what, const char with); PIString & replaceAll(const PIString & what, const char with);
//! \~english Replace all founded symbols "what" with symbols "with" and return this string //! \~english Replace all founded characters "what" with characters "with" and return this string.
//! \~russian Заменяет все найденные символы "what" символами "with", возвращает эту строку //! \~russian Заменяет все найденные символы "what" символами "with", возвращает эту строку.
PIString & replaceAll(const char what, const char with); PIString & replaceAll(const char what, const char with);
//! \~english Replace all founded substrings "what" with strings "with" in string copy //! \~english Replace all founded substrings "what" with strings "with" in string copy.
//! \~russian Заменяет в копии строки все найденные подстроки "what" строками "with" //! \~russian Заменяет в копии строки все найденные подстроки "what" строками "with".
//! \~\sa \a replaceAll() //! \~\sa \a replaceAll()
PIString replacedAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;} PIString replacedAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;}
//! \~english Replace all founded substrings "what" with symbols "with" in string copy //! \~english Replace all founded substrings "what" with characters "with" in string copy.
//! \~russian Заменяет в копии строки все найденные подстроки "what" символами "with" //! \~russian Заменяет в копии строки все найденные подстроки "what" символами "with".
//! \~\sa \a replaceAll() //! \~\sa \a replaceAll()
PIString replacedAll(const PIString & what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;} PIString replacedAll(const PIString & what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;}
//! \~english Replace all founded symbols "what" with symbols "with" in string copy //! \~english Replace all founded characters "what" with characters "with" in string copy.
//! \~russian Заменяет в копии строки все найденные символы "what" символами "with" //! \~russian Заменяет в копии строки все найденные символы "what" символами "with".
//! \~\sa \a replaceAll() //! \~\sa \a replaceAll()
PIString replacedAll(const char what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;} PIString replacedAll(const char what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;}
//! \~english Remove all founded substrings "what" and return this string //! \~english Remove all founded substrings "what" and return this string.
//! \~russian Удаляет все найденные подстроки "what", возвращает эту строку //! \~russian Удаляет все найденные подстроки "what", возвращает эту строку.
PIString & removeAll(const PIString & str); PIString & removeAll(const PIString & str);
//! \~english Remove all founded symbols "what" and return this string //! \~english Remove all founded characters "what" and return this string.
//! \~russian Удаляет все найденные символы "what", возвращает эту строку //! \~russian Удаляет все найденные символы "what", возвращает эту строку.
PIString & removeAll(char c) {PIDeque<PIChar>::removeAll(PIChar(c)); return *this;} PIString & removeAll(char c) {d.removeAll(PIChar(c)); return *this;}
//! \~english Repeat content of string "times" times and return this string //! \~english Repeat content of string "times" times and return this string.
//! \~russian Повторяет содержимое строки "times" раз и возвращает эту строку //! \~russian Повторяет содержимое строки "times" раз и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s(" :-) "); //! PIString s(" :-) ");
@@ -470,8 +662,8 @@ public:
//! \~\sa \a repeated() //! \~\sa \a repeated()
PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;} PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;}
//! \~english Returns repeated "times" times string //! \~english Returns repeated "times" times string.
//! \~russian Возвращает повторённую "times" раз строку //! \~russian Возвращает повторённую "times" раз строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s(" :-) "); //! PIString s(" :-) ");
@@ -481,18 +673,18 @@ public:
//! \~\sa \a repeat() //! \~\sa \a repeat()
PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);} PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);}
//! \~english Insert symbol "c" after index "index" and return this string //! \~english Insert character "c" after index "index" and return this string.
//! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку //! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("pp"); //! PIString s("pp");
//! s.insert(1, "i"); //! s.insert(1, "i");
//! piCout << s; // s = "pip" //! piCout << s; // s = "pip"
//! \endcode //! \endcode
PIString & insert(const int index, const PIChar c) {PIDeque<PIChar>::insert(index, c); return *this;} PIString & insert(const int index, const PIChar c) {d.insert(index, c); return *this;}
//! \~english Insert symbol "c" after index "index" and return this string //! \~english Insert character "c" after index "index" and return this string.
//! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку //! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("pp"); //! PIString s("pp");
@@ -501,8 +693,8 @@ public:
//! \endcode //! \endcode
PIString & insert(const int index, const char c) {return insert(index, PIChar(c));} PIString & insert(const int index, const char c) {return insert(index, PIChar(c));}
//! \~english Insert string "str" after index "index" and return this string //! \~english Insert string "str" after index "index" and return this string.
//! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку //! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("stg"); //! PIString s("stg");
@@ -511,8 +703,8 @@ public:
//! \endcode //! \endcode
PIString & insert(const int index, const PIString & str); PIString & insert(const int index, const PIString & str);
//! \~english Insert string "str" after index "index" and return this string //! \~english Insert string "str" after index "index" and return this string.
//! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку //! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("stg"); //! PIString s("stg");
@@ -521,8 +713,8 @@ public:
//! \endcode //! \endcode
PIString & insert(const int index, const char * c) {return insert(index, PIString(c));} PIString & insert(const int index, const char * c) {return insert(index, PIString(c));}
//! \~english Enlarge string to length "len" by addition symbols "c" at the end, and return this string //! \~english Enlarge string to length "len" by addition characters "c" at the end, and return this string.
//! \~russian Увеличивает длину строки до "len" добавлением символов "c" в конец и возвращает эту строку //! \~russian Увеличивает длину строки до "len" добавлением символов "c" в конец и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("str"); //! PIString s("str");
@@ -532,10 +724,10 @@ public:
//! piCout << s; // s = "str___" //! piCout << s; // s = "str___"
//! \endcode //! \endcode
//! \~\sa \a expandLeftTo(), \a expandedRightTo(), \a expandedLeftTo() //! \~\sa \a expandLeftTo(), \a expandedRightTo(), \a expandedLeftTo()
PIString & expandRightTo(const int len, const PIChar c) {if (len > length()) resize(len, c); return *this;} PIString & expandRightTo(const int len, const PIChar c) {if (len > d.size_s()) d.resize(len, c); return *this;}
//! \~english Enlarge string to length "len" by addition symbols "c" at the begin, and return this string //! \~english Enlarge string to length "len" by addition characters "c" at the begin, and return this string.
//! \~russian Увеличивает длину строки до "len" добавлением символов "c" в начало и возвращает эту строку //! \~russian Увеличивает длину строки до "len" добавлением символов "c" в начало и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("str"); //! PIString s("str");
@@ -545,10 +737,10 @@ public:
//! piCout << s; // s = "___str" //! piCout << s; // s = "___str"
//! \endcode //! \endcode
//! \~\sa \a expandRightTo(), \a expandedRightTo(), \a expandedLeftTo() //! \~\sa \a expandRightTo(), \a expandedRightTo(), \a expandedLeftTo()
PIString & expandLeftTo(const int len, const PIChar c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;} PIString & expandLeftTo(const int len, const PIChar c) {if (len > d.size_s()) insert(0, PIString(len - d.size_s(), c)); return *this;}
//! \~english Enlarge copy of this string to length "len" by addition symbols "c" at the end //! \~english Enlarge copy of this string to length "len" by addition characters "c" at the end.
//! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в конец //! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в конец.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("str"); //! PIString s("str");
@@ -558,8 +750,8 @@ public:
//! \~\sa \a expandRightTo(), \a expandLeftTo(), \a expandedLeftTo() //! \~\sa \a expandRightTo(), \a expandLeftTo(), \a expandedLeftTo()
PIString expandedRightTo(const int len, const PIChar c) const {return PIString(*this).expandRightTo(len, c);} PIString expandedRightTo(const int len, const PIChar c) const {return PIString(*this).expandRightTo(len, c);}
//! \~english Enlarge copy of this string to length "len" by addition symbols "c" at the begin //! \~english Enlarge copy of this string to length "len" by addition characters "c" at the begin.
//! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в начало //! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в начало.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("str"); //! PIString s("str");
@@ -569,8 +761,8 @@ public:
//! \~\sa \a expandRightTo(), \a expandLeftTo(), \a expandedRightTo() //! \~\sa \a expandRightTo(), \a expandLeftTo(), \a expandedRightTo()
PIString expandedLeftTo(const int len, const PIChar c) const {return PIString(*this).expandLeftTo(len, c);} PIString expandedLeftTo(const int len, const PIChar c) const {return PIString(*this).expandLeftTo(len, c);}
//! \~english Add "c" symbols at the beginning and end, and return this string //! \~english Add "c" characters at the beginning and end, and return this string.
//! \~russian Добавляет символ "c" в начало и конец и возвращает эту строку //! \~russian Добавляет символ "c" в начало и конец и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("str"); //! PIString s("str");
@@ -578,10 +770,10 @@ public:
//! piCout << s; // s = ""str"" //! piCout << s; // s = ""str""
//! \endcode //! \endcode
//! \~\sa \a quoted() //! \~\sa \a quoted()
PIString & quote(PIChar c = PIChar('"')) {insert(0, c); *this += c; return *this;} PIString & quote(PIChar c = PIChar('"')) {d.prepend(c); d.append(c); return *this;}
//! \~english Returns quoted copy of this string //! \~english Returns quoted copy of this string.
//! \~russian Возвращает копию строки с добавленным в начало и конец символом "c" //! \~russian Возвращает копию строки с добавленным в начало и конец символом "c".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("str"); //! PIString s("str");
@@ -591,8 +783,8 @@ public:
//! \~\sa \a quote() //! \~\sa \a quote()
PIString quoted(PIChar c = PIChar('"')) {return PIString(*this).quote(c);} PIString quoted(PIChar c = PIChar('"')) {return PIString(*this).quote(c);}
//! \~english Reverse string and return this string //! \~english Reverse string and return this string.
//! \~russian Разворачивает и возвращает эту строку //! \~russian Разворачивает и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -600,10 +792,10 @@ public:
//! piCout << s; // s = "9876543210" //! piCout << s; // s = "9876543210"
//! \endcode //! \endcode
//! \~\sa \a reversed() //! \~\sa \a reversed()
PIString & reverse() {PIString str(*this); clear(); piForeachCR (PIChar c, str) push_back(c); return *this;} PIString & reverse() {d.reverse(); return *this;}
//! \~english Reverse copy of this string //! \~english Reverse copy of this string.
//! \~russian Разворачивает копию этой строки //! \~russian Разворачивает копию этой строки.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -611,15 +803,15 @@ public:
//! piCout << s; // s = "0123456789" //! piCout << s; // s = "0123456789"
//! \endcode //! \endcode
//! \~\sa \a reverse() //! \~\sa \a reverse()
PIString reversed() const {PIString str(*this); str.reverse(); return str;} PIString reversed() const {PIString ret(*this); return ret.reverse();}
//! \~english Fit string to maximum size "size" by inserting ".." at position "pos" and return this string //! \~english Fit string to maximum size "size" by inserting ".." at position "pos" and return this string.
//! \~russian Уменьшает строку до размера "size", вставляя ".." в положение "pos" и возвращает эту строку //! \~russian Уменьшает строку до размера "size", вставляя ".." в положение "pos" и возвращает эту строку.
//! \~\sa \a elided() //! \~\sa \a elided()
PIString & elide(int size, float pos = ElideCenter); PIString & elide(int size, float pos = ElideCenter);
//! \~english Fit copy of this string to maximum size "size" by inserting ".." at position "pos" //! \~english Fit copy of this string to maximum size "size" by inserting ".." at position "pos".
//! \~russian Уменьшает копию этой строки до размера "size", вставляя ".." в положение "pos" //! \~russian Уменьшает копию этой строки до размера "size", вставляя ".." в положение "pos".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideLeft); // ..ABCDEF //! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideLeft); // ..ABCDEF
@@ -631,8 +823,8 @@ public:
PIString elided(int size, float pos = ElideCenter) const {PIString str(*this); str.elide(size, pos); return str;} PIString elided(int size, float pos = ElideCenter) const {PIString str(*this); str.elide(size, pos); return str;}
//! \~english Take a part of string from symbol at index "start" and maximum length "len" and return it //! \~english Take a part of string from character at index "start" and maximum length "len" and return it.
//! \~russian Извлекает часть строки от символа "start" максимальной длины "len" и возвращает её //! \~russian Извлекает часть строки от символа "start" максимальной длины "len" и возвращает её.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -642,8 +834,8 @@ public:
//! \~\sa \a takeLeft, \a takeRight() //! \~\sa \a takeLeft, \a takeRight()
PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;} PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;}
//! \~english Take a part from the begin of string with maximum length "len" and return it //! \~english Take a part from the begin of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки от начала максимальной длины "len" и возвращает её //! \~russian Извлекает часть строки от начала максимальной длины "len" и возвращает её.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -653,8 +845,8 @@ public:
//! \~\sa \a takeMid(), \a takeRight() //! \~\sa \a takeMid(), \a takeRight()
PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;} PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;}
//! \~english Take a part from the end of string with maximum length "len" and return it //! \~english Take a part from the end of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки с конца максимальной длины "len" и возвращает её //! \~russian Извлекает часть строки с конца максимальной длины "len" и возвращает её.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("0123456789"); //! PIString s("0123456789");
@@ -664,73 +856,69 @@ public:
//! \~\sa \a takeMid(), \a takeLeft() //! \~\sa \a takeMid(), \a takeLeft()
PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;} PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;}
//! \~english Take a symbol from the begin of this string and return it //! \~english Take a character from the begin of this string and return it.
//! \~russian Извлекает символ с начала строки и возвращает его как строку //! \~russian Извлекает символ с начала строки и возвращает его как строку.
PIString takeSymbol(); PIString takeSymbol();
//! \~english Take a word from the begin of this string and return it //! \~english Take a word from the begin of this string and return it.
//! \~russian Извлекает слово с начала строки и возвращает его //! \~russian Извлекает слово с начала строки и возвращает его.
PIString takeWord(); PIString takeWord();
//! \~english Take a word with letters, numbers and '_' symbols from the begin of this string and return it //! \~english Take a word with letters, numbers and '_' characters from the begin of this string and return it.
//! \~russian Извлекает слово из букв, цифр и симолов '_' с начала строки и возвращает его //! \~russian Извлекает слово из букв, цифр и симолов '_' с начала строки и возвращает его.
PIString takeCWord(); PIString takeCWord();
//! \~english Take a line from the begin of this string and return it //! \~english Take a line from the begin of this string and return it.
//! \~russian Извлекает строку текста (до новой строки) с начала строки и возвращает её //! \~russian Извлекает строку текста (до новой строки) с начала строки и возвращает её.
PIString takeLine(); PIString takeLine();
//! \~english Take a number with C-format from the begin of this string and return it //! \~english Take a number with C-format from the begin of this string and return it.
//! \~russian Извлекает число в C-формате с начала строки и возвращает его как строку //! \~russian Извлекает число в C-формате с начала строки и возвращает его как строку.
PIString takeNumber(); PIString takeNumber();
//! \~english Take a range between "start" and "end" symbols from the begin of this string and return it //! \~english Take a range between "start" and "end" characters from the begin of this string and return it.
//! \~russian Извлекает диапазон между символами "start" и "end" с начала строки и возвращает его //! \~russian Извлекает диапазон между символами "start" и "end" с начала строки и возвращает его.
PIString takeRange(const PIChar start, const PIChar end, const PIChar shield = '\\'); PIString takeRange(const PIChar start, const PIChar end, const PIChar shield = '\\');
//! \~english Returns string in brackets "start" and "end" symbols from the beginning //! \~english Returns string in brackets "start" and "end" characters from the beginning.
//! \~russian Возвращает строку между символами "start" и "end" с начала строки //! \~russian Возвращает строку между символами "start" и "end" с начала строки.
PIString inBrackets(const PIChar start, const PIChar end) const; PIString inBrackets(const PIChar start, const PIChar end) const;
//! \~english Returns bytes count of this string in system codepage //! \~english Returns \c char * representation of this string in system codepage.
//! \~russian Возвращает объем строки в системной кодировке //! \~russian Возвращает \c char * представление строки в системной кодировке.
int lengthAscii() const;
//! \~english Returns \c char * representation of this string in system codepage
//! \~russian Возвращает \c char * представление строки в системной кодировке
const char * data() const; const char * data() const;
//! \~english Returns \c char * representation of this string in terminal codepage //! \~english Returns \c char * representation of this string in terminal codepage.
//! \~russian Возвращает \c char * представление строки в кодировке консоли //! \~russian Возвращает \c char * представление строки в кодировке консоли.
const char * dataConsole() const; const char * dataConsole() const;
//! \~english Returns \c char * representation of this string in UTF-8 //! \~english Returns \c char * representation of this string in UTF-8.
//! \~russian Возвращает \c char * представление строки в кодировке UTF-8 //! \~russian Возвращает \c char * представление строки в кодировке UTF-8.
const char * dataUTF8() const; const char * dataUTF8() const;
//! \~english Returns \c char * representation of this string in ASCII //! \~english Returns \c char * representation of this string in ASCII.
//! \~russian Возвращает \c char * представление строки в кодировке ASCII //! \~russian Возвращает \c char * представление строки в кодировке ASCII.
const char * dataAscii() const; const char * dataAscii() const;
//! \~english Returns hash //! \~english Returns hash of string
//! \~russian Возвращает хэш //! \~russian Возвращает хэш строки
uint hash() const; uint hash() const;
//! \~english Returns \a PIByteArray contains \a data() of this string without terminating null-char //! \~english Same as \a toUTF8().
//! \~russian Возвращает \a PIByteArray содержащий \a data() строки без завершающего нулевого байта //! \~russian Тоже самое, что \a toUTF8().
PIByteArray toByteArray() const {buildData(__utf8name__); return data_.resized(data_.size_s() - 1);} PIByteArray toByteArray() const {return toUTF8();}
//! \~english Returns \a PIByteArray contains \a dataUTF8() of this string without terminating null-char //! \~english Returns \a PIByteArray contains \a dataUTF8() of this string without terminating null-char.
//! \~russian Возвращает \a PIByteArray содержащий \a dataUTF8() строки без завершающего нулевого байта //! \~russian Возвращает \a PIByteArray содержащий \a dataUTF8() строки без завершающего нулевого байта.
PIByteArray toUTF8() const; PIByteArray toUTF8() const;
//! \~english Returns \a PIByteArray contains custom charset representation of this string without terminating null-char //! \~english Returns \a PIByteArray contains custom charset representation of this string without terminating null-char.
//! \~russian Возвращает \a PIByteArray содержащий строку в указанной кодировке без завершающего нулевого байта //! \~russian Возвращает \a PIByteArray содержащий строку в указанной кодировке без завершающего нулевого байта.
PIByteArray toCharset(const char * c) const; PIByteArray toCharset(const char * c) const;
//! \~english Split string with delimiter "delim" to \a PIStringList //! \~english Split string with delimiter "delim" to \a PIStringList.
//! \~russian Разделяет строку в \a PIStringList через разделитель "delim" //! \~russian Разделяет строку в \a PIStringList через разделитель "delim".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("1 2 3"); //! PIString s("1 2 3");
@@ -739,40 +927,45 @@ public:
PIStringList split(const PIString & delim) const; PIStringList split(const PIString & delim) const;
//! \~english Convert each symbol in copied string to upper case //! \~english Convert each character in copied string to upper case.
//! \~russian Преобразует каждый символ в скопированной строке в верхний регистр //! \~russian Преобразует каждый символ в скопированной строке в верхний регистр.
PIString toUpperCase() const; PIString toUpperCase() const;
//! \~english Convert each symbol in copied string to lower case //! \~english Convert each character in copied string to lower case.
//! \~russian Преобразует каждый символ в скопированной строке в нижний регистр //! \~russian Преобразует каждый символ в скопированной строке в нижний регистр.
PIString toLowerCase() const; PIString toLowerCase() const;
// TODO: doxygen
PIString toNativeDecimalPoints() const; PIString toNativeDecimalPoints() const;
//! \~english Returns if string contains symbol "c" //! \~english Returns if string contains character "c".
//! \~russian Возвращает содержит ли строка символ "c" //! \~russian Возвращает содержит ли строка символ "c".
bool contains(const char c) const {return PIDeque<PIChar>::contains(PIChar(c));} bool contains(const char c) const {return d.contains(PIChar(c));}
//! \~english Returns if string contains substring "str" //! \~english Returns if string contains substring "str".
//! \~russian Возвращает содержит ли строка подстроку "str" //! \~russian Возвращает содержит ли строка подстроку "str".
bool contains(const char * str) const {return contains(PIString(str));} bool contains(const char * str) const {return contains(PIString(str));}
//! \~english Returns if string contains substring "str" //! \~english Returns if string contains substring "str".
//! \~russian Возвращает содержит ли строка подстроку "str" //! \~russian Возвращает содержит ли строка подстроку "str".
bool contains(const PIString & str) const {return find(str) >= 0;} bool contains(const PIString & str) const {return find(str) >= 0;}
//! \~english Search symbol "c" from symbol at index "start" and return first occur position //! \~english Search character "c" from character at index "start" and return first occur position.
//! \~russian Ищет символ "c" от символа "start" и возвращает первое вхождение //! \~russian Ищет символ "c" от символа "start" и возвращает первое вхождение.
int find(const char c, const int start = 0) const; int find(const char c, const int start = 0) const;
//! \~english Search substring "str" from symbol at index "start" and return first occur position //! \~english Search character "c" from character at index "start" and return first occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение //! \~russian Ищет символ "c" от символа "start" и возвращает первое вхождение.
int find(PIChar c, const int start = 0) const {return d.indexOf(c, start);}
//! \~english Search substring "str" from character at index "start" and return first occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение.
int find(const PIString & str, const int start = 0) const; int find(const PIString & str, const int start = 0) const;
//! \~english Search substring "str" from symbol at index "start" and return first occur position //! \~english Search substring "str" from character at index "start" and return first occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение //! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("012345012345"); //! PIString s("012345012345");
@@ -784,12 +977,12 @@ public:
//! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange() //! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int find(const char * str, const int start = 0) const {return find(PIString(str), start);} int find(const char * str, const int start = 0) const {return find(PIString(str), start);}
//! \~english Search any symbol of "str" from symbol at index "start" and return first occur position //! \~english Search any character of "str" from character at index "start" and return first occur position.
//! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение //! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение.
int findAny(const PIString & str, const int start = 0) const; int findAny(const PIString & str, const int start = 0) const;
//! \~english Search any symbol of "str" from symbol at index "start" and return first occur position //! \~english Search any character of "str" from character at index "start" and return first occur position.
//! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение //! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString("1.str").findAny(".,:"); // 1 //! piCout << PIString("1.str").findAny(".,:"); // 1
@@ -799,16 +992,20 @@ public:
//! \~\sa \a find(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange() //! \~\sa \a find(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int findAny(const char * str, const int start = 0) const {return findAny(PIString(str), start);} int findAny(const char * str, const int start = 0) const {return findAny(PIString(str), start);}
//! \~english Search symbol "c" from symbol at index "start" and return last occur position //! \~english Search character "c" from character at index "start" and return last occur position.
//! \~russian Ищет символ "c" от символа "start" и возвращает последнее вхождение //! \~russian Ищет символ "c" от символа "start" и возвращает последнее вхождение.
int findLast(const char c, const int start = 0) const; int findLast(const char c, const int start = 0) const;
//! \~english Search substring "str" from symbol at index "start" and return last occur position //! \~english Search character "c" from character at index "start" and return last occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает последнее вхождение //! \~russian Ищет символ "c" от символа "start" и возвращает последнее вхождение.
int findLast(PIChar c, const int start = 0) const;
//! \~english Search substring "str" from character at index "start" and return last occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает последнее вхождение.
int findLast(const PIString & str, const int start = 0) const; int findLast(const PIString & str, const int start = 0) const;
//! \~english Search substring "str" from symbol at index "start" and return last occur position //! \~english Search substring "str" from character at index "start" and return last occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает последнее вхождение //! \~russian Ищет подстроку "str" от символа "start" и возвращает последнее вхождение.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s("012345012345"); //! PIString s("012345012345");
@@ -820,12 +1017,12 @@ public:
//! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange() //! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);} int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);}
//! \~english Search any symbol of "str" from symbol at index "start" and return last occur position //! \~english Search any character of "str" from character at index "start" and return last occur position.
//! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение //! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение.
int findAnyLast(const PIString & str, const int start = 0) const; int findAnyLast(const PIString & str, const int start = 0) const;
//! \~english Search any symbol of "str" from symbol at index "start" and return last occur position //! \~english Search any character of "str" from character at index "start" and return last occur position.
//! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение //! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString(".str.0").findAnyLast(".,:"); // 4 //! piCout << PIString(".str.0").findAnyLast(".,:"); // 4
@@ -835,20 +1032,20 @@ public:
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findWord(), \a findCWord(), \a findRange() //! \~\sa \a find(), \a findAny(), \a findLast(), \a findWord(), \a findCWord(), \a findRange()
int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);} int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);}
//! \~english Search word "word" from symbol at index "start" and return first occur position //! \~english Search word "word" from character at index "start" and return first occur position.
//! \~russian Ищет слово "word" от симола "start" и возвращает первое вхождение //! \~russian Ищет слово "word" от симола "start" и возвращает первое вхождение.
int findWord(const PIString & word, const int start = 0) const; int findWord(const PIString & word, const int start = 0) const;
//! \~english Search C-word "word" from symbol at index "start" and return first occur position //! \~english Search C-word "word" from character at index "start" and return first occur position.
//! \~russian Ищет C-слово "word" от симола "start" и возвращает первое вхождение //! \~russian Ищет C-слово "word" от симола "start" и возвращает первое вхождение.
int findCWord(const PIString & word, const int start = 0) const; int findCWord(const PIString & word, const int start = 0) const;
//! \~english Search range start between "start" and "end" symbols at index "start_index" and return first occur position //! \~english Search range start between "start" and "end" characters at index "start_index" and return first occur position.
//! \~russian Ищет начало диапазона между символами "start" и "end" от симола "start" и возвращает первое вхождение //! \~russian Ищет начало диапазона между символами "start" и "end" от симола "start" и возвращает первое вхождение.
int findRange(const PIChar start, const PIChar end, const PIChar shield = '\\', const int start_index = 0, int * len = 0) const; int findRange(const PIChar start, const PIChar end, const PIChar shield = '\\', const int start_index = 0, int * len = 0) const;
//! \~english Returns number of occurrences of symbol "c" //! \~english Returns number of occurrences of character "c".
//! \~russian Возвращает число вхождений символа "c" //! \~russian Возвращает число вхождений символа "c".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString(".str.0").entries("."); // 2 //! piCout << PIString(".str.0").entries("."); // 2
@@ -856,8 +1053,8 @@ public:
//! \endcode //! \endcode
int entries(const PIChar c) const; int entries(const PIChar c) const;
//! \~english Returns number of occurrences of symbol "c" //! \~english Returns number of occurrences of character "c".
//! \~russian Возвращает число вхождений символа "c" //! \~russian Возвращает число вхождений символа "c".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString(".str.0").entries('.'); // 2 //! piCout << PIString(".str.0").entries('.'); // 2
@@ -865,40 +1062,56 @@ public:
//! \endcode //! \endcode
int entries(char c) const {return entries(PIChar(c));} int entries(char c) const {return entries(PIChar(c));}
//! \~english Returns if string starts with "str" //! \~english Returns if string starts with "str".
//! \~russian Возвращает начинается ли строка со "str" //! \~russian Возвращает начинается ли строка со "str".
bool startsWith(const PIString & str) const; bool startsWith(const PIString & str) const;
//! \~english Returns if string ends with "str" //! \~english Returns if string ends with "str".
//! \~russian Возвращает оканчивается ли строка на "str" //! \~russian Возвращает оканчивается ли строка на "str".
bool endsWith(const PIString & str) const; bool endsWith(const PIString & str) const;
//! \~english Returns symbols length of string //! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах //! \~russian Возвращает длину строки в символах.
int length() const {return size();} int length() const {return d.size_s();}
//! \~english Returns \c true if string is empty, i.e. length = 0 //! \~english Returns characters length of string.
//! \~russian Возвращает \c true если строка пустая, т.е. длина = 0 //! \~russian Возвращает длину строки в символах.
bool isEmpty() const {return (size() == 0 || *this == "");} size_t size() const {return d.size();}
//! \~english Returns \c true if string is not empty, i.e. length > 0 //! \~english Returns characters length of string.
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0 //! \~russian Возвращает длину строки в символах.
ssize_t size_s() const {return d.size_s();}
//! \~english Returns \c true if string is empty, i.e. length = 0.
//! \~russian Возвращает \c true если строка пустая, т.е. длина = 0.
bool isEmpty() const {if (d.isEmpty()) return true; if (d.at(0) == PIChar()) return true; return false;}
//! \~english Returns \c true if string is not empty, i.e. length > 0.
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
bool isNotEmpty() const {return !isEmpty();} bool isNotEmpty() const {return !isEmpty();}
//! \~english Clear string, will be empty string.
//! \~russian Очищает строку, строка становится пустой.
//! \~\details
//! \~\note
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
void clear() {d.clear();}
//! \~english Returns \c true if string equal "true", "yes", "on" or positive not null numeric value //! \~english Returns \c true if string equal "true", "yes", "on" or positive not null numeric value.
//! \~russian Возвращает \c true если строка равна "true", "yes", "on" или числу > 0 //! \~russian Возвращает \c true если строка равна "true", "yes", "on" или числу > 0.
bool toBool() const; bool toBool() const;
//! \~english Returns \c char numeric value of string //! \~english Returns \c char numeric value of string.
//! \~russian Возвращает \c char числовое значение строки //! \~russian Возвращает \c char числовое значение строки.
char toChar() const; char toChar() const;
//! \~english Returns \c short numeric value of string in base "base" //! \~english Returns \c short numeric value of string in base "base".
//! \~russian Возвращает \c short числовое значение строки по основанию "base" //! \~russian Возвращает \c short числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toShort(); // 123 //! piCout << PIString("123").toShort(); // 123
//! piCout << PIString("123").toShort(16); // 291 //! piCout << PIString("123").toShort(16); // 291
@@ -907,11 +1120,11 @@ public:
//! \endcode //! \endcode
short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));} short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));}
//! \~english Returns \c ushort numeric value of string in base "base" //! \~english Returns \c ushort numeric value of string in base "base".
//! \~russian Возвращает \c ushort числовое значение строки по основанию "base" //! \~russian Возвращает \c ushort числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toUShort(); // 123 //! piCout << PIString("123").toUShort(); // 123
//! piCout << PIString("123").toUShort(16); // 291 //! piCout << PIString("123").toUShort(16); // 291
@@ -920,11 +1133,11 @@ public:
//! \endcode //! \endcode
ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));} ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));}
//! \~english Returns \c int numeric value of string in base "base" //! \~english Returns \c int numeric value of string in base "base".
//! \~russian Возвращает \c int числовое значение строки по основанию "base" //! \~russian Возвращает \c int числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toInt(); // 123 //! piCout << PIString("123").toInt(); // 123
//! piCout << PIString("123").toInt(16); // 291 //! piCout << PIString("123").toInt(16); // 291
@@ -933,11 +1146,11 @@ public:
//! \endcode //! \endcode
int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));} int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));}
//! \~english Returns \c uint numeric value of string in base "base" //! \~english Returns \c uint numeric value of string in base "base".
//! \~russian Возвращает \c uint числовое значение строки по основанию "base" //! \~russian Возвращает \c uint числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toUInt(); // 123 //! piCout << PIString("123").toUInt(); // 123
//! piCout << PIString("123").toUInt(16); // 291 //! piCout << PIString("123").toUInt(16); // 291
@@ -946,11 +1159,11 @@ public:
//! \endcode //! \endcode
uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));} uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));}
//! \~english Returns \c long numeric value of string in base "base" //! \~english Returns \c long numeric value of string in base "base".
//! \~russian Возвращает \c long числовое значение строки по основанию "base" //! \~russian Возвращает \c long числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toLong(); // 123 //! piCout << PIString("123").toLong(); // 123
//! piCout << PIString("123").toLong(16); // 291 //! piCout << PIString("123").toLong(16); // 291
@@ -959,11 +1172,11 @@ public:
//! \endcode //! \endcode
long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));} long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));}
//! \~english Returns \c ulong numeric value of string in base "base" //! \~english Returns \c ulong numeric value of string in base "base".
//! \~russian Возвращает \c ulong числовое значение строки по основанию "base" //! \~russian Возвращает \c ulong числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toULong(); // 123 //! piCout << PIString("123").toULong(); // 123
//! piCout << PIString("123").toULong(16); // 291 //! piCout << PIString("123").toULong(16); // 291
@@ -972,11 +1185,11 @@ public:
//! \endcode //! \endcode
ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));} ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));}
//! \~english Returns \c llong numeric value of string in base "base" //! \~english Returns \c llong numeric value of string in base "base".
//! \~russian Возвращает \c llong числовое значение строки по основанию "base" //! \~russian Возвращает \c llong числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toLLong(); // 123 //! piCout << PIString("123").toLLong(); // 123
//! piCout << PIString("123").toLLong(16); // 291 //! piCout << PIString("123").toLLong(16); // 291
@@ -985,11 +1198,11 @@ public:
//! \endcode //! \endcode
llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);} llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);}
//! \~english Returns \c ullong numeric value of string in base "base" //! \~english Returns \c ullong numeric value of string in base "base".
//! \~russian Возвращает \c ullong числовое значение строки по основанию "base" //! \~russian Возвращает \c ullong числовое значение строки по основанию "base".
//! \~\details //! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10 //! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10 //! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code //! \~\code
//! piCout << PIString("123").toULLong(); // 123 //! piCout << PIString("123").toULLong(); // 123
//! piCout << PIString("123").toULLong(16); // 291 //! piCout << PIString("123").toULLong(16); // 291
@@ -998,8 +1211,8 @@ public:
//! \endcode //! \endcode
ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));} ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));}
//! \~english Returns \c float numeric value of string //! \~english Returns \c float numeric value of string.
//! \~russian Возвращает \c float числовое значение строки //! \~russian Возвращает \c float числовое значение строки.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString("123").toFloat(); // 123 //! piCout << PIString("123").toFloat(); // 123
@@ -1008,8 +1221,8 @@ public:
//! \endcode //! \endcode
float toFloat() const; float toFloat() const;
//! \~english Returns \c double numeric value of string //! \~english Returns \c double numeric value of string.
//! \~russian Возвращает \c double числовое значение строки //! \~russian Возвращает \c double числовое значение строки.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString("123").toDouble(); // 123 //! piCout << PIString("123").toDouble(); // 123
@@ -1018,8 +1231,8 @@ public:
//! \endcode //! \endcode
double toDouble() const; double toDouble() const;
//! \~english Returns \c ldouble numeric value of string //! \~english Returns \c ldouble numeric value of string.
//! \~russian Возвращает \c ldouble числовое значение строки //! \~russian Возвращает \c ldouble числовое значение строки.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString("123").toLDouble(); // 123 //! piCout << PIString("123").toLDouble(); // 123
@@ -1028,8 +1241,8 @@ public:
//! \endcode //! \endcode
ldouble toLDouble() const; ldouble toLDouble() const;
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1038,10 +1251,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const short value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1050,10 +1263,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1062,10 +1275,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const int value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1074,10 +1287,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1086,10 +1299,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const long value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1098,10 +1311,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1110,10 +1323,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string //! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1122,10 +1335,10 @@ public:
//! s.setNumber(123, 16); //! s.setNumber(123, 16);
//! piCout << s; // 7B //! piCout << s; // 7B
//! \endcode //! \endcode
PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string //! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1140,10 +1353,10 @@ public:
//! s.setNumber(123456789., 'f', 0); //! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789 //! piCout << s; // 123456789
//! \endcode //! \endcode
PIString & setNumber(const float value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;} PIString & setNumber(const float value, char format = 'f', int precision = 8) {*this = PIString::fromNumber(value, format, precision); return *this;}
//! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string //! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1158,10 +1371,10 @@ public:
//! s.setNumber(123456789., 'f', 0); //! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789 //! piCout << s; // 123456789
//! \endcode //! \endcode
PIString & setNumber(const double & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;} PIString & setNumber(const double & value, char format = 'f', int precision = 8) {*this = PIString::fromNumber(value, format, precision); return *this;}
//! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string //! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку //! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку.
//! \~\details //! \~\details
//! \~\code //! \~\code
//! PIString s; //! PIString s;
@@ -1176,15 +1389,15 @@ public:
//! s.setNumber(123456789., 'f', 0); //! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789 //! piCout << s; // 123456789
//! \endcode //! \endcode
PIString & setNumber(const ldouble & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;} PIString & setNumber(const ldouble & value, char format = 'f', int precision = 8) {*this = PIString::fromNumber(value, format, precision); return *this;}
//! \~english Set string content to human readable size in B/kB/MB/GB/TB/PB //! \~english Set string content to human readable size in B/kB/MB/GB/TB/PB.
//! \~russian Устанавливает содержимое в строку с читаемым размером B/kB/MB/GB/TB/PB //! \~russian Устанавливает содержимое в строку с читаемым размером B/kB/MB/GB/TB/PB.
//! \~\sa PIString::readableSize() //! \~\sa PIString::readableSize()
PIString & setReadableSize(llong bytes); PIString & setReadableSize(llong bytes);
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1192,8 +1405,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1201,8 +1414,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1210,8 +1423,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1219,8 +1432,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1228,8 +1441,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1237,8 +1450,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1246,8 +1459,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);} static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base" //! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base" //! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(123); // 123 //! piCout << PIString::fromNumber(123); // 123
@@ -1255,8 +1468,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);} static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);}
//! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision" //! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision".
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision" //! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000 //! piCout << PIString::fromNumber(12.3); // 12.30000000
@@ -1265,10 +1478,10 @@ public:
//! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08 //! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08
//! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789 //! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789
//! \endcode //! \endcode
static PIString fromNumber(const float value, char format = 'f', int precision = 8) {return ftos(value, format, precision);} static PIString fromNumber(const float value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
//! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision" //! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision".
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision" //! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000 //! piCout << PIString::fromNumber(12.3); // 12.30000000
@@ -1279,8 +1492,8 @@ public:
//! \endcode //! \endcode
static PIString fromNumber(const double & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);} static PIString fromNumber(const double & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
//! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision" //! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision".
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision" //! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision".
//! \~\details //! \~\details
//! \~\code //! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000 //! piCout << PIString::fromNumber(12.3); // 12.30000000
@@ -1293,44 +1506,54 @@ public:
//! \~english Returns "true" or "false" //! \~english Returns "true" or "false"
//! \~russian Возвращает "true" или "false" //! \~russian Возвращает "true" или "false"
static PIString fromBool(const bool value) {return PIString(value ? "true" : "false");} static PIString fromBool(const bool value) {return PIString(value ? PIStringAscii("true") : PIStringAscii("false"));}
//! \~english Returns string constructed from terminal codepage //! \~english Returns string constructed from terminal codepage.
//! \~russian Возвращает строку созданную из кодировки консоли //! \~russian Возвращает строку созданную из кодировки консоли.
static PIString fromConsole(const char * s); static PIString fromConsole(const char * s);
//! \~english Returns string constructed from system codepage //! \~english Returns string constructed from system codepage.
//! \~russian Возвращает строку созданную из кодировки системы //! \~russian Возвращает строку созданную из кодировки системы.
static PIString fromSystem(const char * s); static PIString fromSystem(const char * s);
//! \~english Returns string constructed from UTF-8 //! \~english Returns string constructed from UTF-8.
//! \~russian Возвращает строку созданную из UTF-8 //! \~russian Возвращает строку созданную из UTF-8.
static PIString fromUTF8(const char * s); static PIString fromUTF8(const char * s);
//! \~english Returns string constructed from UTF-8 //! \~english Returns string constructed from UTF-8.
//! \~russian Возвращает строку созданную из UTF-8 //! \~russian Возвращает строку созданную из UTF-8.
static PIString fromUTF8(const PIByteArray & utf); static PIString fromUTF8(const PIByteArray & utf);
//! \~english Returns string constructed from ASCII //! \~english Returns string constructed from ASCII.
//! \~russian Возвращает строку созданную из ASCII //! \~russian Возвращает строку созданную из ASCII.
static PIString fromAscii(const char * s); static PIString fromAscii(const char * s);
//! \~english Returns string constructed from "len" chars ASCII //! \~english Returns string constructed from "len" chars ASCII.
//! \~russian Возвращает строку созданную из "len" символов ASCII //! \~russian Возвращает строку созданную из "len" символов ASCII.
static PIString fromAscii(const char * s, int len); static PIString fromAscii(const char * s, int len);
//! \~english Returns string constructed from "cp" codepage //! \~english Returns string constructed from "cp" codepage.
//! \~russian Возвращает строку созданную из кодировки "cp" //! \~russian Возвращает строку созданную из кодировки "cp".
static PIString fromCodepage(const char * s, const char * cp); static PIString fromCodepage(const char * s, const char * cp);
//! \~english Returns string contains human readable size in B/kB/MB/GB/TB/PB //! \~english Returns string contains human readable size in B/kB/MB/GB/TB/PB.
//! \~russian Возвращает строку с читаемым размером B/kB/MB/GB/TB/PB //! \~russian Возвращает строку с читаемым размером B/kB/MB/GB/TB/PB.
//! \~\sa PIString::setReadableSize() //! \~\sa PIString::setReadableSize()
static PIString readableSize(llong bytes); static PIString readableSize(llong bytes);
//! \~english Swaps string `str` other with this string.
//! \~russian Меняет строку `str` с этой строкой.
//! \~\details
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
void swap(PIString & str) {
d.swap(str.d);
piSwap(data_, str.data_);
}
private: private:
static const char toBaseN[]; static const char toBaseN[];
static const int fromBaseN[]; static const char fromBaseN[];
static PIString itos(const int num); static PIString itos(const int num);
static PIString ltos(const long num); static PIString ltos(const long num);
@@ -1338,71 +1561,72 @@ private:
static PIString uitos(const uint num); static PIString uitos(const uint num);
static PIString ultos(const ulong num); static PIString ultos(const ulong num);
static PIString ulltos(const ullong num); static PIString ulltos(const ullong num);
static PIString ftos(const float num, char format = 'f', int precision = 8);
static PIString dtos(const double num, char format = 'f', int precision = 8); static PIString dtos(const double num, char format = 'f', int precision = 8);
static PIString fromNumberBaseS(const llong value, int base = 10, bool * ok = 0); static PIString fromNumberBaseS(const llong value, int base = 10, bool * ok = 0);
static PIString fromNumberBaseU(const ullong value, int base = 10, bool * ok = 0); static PIString fromNumberBaseU(const ullong value, int base = 10, bool * ok = 0);
static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0); static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0);
void appendFromChars(const char * c, int s, const char * cp = __syslocname__); void appendFromChars(const char * c, int s, const char * cp = __syslocname__);
void buildData(const char * cp = __syslocname__) const; void buildData(const char * cp = __syslocname__) const;
void deleteData() const;
void trimsubstr(int &st, int &fn) const; void trimsubstr(int &st, int &fn) const;
mutable PIByteArray data_;
PIDeque<PIChar> d;
mutable char * data_ = nullptr;
}; };
//! \relatesalso PICout //! \relatesalso PICout
//! \~english Output operator to \a PICout //! \~english Output operator to \a PICout.
//! \~russian Оператор вывода в \a PICout //! \~russian Оператор вывода в \a PICout.
PIP_EXPORT PICout operator <<(PICout s, const PIString & v); PIP_EXPORT PICout operator <<(PICout s, const PIString & v);
//! \relatesalso PIByteArray //! \relatesalso PIByteArray
//! \~english Store operator //! \~english Store operator.
//! \~russian Оператор сохранения //! \~russian Оператор сохранения.
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << *(PIDeque<PIChar>*)&v; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.d; return s;}
//! \relatesalso PIByteArray //! \relatesalso PIByteArray
//! \~english Restore operator //! \~english Restore operator.
//! \~russian Оператор извлечения //! \~russian Оператор извлечения.
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {v.clear(); s >> *(PIDeque<PIChar>*)&v; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {v.d.clear(); s >> v.d; return s;}
//! \~english Returns concatenated string //! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк //! \~russian Возвращает соединение строк.
inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;} inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;}
//! \~english Returns concatenated string //! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк //! \~russian Возвращает соединение строк.
inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;} inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;}
//! \~english Returns concatenated string //! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк //! \~russian Возвращает соединение строк.
inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;} inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;}
//! \~english Returns concatenated string //! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк //! \~russian Возвращает соединение строк.
inline PIString operator +(const char c, const PIString & f) {return PIChar(c) + f;} inline PIString operator +(const char c, const PIString & f) {return PIChar(c) + f;}
//! \~english Returns concatenated string //! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк //! \~russian Возвращает соединение строк.
inline PIString operator +(const PIString & f, const char c) {return f + PIChar(c);} inline PIString operator +(const PIString & f, const char c) {return f + PIChar(c);}
//! \relatesalso PIString //! \relatesalso PIString
//! \~english Compare two version strings in free notation and returns 0, -1 or 1 //! \~english Compare two version strings in free notation and returns 0, -1 or 1.
//! \~russian Сравнивает две строки с версиями в произвольной форме и возвращает 0, -1 или 1 //! \~russian Сравнивает две строки с версиями в произвольной форме и возвращает 0, -1 или 1.
int PIP_EXPORT versionCompare(const PIString & v0, const PIString & v1, int components = 6); int PIP_EXPORT versionCompare(const PIString & v0, const PIString & v1, int components = 6);
//! \relatesalso PIString //! \relatesalso PIString
//! \~english Converts version string in free notation to classic view //! \~english Converts version string in free notation to classic view.
//! \~russian Преобразует строку с версией в произвольной форме к классическому виду //! \~russian Преобразует строку с версией в произвольной форме к классическому виду.
PIString PIP_EXPORT versionNormalize(const PIString & v); PIString PIP_EXPORT versionNormalize(const PIString & v);
//! \~english Returns hash of string
//! \~russian Возвращает хэш строки
template<> inline uint piHash(const PIString & s) {return s.hash();} template<> inline uint piHash(const PIString & s) {return s.hash();}
template<> inline void piSwap(PIString & f, PIString & s) {f.swap(s);} template<> inline void piSwap(PIString & f, PIString & s) {
f.swap(s);
}
#endif // PISTRING_H #endif // PISTRING_H

View File

@@ -20,16 +20,9 @@
#include "pistringlist.h" #include "pistringlist.h"
//! \addtogroup Core
//! \{
//! \~\class PIStringList pistringlist.h //! \~\class PIStringList pistringlist.h
//! \~\brief
//! \~english Based on \a PIDeque<PIString> strings list
//! \~russian Основанный на \a PIDeque<PIString> массив строк
//!
//! \~\details //! \~\details
//! //!
//! \}
//! \details //! \details

View File

@@ -29,6 +29,10 @@
#include "pistring.h" #include "pistring.h"
//! \ingroup Core
//! \~\brief
//! \~english Based on \a PIDeque<PIString> strings list.
//! \~russian Основанный на \a PIDeque<PIString> массив строк.
class PIP_EXPORT PIStringList: public PIDeque<PIString> class PIP_EXPORT PIStringList: public PIDeque<PIString>
{ {
public: public:

View File

@@ -45,13 +45,8 @@
#endif #endif
//! \addtogroup Core
//! \{
//! \class PISystemTime pisystemtime.h //! \class PISystemTime pisystemtime.h
//! \brief //! \details
//! \~english System time with nanosecond precision
//! \~russian Системное время с точностью до наносекунд
//!
//! \~english \section PISystemTime_sec0 Synopsis //! \~english \section PISystemTime_sec0 Synopsis
//! \~russian \section PISystemTime_sec0 Краткий обзор //! \~russian \section PISystemTime_sec0 Краткий обзор
//! \~english //! \~english
@@ -72,16 +67,10 @@
//! \~russian \section PISystemTime_sec1 Пример //! \~russian \section PISystemTime_sec1 Пример
//! \~\snippet pitimer.cpp system_time //! \~\snippet pitimer.cpp system_time
//! //!
//! \}
//! \addtogroup Core
//! \{
//! \class PITimeMeasurer pisystemtime.h //! \class PITimeMeasurer pisystemtime.h
//! \brief //! \details
//! \~english Time measurements
//! \~russian Измерение времени
//!
//! \~english \section PITimeMeasurer_sec0 Usage //! \~english \section PITimeMeasurer_sec0 Usage
//! \~russian \section PITimeMeasurer_sec0 Использование //! \~russian \section PITimeMeasurer_sec0 Использование
//! \~english //! \~english
@@ -96,7 +85,6 @@
//! Эти методы возвращают нано, микро, милли и секунды с приставками //! Эти методы возвращают нано, микро, милли и секунды с приставками
//! "n", "u", "m" и "s". //! "n", "u", "m" и "s".
//! //!
//! \}

View File

@@ -30,6 +30,10 @@
#include "pistring.h" #include "pistring.h"
//! \ingroup Core
//! \~\brief
//! \~english System time with nanosecond precision.
//! \~russian Системное время с точностью до наносекунд.
class PIP_EXPORT PISystemTime { class PIP_EXPORT PISystemTime {
public: public:
@@ -187,6 +191,10 @@ inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.setCon
//! \ingroup Core
//! \~\brief
//! \~english Time measurements.
//! \~russian Измерение времени.
class PIP_EXPORT PITimeMeasurer { class PIP_EXPORT PITimeMeasurer {
public: public:
PITimeMeasurer(); PITimeMeasurer();

View File

@@ -21,7 +21,6 @@
/** \class PIVariant /** \class PIVariant
* \brief Variant type
* \details * \details
* \section PIVariant_sec0 Synopsis * \section PIVariant_sec0 Synopsis
* This class provides general type that can contains all standard types, some * This class provides general type that can contains all standard types, some

View File

@@ -27,6 +27,7 @@
#define PIVARIANT_H #define PIVARIANT_H
#include "pivarianttypes.h" #include "pivarianttypes.h"
#include "piconstchars.h"
#include "pitime.h" #include "pitime.h"
#include "pigeometry.h" #include "pigeometry.h"
#include "pimathmatrix.h" #include "pimathmatrix.h"
@@ -200,6 +201,9 @@ classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(c
#endif #endif
//! \ingroup Core
//! \~\brief
//! \~english Variant type.
class PIP_EXPORT PIVariant { class PIP_EXPORT PIVariant {
friend PICout operator <<(PICout s, const PIVariant & v); friend PICout operator <<(PICout s, const PIVariant & v);
friend PIByteArray & operator <<(PIByteArray & s, const PIVariant & v); friend PIByteArray & operator <<(PIByteArray & s, const PIVariant & v);
@@ -801,7 +805,10 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVariant & v) {
inline PICout operator <<(PICout s, const PIVariant & v) { inline PICout operator <<(PICout s, const PIVariant & v) {
s.space(); s.setControl(0, true); s.space(); s.setControl(0, true);
s << "PIVariant(" << v.typeName() << ", " << v.toString() << ")"; s << "PIVariant(" << v.typeName();
if (v.isValid())
s << ", " << v.toString();
s << ")";
s.restoreControl(); return s; s.restoreControl(); return s;
} }

View File

@@ -16,16 +16,16 @@
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 Crypt //! \defgroup Crypt Crypt
//! \~\brief //! \~\brief
//! \~english Cryptographic support //! \~english Cryptographic support
//! \~russian Поддержка шифрования //! \~russian Поддержка шифрования
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Crypt Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Crypt Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Crypt) //! target_link_libraries([target] PIP::Crypt)
//! \endcode //! \endcode

View File

@@ -16,16 +16,16 @@
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 Geo //! \defgroup Geo Geo
//! \~\brief //! \~\brief
//! \~english Geographical position and Earth models //! \~english Geographical position and Earth models
//! \~russian Географическая позиция и модели Земли //! \~russian Географическая позиция и модели Земли
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Geo Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Geo Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP) //! target_link_libraries([target] PIP)
//! \endcode //! \endcode

View File

@@ -16,16 +16,16 @@
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 Introspection //! \defgroup Introspection Introspection
//! \~\brief //! \~\brief
//! \~english Internal PIP introspection //! \~english Internal PIP introspection
//! \~russian Внутренняя интроспекция PIP //! \~russian Внутренняя интроспекция PIP
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_Introspection Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_Introspection Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP) //! target_link_libraries([target] PIP)
//! \endcode //! \endcode

View File

@@ -17,13 +17,49 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "piintrospection_containers.h"
PIIntrospectionContainersType::~PIIntrospectionContainersType() {
if (has_demangled) {
//free((void*)demangled);
has_demangled = false;
}
}
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_containers.h"
#include "piintrospection_containers_p.h" #include "piintrospection_containers_p.h"
__PIINTROSPECTION_SINGLETON_CPP__(Containers) __PIINTROSPECTION_SINGLETON_CPP__(Containers)
#ifdef CC_GCC
# include <cxxabi.h>
const char * demangle(const char * name) {
int status = -4;
char * res = abi::__cxa_demangle(name, NULL, NULL, &status);
if (status == 0) return res;
return name;
}
#else
const char * demangle(const char * name) {return name;}
#endif
void PIIntrospectionContainersType::finish() {
inited = true;
if (!name) {
printf("[PIIntrospectionContainersType::finish] Null name!\n");
return;
}
size_t l = strlen(name);
if (l > 0)
id = piHashData((const uchar*)name, int(l));
demangled = demangle(name);
has_demangled = name != demangled;
//printf("create typeinfo for %s -> %s\n", name, demangled);
}
PIIntrospectionContainersInterface::PIIntrospectionContainersInterface() { PIIntrospectionContainersInterface::PIIntrospectionContainersInterface() {
p = new PIIntrospectionContainers(); p = new PIIntrospectionContainers();
@@ -35,33 +71,33 @@ PIIntrospectionContainersInterface::~PIIntrospectionContainersInterface() {
} }
void PIIntrospectionContainersInterface::containerNew(const char * tn, uint isz) { void PIIntrospectionContainersInterface::containerNew(const PIIntrospectionContainersType & ti, uint isz) {
p->containerNew(tn, isz); p->containerNew(ti, isz);
} }
void PIIntrospectionContainersInterface::containerDelete(const char * tn) { void PIIntrospectionContainersInterface::containerDelete(const PIIntrospectionContainersType & ti) {
p->containerDelete(tn); p->containerDelete(ti);
} }
void PIIntrospectionContainersInterface::containerAlloc(const char * tn, ullong cnt) { void PIIntrospectionContainersInterface::containerAlloc(const PIIntrospectionContainersType & ti, ullong cnt) {
p->containerAlloc(tn, cnt); p->containerAlloc(ti, cnt);
} }
void PIIntrospectionContainersInterface::containerFree(const char * tn, ullong cnt) { void PIIntrospectionContainersInterface::containerFree(const PIIntrospectionContainersType & ti, ullong cnt) {
p->containerFree(tn, cnt); p->containerFree(ti, cnt);
} }
void PIIntrospectionContainersInterface::containerUsed(const char * tn, ullong cnt) { void PIIntrospectionContainersInterface::containerUsed(const PIIntrospectionContainersType & ti, ullong cnt) {
p->containerUsed(tn, cnt); p->containerUsed(ti, cnt);
} }
void PIIntrospectionContainersInterface::containerUnused(const char * tn, ullong cnt) { void PIIntrospectionContainersInterface::containerUnused(const PIIntrospectionContainersType & ti, ullong cnt) {
p->containerUnused(tn, cnt); p->containerUnused(ti, cnt);
} }
#endif #endif

View File

@@ -20,27 +20,48 @@
#ifndef PIINTROSPECTION_CONTAINERS_H #ifndef PIINTROSPECTION_CONTAINERS_H
#define PIINTROSPECTION_CONTAINERS_H #define PIINTROSPECTION_CONTAINERS_H
#include "pibase.h"
struct PIP_EXPORT PIIntrospectionContainersType {
~PIIntrospectionContainersType();
void finish();
uint id = 0;
const char * name = nullptr;
const char * demangled = "?";
bool inited = false;
bool has_demangled = false;
};
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "piintrospection_base.h" #include "piintrospection_base.h"
class PIIntrospectionContainers; class PIIntrospectionContainers;
#define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())//(PIIntrospectionContainersInterface::instance()) template<typename T>
class PIIntrospectionContainersTypeInfo {
public:
static const PIIntrospectionContainersType & get() {
static PIIntrospectionContainersType ret = create();
return ret;
}
private:
static PIIntrospectionContainersType create() {
PIIntrospectionContainersType ret;
ret.name = __PIP_TYPENAME__(T);
ret.finish();
return ret;
}
};
#ifdef CC_GCC #define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())
# include <typeinfo>
# define _PIIS_TYPENAME_(t) typeid(t).name()
#else
# define _PIIS_TYPENAME_(t) ""
#endif
# define PIINTROSPECTION_CONTAINER_NEW(t, isz) PIINTROSPECTION_CONTAINERS->containerNew (_PIIS_TYPENAME_(t), isz); # define PIINTROSPECTION_CONTAINER_NEW(t, isz) PIINTROSPECTION_CONTAINERS->containerNew (PIIntrospectionContainersTypeInfo<t>::get(), isz);
# define PIINTROSPECTION_CONTAINER_DELETE(t) PIINTROSPECTION_CONTAINERS->containerDelete(_PIIS_TYPENAME_(t)); # define PIINTROSPECTION_CONTAINER_DELETE(t) PIINTROSPECTION_CONTAINERS->containerDelete(PIIntrospectionContainersTypeInfo<t>::get());
# define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt) PIINTROSPECTION_CONTAINERS->containerAlloc (_PIIS_TYPENAME_(t), cnt); # define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt) PIINTROSPECTION_CONTAINERS->containerAlloc (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_FREE(t, cnt) PIINTROSPECTION_CONTAINERS->containerFree (_PIIS_TYPENAME_(t), cnt); # define PIINTROSPECTION_CONTAINER_FREE(t, cnt) PIINTROSPECTION_CONTAINERS->containerFree (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_USED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUsed (_PIIS_TYPENAME_(t), cnt); # define PIINTROSPECTION_CONTAINER_USED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUsed (PIIntrospectionContainersTypeInfo<t>::get(), cnt);
# define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUnused(_PIIS_TYPENAME_(t), cnt); # define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUnused(PIIntrospectionContainersTypeInfo<t>::get(), cnt);
class PIP_EXPORT PIIntrospectionContainersInterface { class PIP_EXPORT PIIntrospectionContainersInterface {
@@ -49,12 +70,12 @@ class PIP_EXPORT PIIntrospectionContainersInterface {
public: public:
__PIINTROSPECTION_SINGLETON_H__(Containers) __PIINTROSPECTION_SINGLETON_H__(Containers)
void containerNew (const char * tn, uint isz); void containerNew (const PIIntrospectionContainersType & ti, uint isz);
void containerDelete(const char * tn); void containerDelete(const PIIntrospectionContainersType & ti);
void containerAlloc (const char * tn, ullong cnt); void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt);
void containerFree (const char * tn, ullong cnt); void containerFree (const PIIntrospectionContainersType & ti, ullong cnt);
void containerUsed (const char * tn, ullong cnt); void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt);
void containerUnused(const char * tn, ullong cnt); void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt);
PIIntrospectionContainers * p; PIIntrospectionContainers * p;
private: private:

View File

@@ -18,38 +18,23 @@
*/ */
#include "piintrospection_containers_p.h" #include "piintrospection_containers_p.h"
#include "piintrospection_containers.h"
#include <stdio.h> #include <stdio.h>
#ifdef CC_GCC
# include <cxxabi.h>
const PIString demangle(const char * name) {
int status = -4;
char * res = abi::__cxa_demangle(name, NULL, NULL, &status);
PIString ret((status == 0) ? res : name);
free(res);
return ret;
}
#else
const PIString demangle(const char * name) {return PIString(name);}
#endif
PIIntrospectionContainers::PIIntrospectionContainers() { PIIntrospectionContainers::PIIntrospectionContainers() {
//printf("PIIntrospectionContainers %p\n", this); //printf("PIIntrospectionContainers %p\n", this);
} }
void PIIntrospectionContainers::containerNew(const char * tn, uint isz) { void PIIntrospectionContainers::containerNew(const PIIntrospectionContainersType & ti, uint isz) {
uint id = typeID(tn); PISpinlockLocker _ml(mutex);
PIMutexLocker _ml(mutex);
//printf("containerNew lock\n"); //printf("containerNew lock\n");
std::string & n(typenames[id]); PIIntrospectionContainersType & t(types[ti.id]);
_Type & d(data[id]); _Type & d(data[ti.id]);
if (n.empty()) { if (!t.inited) {
n = tn; t = ti;
d.id = id; d.id = ti.id;
d.item_size = isz; d.item_size = isz;
} }
d.count++; d.count++;
@@ -57,49 +42,41 @@ void PIIntrospectionContainers::containerNew(const char * tn, uint isz) {
} }
void PIIntrospectionContainers::containerDelete(const char * tn) { void PIIntrospectionContainers::containerDelete(const PIIntrospectionContainersType & ti) {
PIMutexLocker _ml(mutex); PISpinlockLocker _ml(mutex);
data[typeID(tn)].count--; data[ti.id].count--;
} }
void PIIntrospectionContainers::containerAlloc(const char * tn, ullong cnt) { void PIIntrospectionContainers::containerAlloc(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf(" alloc %s %d\n", tn, cnt); //printf(" alloc %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PIMutexLocker _ml(mutex); PISpinlockLocker _ml(mutex);
data[typeID(tn)].allocated += cnt; data[ti.id].allocated += cnt;
} }
void PIIntrospectionContainers::containerFree(const char * tn, ullong cnt) { void PIIntrospectionContainers::containerFree(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf(" free %s %d\n", tn, cnt); //printf(" free %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PIMutexLocker _ml(mutex); PISpinlockLocker _ml(mutex);
data[typeID(tn)].allocated -= cnt; data[ti.id].allocated -= cnt;
} }
void PIIntrospectionContainers::containerUsed(const char * tn, ullong cnt) { void PIIntrospectionContainers::containerUsed(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf(" used %s %d\n", tn, cnt); //printf(" used %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PIMutexLocker _ml(mutex); PISpinlockLocker _ml(mutex);
data[typeID(tn)].used += cnt; data[ti.id].used += cnt;
} }
void PIIntrospectionContainers::containerUnused(const char * tn, ullong cnt) { void PIIntrospectionContainers::containerUnused(const PIIntrospectionContainersType & ti, ullong cnt) {
//printf("unused %s %d\n", tn, cnt); //printf("unused %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PIMutexLocker _ml(mutex); PISpinlockLocker _ml(mutex);
data[typeID(tn)].used -= cnt; data[ti.id].used -= cnt;
}
uint PIIntrospectionContainers::typeID(const char * tn) {
if (!tn) return 0u;
size_t l = strlen(tn);
if (l == 0) return 0u;
return piHashData((const uchar*)tn, int(l));
} }
@@ -107,15 +84,15 @@ PIVector<PIIntrospectionContainers::TypeInfo> PIIntrospectionContainers::getInfo
PIVector<PIIntrospectionContainers::TypeInfo> ret; PIVector<PIIntrospectionContainers::TypeInfo> ret;
mutex.lock(); mutex.lock();
std::map<uint, PIIntrospectionContainers::_Type> d = data; std::map<uint, PIIntrospectionContainers::_Type> d = data;
std::map<uint, std::string> t = typenames; std::map<uint, PIIntrospectionContainersType> t = types;
mutex.unlock(); mutex.unlock();
ret.reserve(t.size()); ret.reserve(t.size());
for (typename std::map<uint, std::string>::const_iterator i = t.begin(); i != t.end(); ++i) { for (typename std::map<uint, PIIntrospectionContainersType>::const_iterator i = t.begin(); i != t.end(); ++i) {
ret.push_back(TypeInfo()); ret.push_back(TypeInfo());
TypeInfo & ti(ret.back()); TypeInfo & ti(ret.back());
_Type & _t(d[i->first]); _Type & _t(d[i->first]);
memcpy((void*)&ti, (const void*)&_t, sizeof(_t)); memcpy((void*)&ti, (const void*)&_t, sizeof(_t));
ti.name = demangle(i->second.c_str()); ti.name = PIStringAscii(i->second.demangled);
} }
return ret; return ret;
} }

View File

@@ -20,7 +20,7 @@
#ifndef PIINTROSPECTION_CONTAINERS_P_H #ifndef PIINTROSPECTION_CONTAINERS_P_H
#define PIINTROSPECTION_CONTAINERS_P_H #define PIINTROSPECTION_CONTAINERS_P_H
#include "pimutex.h" #include "pispinlock.h"
#include <map> #include <map>
#include <string> #include <string>
#include "picrc.h" #include "picrc.h"
@@ -32,14 +32,12 @@ public:
struct TypeInfo; struct TypeInfo;
void containerNew (const char * tn, uint isz); void containerNew (const PIIntrospectionContainersType & ti, uint isz);
void containerDelete(const char * tn); void containerDelete(const PIIntrospectionContainersType & ti);
void containerAlloc (const char * tn, ullong cnt); void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt);
void containerFree (const char * tn, ullong cnt); void containerFree (const PIIntrospectionContainersType & ti, ullong cnt);
void containerUsed (const char * tn, ullong cnt); void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt);
void containerUnused(const char * tn, ullong cnt); void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt);
uint typeID(const char * tn);
PIVector<TypeInfo> getInfo() const; PIVector<TypeInfo> getInfo() const;
@@ -63,8 +61,8 @@ public:
}; };
std::map<uint, _Type> data; std::map<uint, _Type> data;
std::map<uint, std::string> typenames; std::map<uint, PIIntrospectionContainersType> types;
mutable PIMutex mutex; mutable PISpinlock mutex;
}; };
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v); PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v);

View File

@@ -1,3 +1,9 @@
/*! \file piintrospection_server.h
* \ingroup Introspection
* \~\brief
* \~english Introspection server
* \~russian Сервер интроспекции
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module Introspection module
@@ -20,6 +26,15 @@
#ifndef PIINTROSPECTION_SERVER_H #ifndef PIINTROSPECTION_SERVER_H
#define PIINTROSPECTION_SERVER_H #define PIINTROSPECTION_SERVER_H
#ifdef DOXYGEN
//! \ingroup Introspection
//! \~english Start introspection server with name "name"
//! \~russian Запускает сервер интроспекции с именем "name"
# define PIINTROSPECTION_START(name)
#else
# if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) # if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#include "pipeer.h" #include "pipeer.h"
@@ -57,4 +72,6 @@ private:
# define PIINTROSPECTION_START(name) # define PIINTROSPECTION_START(name)
# endif # endif
#endif // DOXYGEN
#endif // PIINTROSPECTION_SERVER_H #endif // PIINTROSPECTION_SERVER_H

View File

@@ -66,7 +66,7 @@ PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() {
for (int i = 0; i < ao.size_s(); ++i) { for (int i = 0; i < ao.size_s(); ++i) {
ret[i].classname = PIStringAscii(ao[i]->className()); ret[i].classname = PIStringAscii(ao[i]->className());
ret[i].name = ao[i]->name(); ret[i].name = ao[i]->name();
ret[i].properties = ao[i]->properties(); //ret[i].properties = ao[i]->properties();
ret[i].parents = ao[i]->scopeList(); ret[i].parents = ao[i]->scopeList();
ao[i]->mutex_queue.lock(); ao[i]->mutex_queue.lock();
ret[i].queued_events = ao[i]->events_queue.size_s(); ret[i].queued_events = ao[i]->events_queue.size_s();

View File

@@ -791,7 +791,7 @@ void PIBinaryLog::configureFromVariantDevice(const PIPropertyStorage & d) {
} }
void PIBinaryLog::propertyChanged(const PIString &s) { void PIBinaryLog::propertyChanged(const char * s) {
default_id = property("defaultID").toInt(); default_id = property("defaultID").toInt();
rapid_start = property("rapidStart").toBool(); rapid_start = property("rapidStart").toBool();
play_mode = (PlayMode)property("playMode").toInt(); play_mode = (PlayMode)property("playMode").toInt();

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PIBinaryLog: public PIIODevice class PIP_EXPORT PIBinaryLog: public PIIODevice
{ {
PIIODEVICE(PIBinaryLog) PIIODEVICE(PIBinaryLog, "binlog")
public: public:
explicit PIBinaryLog(); explicit PIBinaryLog();
virtual ~PIBinaryLog(); virtual ~PIBinaryLog();
@@ -288,7 +288,6 @@ public:
static bool cutBinLog(const BinLogInfo & src, const PIString & dst, int from, int to); static bool cutBinLog(const BinLogInfo & src, const PIString & dst, int from, int to);
protected: protected:
PIString fullPathPrefix() const {return PIStringAscii("binlog");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;
@@ -297,7 +296,7 @@ protected:
int writeDevice(const void * data, int size) {return writeBinLog(default_id, data, size);} int writeDevice(const void * data, int size) {return writeBinLog(default_id, data, size);}
bool openDevice(); bool openDevice();
bool closeDevice(); bool closeDevice();
void propertyChanged(const PIString &); void propertyChanged(const char * s);
bool threadedRead(uchar *readed, int size); bool threadedRead(uchar *readed, int size);
void threadedReadTerminated() {pausemutex.unlock();} void threadedReadTerminated() {pausemutex.unlock();}
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;} DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PICAN: public PIIODevice class PIP_EXPORT PICAN: public PIIODevice
{ {
PIIODEVICE(PICAN) PIIODEVICE(PICAN, "can")
public: public:
explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICAN(); virtual ~PICAN();
@@ -45,7 +45,6 @@ protected:
bool closeDevice(); bool closeDevice();
int readDevice(void * read_to, int max_size); int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size); int writeDevice(const void * data, int max_size);
PIString fullPathPrefix() const {return PIStringAscii("can");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;

View File

@@ -45,17 +45,16 @@ extern "C" {
# include <sys/stat.h> # include <sys/stat.h>
#endif #endif
/*! \class PIDir
* \brief Local directory //! \class PIDir pidir.h
* //! \details
* \section PIDir_sec0 Synopsis //! \~english \section PIDir_sec0 Synopsis
* This class provide access to local file. You can manipulate //! \~russian \section PIDir_sec0 Краткий обзор
* binary content or use this class as text stream. To binary //! \~english
* access there are function \a read(), \a write(), and many //! This class provide access to local directory.
* \a writeBinary() functions. For write variables to file in //!
* their text representation threr are many "<<" operators. //! \~russian
* //!
*/
PIDir::PIDir(const PIString & dir) { PIDir::PIDir(const PIString & dir) {
@@ -115,6 +114,15 @@ PIString PIDir::absolutePath() const {
} }
//! \details
//! \~english
//! This function remove repeatedly separators and
//! resolve ".." in path. E.g. "/home/.//user/src/../.." will
//! become "/home". \n Returns reference to this %PIDir
//! \~russian
//! Этот метод удаляет повторяющиеся разделители и разрешает
//! "..". Например, путь "/home/.//user/src/../.." станет "/home". \n
//! Возвращает ссылку на этот %PIDir
PIDir & PIDir::cleanPath() { PIDir & PIDir::cleanPath() {
PIString p(path_); PIString p(path_);
if (p.isEmpty()) { if (p.isEmpty()) {
@@ -236,6 +244,14 @@ bool PIDir::make(bool withParents) {
} }
bool PIDir::rename(const PIString & new_name) {
if (!PIDir::rename(path(), new_name))
return false;
setDir(new_name);
return true;
}
#ifdef WINDOWS #ifdef WINDOWS
bool sort_compare(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) { bool sort_compare(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {
return strcoll(v0.path.data(), v1.path.data()) < 0; return strcoll(v0.path.data(), v1.path.data()) < 0;
@@ -243,6 +259,20 @@ bool sort_compare(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {
#endif #endif
//! \~\details
//! \~english
//! Scan this directory and returns all directories
//! and files in one list, sorted alphabetically. This list
//! contains also "." and ".." members. There are absolute
//! pathes in returned list.
//! \attention This function doesn`t scan content of inner
//! directories!
//! \~russian
//! Читает директорию и возвращает все директории и файлы
//! одним списком, сортированным по алфавиту. Список содержит
//! также "." и "..". Возвращаются абсолютные пути.
//! \attention Этот метод не читает содержимое директорий
//! рекурсивно!
PIVector<PIFile::FileInfo> PIDir::entries() { PIVector<PIFile::FileInfo> PIDir::entries() {
PIVector<PIFile::FileInfo> l; PIVector<PIFile::FileInfo> l;
if (!isExists()) return l; if (!isExists()) return l;
@@ -322,6 +352,18 @@ PIVector<PIFile::FileInfo> PIDir::entries() {
} }
//! \~\details
//! \~english
//! Scan this directory recursively and returns all
//! directories and files in one list, sorted alphabetically.
//! This list doesn`t contains "." and ".." members. There
//! are absolute pathes in returned list, and
//! files placed after directories in this list.
//! \~russian
//! Читает директорию рекурсивно и возвращает все директории и файлы
//! одним списком, сортированным по алфавиту. Список не содержит
//! "." и "..". Возвращаются абсолютные пути, причём файлы
//! располагаются после директорий.
PIVector<PIFile::FileInfo> PIDir::allEntries() { PIVector<PIFile::FileInfo> PIDir::allEntries() {
PIVector<PIFile::FileInfo> ret; PIVector<PIFile::FileInfo> ret;
PIVector<PIFile::FileInfo> dirs; PIVector<PIFile::FileInfo> dirs;

View File

@@ -29,93 +29,146 @@
#include "pifile.h" #include "pifile.h"
//! \ingroup IO
//! \~\brief
//! \~english Local directory.
//! \~russian Локальная директория.
class PIP_EXPORT PIDir class PIP_EXPORT PIDir
{ {
public: public:
//! Constructs directory with path "path" //! \~english Constructs directory with path "dir"
//! \~russian Создает директорию с путём "dir"
PIDir(const PIString & dir = PIString()); PIDir(const PIString & dir = PIString());
//! Constructs directory with "file" directory path "path" //! \~english Constructs directory with "file" directory path
//! \~russian Создает директорию с путём директории файла "file"
PIDir(const PIFile & file); PIDir(const PIFile & file);
//! Returns if this directory is exists //! \~english Returns if this directory exists
//! \~russian Возвращает существует ли эта директория
bool isExists() const {return PIDir::isExists(path());} bool isExists() const {return PIDir::isExists(path());}
//! Returns if path of this directory is absolute //! \~english Returns if path of this directory is absolute
//! \~russian Возвращает абсолютный ли путь у директории
bool isAbsolute() const; bool isAbsolute() const;
//! Returns if path of this directory is relative //! \~english Returns if path of this directory is relative
//! \~russian Возвращает относительный ли путь у директории
bool isRelative() const {return !isAbsolute();} bool isRelative() const {return !isAbsolute();}
//! Returns path of current reading directory. This path //! \~english Returns path of current reading directory. This path valid only while \a allEntries() functions
//! valid only while \a allEntries functions //! \~russian Возвращает путь текущей директории чтения. Этот путь действителен только во время выполнения метода \a allEntries()
const PIString & scanDir() const {return scan_;} const PIString & scanDir() const {return scan_;}
//! Returns path of this directory //! \~english Returns path of this directory
//! \~russian Возвращает путь директории
PIString path() const; PIString path() const;
//! Returns absolute path of this directory //! \~english Returns absolute path of this directory
//! \~russian Возвращает абсолютный путь директории
PIString absolutePath() const; PIString absolutePath() const;
/** \brief Simplify path of this directory //! \~english Simplify path of this directory
* \details This function remove repeatedly separators and //! \~russian Упрощает путь директории
* resolve ".." in path. E.g. "/home/.//peri4/src/../.." will
* become "/home" \n This function returns reference to this %PIDir */
PIDir & cleanPath(); PIDir & cleanPath();
//! Returns %PIDir with simplified path of this directory //! \~english Returns %PIDir with simplified path of this directory
//! \~russian Возвращает %PIDir с упрощённым путём директории
PIDir cleanedPath() const {PIDir d(path()); d.cleanPath(); return d;} PIDir cleanedPath() const {PIDir d(path()); d.cleanPath(); return d;}
//! Returns relative to this directory path "path" //! \~english Returns relative to this directory path "path"
//! \~russian Возвращает путь "path" относительно этой директории
PIString relative(const PIString & path) const; PIString relative(const PIString & path) const;
//! Set this directory path to simplified "path" //! \~english Set this directory path to simplified "path"
//! \~russian Устанавливает путь директории упрощённым "path"
PIDir & setDir(const PIString & path); PIDir & setDir(const PIString & path);
//! Set this directory path as current for application //! \~english Set this directory path as current for application
//! \~russian Устанавливает путь директории текущим путём приложения
bool setCurrent() {return PIDir::setCurrent(path());} bool setCurrent() {return PIDir::setCurrent(path());}
/** \brief Returns this directory content //! \~english Returns this directory content
* \details Scan this directory and returns all directories //! \~russian Возвращает содержимое этой директории
* and files in one list, sorted alphabetically. This list
* contains also "." and ".." members. There are absolute
* pathes in returned list.
* \attention This function doesn`t scan content of inner
* directories! */
PIVector<PIFile::FileInfo> entries(); PIVector<PIFile::FileInfo> entries();
/** \brief Returns all this directory content //! \~english Returns this directory content recursively
* \details Scan this directory recursively and returns all //! \~russian Возвращает содержимое этой директории рекурсивно
* directories and files in one list, sorted alphabetically.
* This list doesn`t contains "." and ".." members. There
* are absolute pathes in returned list, and
* files placed after directories in this list */
PIVector<PIFile::FileInfo> allEntries(); PIVector<PIFile::FileInfo> allEntries();
//! \~english Make this directory, recursively if "withParents"
//! \~russian Создаёт эту директорию, рекурсивно если "withParents"
bool make(bool withParents = true); bool make(bool withParents = true);
//! \~english Remove this directory
//! \~russian Удаляет эту директорию
bool remove() {return PIDir::remove(path());} bool remove() {return PIDir::remove(path());}
bool rename(const PIString & new_name) {if (!PIDir::rename(path(), new_name)) return false; setDir(new_name); return true;}
//! \~english Rename this directory
//! \~russian Переименовывает эту директорию
bool rename(const PIString & new_name);
//! \~english Change this directory to relative path "path"
//! \~russian Изменяет директорию на относительный путь "path"
PIDir & cd(const PIString & path); PIDir & cd(const PIString & path);
//! \~english Change this directory to parent
//! \~russian Изменяет директорию на родительскую
PIDir & up() {return cd("..");} PIDir & up() {return cd("..");}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator ==(const PIDir & d) const; bool operator ==(const PIDir & d) const;
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const PIDir & d) const {return !((*this) == d);} bool operator !=(const PIDir & d) const {return !((*this) == d);}
static const PIChar separator; static const PIChar separator;
//! \~english Returns current directory for application
//! \~russian Возвращает текущую директорию приложения
static PIDir current(); static PIDir current();
//! \~english Returns user home directory
//! \~russian Возвращает домашнюю директорию пользователя
static PIDir home(); static PIDir home();
//! \~english Returns temporary directory
//! \~russian Возвращает временную директорию
static PIDir temporary(); static PIDir temporary();
//! \~english Returns directory "path" content recursively
//! \~russian Возвращает содержимое директории "path" рекурсивно
static PIVector<PIFile::FileInfo> allEntries(const PIString & path); static PIVector<PIFile::FileInfo> allEntries(const PIString & path);
//! \~english Returns if directory "path" exists
//! \~russian Возвращает существует ли эта директория
static bool isExists(const PIString & path); static bool isExists(const PIString & path);
//! \~english Make directory "path", recursively if "withParents"
//! \~russian Создаёт директорию "path", рекурсивно если "withParents"
static bool make(const PIString & path, bool withParents = true); static bool make(const PIString & path, bool withParents = true);
//! \~english Remove directory "path"
//! \~russian Удаляет директорию "path"
static bool remove(const PIString & path) {return removeDir(path);} static bool remove(const PIString & path) {return removeDir(path);}
//! \~english Rename directory "path"
//! \~russian Переименовывает директорию "path"
static bool rename(const PIString & path, const PIString & new_name) {return PIDir::renameDir(path, new_name);} static bool rename(const PIString & path, const PIString & new_name) {return PIDir::renameDir(path, new_name);}
//! \~english Set path "path" as current for application
//! \~russian Устанавливает путь "path" текущим путём приложения
static bool setCurrent(const PIString & path); static bool setCurrent(const PIString & path);
//! \~english Set directory "dir" path as current for application
//! \~russian Устанавливает путь директории "dir" текущим путём приложения
static bool setCurrent(const PIDir & dir) {return setCurrent(dir.path());} static bool setCurrent(const PIDir & dir) {return setCurrent(dir.path());}
private: private:
@@ -133,6 +186,9 @@ inline bool operator >(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1
inline bool operator ==(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path == v1.path);} inline bool operator ==(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path == v1.path);}
inline bool operator !=(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path != v1.path);} inline bool operator !=(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path != v1.path);}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIDir & v) {s.setControl(0, true); s << "PIDir(\"" << v.path() << "\")"; s.restoreControl(); return s;} inline PICout operator <<(PICout s, const PIDir & v) {s.setControl(0, true); s << "PIDir(\"" << v.path() << "\")"; s.restoreControl(); return s;}

View File

@@ -21,6 +21,7 @@
#include "piconfig.h" #include "piconfig.h"
#include "pisysteminfo.h" #include "pisysteminfo.h"
#include "pipropertystorage.h" #include "pipropertystorage.h"
#include "piconstchars.h"
#ifdef QNX #ifdef QNX
# include <net/if.h> # include <net/if.h>
# include <net/if_dl.h> # include <net/if_dl.h>
@@ -919,10 +920,11 @@ bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
} }
void PIEthernet::propertyChanged(const PIString & name) { void PIEthernet::propertyChanged(const char * name) {
if (name.endsWith("Timeout")) applyTimeouts(); PIConstChars pn(name);
if (name == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL()); if (pn.endsWith("Timeout")) applyTimeouts();
if (name == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL()); if (pn == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL());
if (pn == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL());
} }
@@ -1001,24 +1003,23 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ci.index = -1; ci.index = -1;
ci.mtu = 1500; ci.mtu = 1500;
#ifdef WINDOWS #ifdef WINDOWS
PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0;
int ret = 0; int ret = 0;
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO); ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO))); PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO));
if (pAdapterInfo == 0) { if (!pAdapterInfo) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersInfo";
return il; return il;
} }
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); HeapFree(GetProcessHeap(), 0, pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen)); pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, ulOutBufLen);
if (pAdapterInfo == 0) { if (!pAdapterInfo) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersInfo";
return il; return il;
} }
} }
if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
pAdapter = pAdapterInfo; PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
while (pAdapter) { while (pAdapter) {
ci.name = PIString(pAdapter->AdapterName); ci.name = PIString(pAdapter->AdapterName);
ci.index = pAdapter->Index; ci.index = pAdapter->Index;
@@ -1031,8 +1032,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
IP_ADDR_STRING * as = &(pAdapter->IpAddressList); IP_ADDR_STRING * as = &(pAdapter->IpAddressList);
while (as) { while (as) {
// piCout << "[pAdapter]" << ci.name << PIString(as->IpAddress.String); // piCout << "[pAdapter]" << ci.name << PIString(as->IpAddress.String);
ci.address = PIString(as->IpAddress.String); ci.address = PIStringAscii(as->IpAddress.String);
ci.netmask = PIString(as->IpMask.String); ci.netmask = PIStringAscii(as->IpMask.String);
if (ci.address == "0.0.0.0") { if (ci.address == "0.0.0.0") {
as = as->Next; as = as->Next;
continue; continue;
@@ -1053,7 +1054,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
} }
} }
if (pAdapterInfo) if (pAdapterInfo)
HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); HeapFree(GetProcessHeap(), 0, pAdapterInfo);
#else #else
#ifdef MICRO_PIP #ifdef MICRO_PIP
#else #else
@@ -1213,10 +1214,16 @@ int PIEthernet::ethErrorCore() {
PIString PIEthernet::ethErrorString() { PIString PIEthernet::ethErrorString() {
#ifdef WINDOWS #ifdef WINDOWS
char * msg; char * msg = nullptr;
int err = WSAGetLastError(); int err = WSAGetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
return "code " + PIString::fromNumber(err) + " - " + PIString(msg); PIString ret = PIStringAscii("code ") + PIString::fromNumber(err) + PIStringAscii(" - ");
if (msg) {
ret += PIString::fromSystem(msg).trim();
LocalFree(msg);
} else
ret += '?';
return ret;
#else #else
return errorString(); return errorString();
#endif #endif

View File

@@ -38,7 +38,7 @@ class
class PIP_EXPORT PIEthernet: public PIIODevice class PIP_EXPORT PIEthernet: public PIIODevice
{ {
PIIODEVICE(PIEthernet) PIIODEVICE(PIEthernet, "eth")
friend class PIPeer; friend class PIPeer;
public: public:
@@ -201,44 +201,44 @@ public:
//! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them //! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {setProperty(PIStringAscii("parameters"), (int)parameters_);} void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {setProperty("parameters", (int)parameters_);}
//! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this //! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this
void setParameter(PIEthernet::Parameters parameter, bool on = true); void setParameter(PIEthernet::Parameters parameter, bool on = true);
//! Returns if parameter "parameter" is set //! Returns if parameter "parameter" is set
bool isParameterSet(PIEthernet::Parameters parameter) const {return ((PIFlags<PIEthernet::Parameters>)(property(PIStringAscii("parameters")).toInt()))[parameter];} bool isParameterSet(PIEthernet::Parameters parameter) const {return ((PIFlags<PIEthernet::Parameters>)(property("parameters").toInt()))[parameter];}
//! Returns parameters //! Returns parameters
PIFlags<PIEthernet::Parameters> parameters() const {return (PIFlags<PIEthernet::Parameters>)(property(PIStringAscii("parameters")).toInt());} PIFlags<PIEthernet::Parameters> parameters() const {return (PIFlags<PIEthernet::Parameters>)(property("parameters").toInt());}
//! Returns %PIEthernet type //! Returns %PIEthernet type
Type type() const {return (Type)(property(PIStringAscii("type")).toInt());} Type type() const {return (Type)(property("type").toInt());}
//! Returns read timeout //! Returns read timeout
double readTimeout() const {return property(PIStringAscii("readTimeout")).toDouble();} double readTimeout() const {return property("readTimeout").toDouble();}
//! Returns write timeout //! Returns write timeout
double writeTimeout() const {return property(PIStringAscii("writeTimeout")).toDouble();} double writeTimeout() const {return property("writeTimeout").toDouble();}
//! Set timeout for read //! Set timeout for read
void setReadTimeout(double ms) {setProperty(PIStringAscii("readTimeout"), ms);} void setReadTimeout(double ms) {setProperty("readTimeout", ms);}
//! Set timeout for write //! Set timeout for write
void setWriteTimeout(double ms) {setProperty(PIStringAscii("writeTimeout"), ms);} void setWriteTimeout(double ms) {setProperty("writeTimeout", ms);}
//! Returns TTL (Time To Live) //! Returns TTL (Time To Live)
int TTL() const {return property(PIStringAscii("TTL")).toInt();} int TTL() const {return property("TTL").toInt();}
//! Returns multicast TTL (Time To Live) //! Returns multicast TTL (Time To Live)
int multicastTTL() const {return property(PIStringAscii("MulticastTTL")).toInt();} int multicastTTL() const {return property("MulticastTTL").toInt();}
//! Set TTL (Time To Live), default is 64 //! Set TTL (Time To Live), default is 64
void setTTL(int ttl) {setProperty(PIStringAscii("TTL"), ttl);} void setTTL(int ttl) {setProperty("TTL", ttl);}
//! Set multicast TTL (Time To Live), default is 1 //! Set multicast TTL (Time To Live), default is 1
void setMulticastTTL(int ttl) {setProperty(PIStringAscii("MulticastTTL"), ttl);} void setMulticastTTL(int ttl) {setProperty("MulticastTTL", ttl);}
//! Join to multicast group with address "group". Use only for UDP //! Join to multicast group with address "group". Use only for UDP
@@ -462,9 +462,8 @@ public:
protected: protected:
explicit PIEthernet(int sock, PIString ip_port); explicit PIEthernet(int sock, PIString ip_port);
void propertyChanged(const PIString & name); void propertyChanged(const char * name);
PIString fullPathPrefix() const {return PIStringAscii("eth");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;
@@ -499,7 +498,7 @@ protected:
private: private:
EVENT_HANDLER1(void, clientDeleted, PIObject *, o); EVENT_HANDLER1(void, clientDeleted, PIObject *, o);
static void server_func(void * eth); static void server_func(void * eth);
void setType(Type t, bool reopen = true) {setProperty(PIStringAscii("type"), (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}} void setType(Type t, bool reopen = true) {setProperty("type", (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}}
static int ethErrorCore(); static int ethErrorCore();
static PIString ethErrorString(); static PIString ethErrorString();

View File

@@ -69,25 +69,44 @@
# define _stat_link_ lstat64 # define _stat_link_ lstat64
#endif #endif
/*! \class PIFile
* \brief Local file //! \class PIFile pifile.h
* //! \details
* \section PIFile_sec0 Synopsis //! \~english \section PIFile_sec0 Synopsis
* This class provide access to local file. You can manipulate //! \~russian \section PIFile_sec0 Краткий обзор
* binary content or use this class as text stream. To binary //! \~english
* access there are function \a read(), \a write(), and many //!
* \a writeBinary() functions. For write variables to file in //! This class provide access to local file. You can manipulate
* their text representation threr are many "<<" operators. //! binary content or use this class as text stream. To binary
* //! access there are function \a read(), \a write(), and many
* \section PIFile_sec1 Position //! \a writeBinary() functions. For write and read variables to file in
* Each opened file has a read/write position - logical position //! their text representation there are many "<<" and ">>" operators.
* in the file content you read from or you write to. You can //!
* find out current position with function \a pos(). Function //! \~russian
* \a seek(llong position) move position to position "position", //! Этот класс предоставляет доступ к локальному файлу. Можно
* \a seekToBegin() move position to the begin of file, //! работать на байтовом уровне, либо использовать его как
* \a seekToEnd() move position to the end of file. //! текстовый поток. Для байтового доступа используются методы
* //! \a read(), \a write(), и много \a writeBinary() методов.
*/ //! Для записи и чтения переменных в текстовом представлении
//! используются операторы "<<" и ">>".
//!
//! \~english \section PIFile_sec1 Position
//! \~russian \section PIFile_sec1 Позиция
//! \~english
//! Each opened file has a read/write position - logical position
//! in the file content you read from or you write to. You can
//! find out current position with function \a pos(). Function
//! \a seek(llong position) move position to position "position",
//! \a seekToBegin() move position to the begin of file,
//! \a seekToEnd() move position to the end of file.
//!
//! \~russian
//! Каждый файл имеет позицию чтения/записи - логическое положение
//! в содержимом файла, откуда производится чтение или запись.
//! Узнать текущую позицию можно с помощью метода \a pos().
//! Метод \a seek(llong position) перемещает позицию на указанную,
//! \a seekToBegin() перемещает её в начало файла, а \a seekToEnd() - в конец.
//!
REGISTER_DEVICE(PIFile) REGISTER_DEVICE(PIFile)
@@ -614,7 +633,7 @@ int PIFile::writeDevice(const void * data, int max_size) {
PIFile &PIFile::operator <<(const PIString & v) { PIFile &PIFile::operator <<(const PIString & v) {
if (canWrite() && PRIVATE->fd != 0) if (canWrite() && v.isNotEmpty() && PRIVATE->fd != 0)
*this << v.toCharset(defaultCharset()); *this << v.toCharset(defaultCharset());
return *this; return *this;
} }

View File

@@ -30,30 +30,62 @@
#include "pipropertystorage.h" #include "pipropertystorage.h"
//! \ingroup IO
//! \~\brief
//! \~english Local file.
//! \~russian Локальный файл.
class PIP_EXPORT PIFile: public PIIODevice class PIP_EXPORT PIFile: public PIIODevice
{ {
PIIODEVICE(PIFile) PIIODEVICE(PIFile, "file")
public: public:
//! Constructs an empty file //! \~english Constructs file with empty path
//! \~russian Создает файл с пустым путём
explicit PIFile(); explicit PIFile();
//! \~english Constructs a file with path "path" and open mode "mode". Open if "path" is not empty
//! \~russian Создает файл с путём "path" и режимом открытия "mode". Открывает если "path" не пустой
explicit PIFile(const PIString & path, DeviceMode mode = ReadWrite);
virtual ~PIFile();
//! \ingroup IO
//! \~\brief
//! \~english Local file or directory information.
//! \~russian Информация о локальном файле или директории.
struct PIP_EXPORT FileInfo { struct PIP_EXPORT FileInfo {
//! \~english Constructs %FileInfo with path "path_". No information gathered
//! \~russian Создает %FileInfo с путём "path_". Информация не собирается
FileInfo(const PIString & path_ = PIString()) {path = path_; size = 0; id_group = id_user = 0;} FileInfo(const PIString & path_ = PIString()) {path = path_; size = 0; id_group = id_user = 0;}
//! \~english Type flags
//! \~russian Флаги типа
enum Flag { enum Flag {
File = 0x01, File /*! \~english File \~russian Файл */ = 0x01,
Dir = 0x02, Dir /*! \~english Directory \~russian Директория */ = 0x02,
Dot = 0x04, Dot /*! \~english '.', current directory \~russian '.', текущая директория */ = 0x04,
DotDot = 0x08, DotDot /*! \~english '..', parent directory \~russian '..', родительская директория */ = 0x08,
SymbolicLink = 0x10, SymbolicLink /*! \~english Symbolic link \~russian Символическая ссылка */ = 0x10,
Hidden = 0x20 Hidden /*! \~english Hidden \~russian Скрытый */ = 0x20
}; };
typedef PIFlags<FileInfo::Flag> Flags; typedef PIFlags<FileInfo::Flag> Flags;
//! \ingroup IO
//! \~\brief
//! \~english Local file or directory permissions.
//! \~russian Разрешения локального файла или директории.
struct PIP_EXPORT Permissions { struct PIP_EXPORT Permissions {
Permissions(uchar r = 0): raw(r) {} Permissions(uchar r = 0): raw(r) {}
Permissions(bool r, bool w, bool e): raw(0) {read = r; write = w; exec = e;} Permissions(bool r, bool w, bool e): raw(0) {read = r; write = w; exec = e;}
//! \~english Returns as string (from "---" to "rwx")
//! \~russian Возвращает как строку (от "---" до "rwx")
PIString toString() const {return PIString(read ? "r" : "-") + PIString(write ? "w" : "-") + PIString(exec ? "x" : "-");} PIString toString() const {return PIString(read ? "r" : "-") + PIString(write ? "w" : "-") + PIString(exec ? "x" : "-");}
//! \~english Convertion to \c int
//! \~russian Преобразование в \c int
operator int() const {return raw;} operator int() const {return raw;}
Permissions & operator =(int v) {raw = v; return *this;} Permissions & operator =(int v) {raw = v; return *this;}
union { union {
@@ -66,175 +98,321 @@ public:
}; };
}; };
//! \~english Path
//! \~russian Путь
PIString path; PIString path;
//! \~english File size
//! \~russian Размер файла
llong size; llong size;
//! \~english Last access time
//! \~russian Время последнего доступа
PIDateTime time_access; PIDateTime time_access;
//! \~english Last modification time
//! \~russian Время последнего изменения
PIDateTime time_modification; PIDateTime time_modification;
//! \~english Flags
//! \~russian Флаги
Flags flags; Flags flags;
//! \~english User ID
//! \~russian ID пользователя
uint id_user; uint id_user;
//! \~english Group ID
//! \~russian ID группы
uint id_group; uint id_group;
//! \~english Permissions for user
//! \~russian Разрешения для пользователя
Permissions perm_user; Permissions perm_user;
//! \~english Permissions for group
//! \~russian Разрешения для группы
Permissions perm_group; Permissions perm_group;
//! \~english Permissions for other
//! \~russian Разрешения для остальных
Permissions perm_other; Permissions perm_other;
//! \~english Returns name, without directory
//! \~russian Возвращает имя, без директории
PIString name() const; PIString name() const;
//! \~english Returns base name, without directory and extension
//! \~russian Возвращает базовое имя, без директории и расширения
PIString baseName() const; PIString baseName() const;
//! \~english Returns extension
//! \~russian Возвращает расширение
PIString extension() const; PIString extension() const;
//! \~english Returns directory
//! \~russian Возвращает директорию
PIString dir() const; PIString dir() const;
//! \~english Returns if it`s directory
//! \~russian Возвращает директория ли это
bool isDir() const {return flags[Dir];} bool isDir() const {return flags[Dir];}
//! \~english Returns if it`s file
//! \~russian Возвращает файл ли это
bool isFile() const {return flags[File];} bool isFile() const {return flags[File];}
//! \~english Returns if it`s symbolic link
//! \~russian Возвращает символическая ссылка ли это
bool isSymbolicLink() const {return flags[SymbolicLink];} bool isSymbolicLink() const {return flags[SymbolicLink];}
//! \~english Returns if Hidden flag set
//! \~russian Возвращает установлен ли флаг Hidden
bool isHidden() const {return flags[Hidden];} bool isHidden() const {return flags[Hidden];}
}; };
//! Constructs a file with path "path" and open mode "mode"
//! If "path" is not empty then open file
explicit PIFile(const PIString & path, DeviceMode mode = ReadWrite);
//! \~english Open temporary file with open mode "mode"
//! Open temporary file with open mode "mode" //! \~russian Открывает временный файл с режимом открытия "mode"
bool openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PIFile(); //! \~english Immediate write all buffered data to disk
//! \~russian Немедленно записывает все буферизированные данные на диск
//! Immediate write all buffered data to disk
void flush(); void flush();
//! Move read/write position to "position" //! \~english Move read/write position to "position"
//! \~russian Перемещает позицию чтения/записи на "position"
void seek(llong position); void seek(llong position);
//! Move read/write position to the begin of the file //! \~english Move read/write position to the begin of the file
//! \~russian Перемещает позицию чтения/записи на начало файла
void seekToBegin(); void seekToBegin();
//! Move read/write position to the end of the file //! \~english Move read/write position to the end of the file
//! \~russian Перемещает позицию чтения/записи на конец файла
void seekToEnd(); void seekToEnd();
//! Move read/write position to text line number "line" //! \~english Move read/write position to text line number "line" beginning
//! \~russian Перемещает позицию чтения/записи на начало текстовой строки номер "line"
void seekToLine(llong line); void seekToLine(llong line);
//! Skip "bytes" bytes (move position next to "bytes" bytes) //! \~english Skip "bytes" bytes (move position next to "bytes" bytes)
//! \~russian Пропускает "bytes" байт (перемещает позицию на "bytes" байт вперёд)
void skip(llong bytes); void skip(llong bytes);
//! Read one char and return it //! \~english Read one char and return it
//! \~russian Читает один байт и возвращает его
char readChar(); char readChar();
//! Read one text line and return it //! \~english Read one text line and return it
//! \~russian Читает одну текстовую строку и возвращает её
PIString readLine(); PIString readLine();
//! Read all file content to "data" and return readed bytes count. Position leaved unchanged //! \~english Read all file content to "data" and return readed bytes count. Position leaved unchanged
//! \~russian Читает всё содержимое файла в "data" и возвращает количество прочитанных байт. Позиция остаётся неизменной
llong readAll(void * data); llong readAll(void * data);
//! Read all file content to byte array and return it. Position leaved unchanged //! \~english Read all file content to byte array and return it. Position leaved unchanged
//! \~russian Читает всё содержимое файла и возвращает его как массив байтов. Позиция остаётся неизменной
PIByteArray readAll(bool forceRead = false); PIByteArray readAll(bool forceRead = false);
//! Set file path to "path" and reopen file if need //! \~english Set file path to "path" and reopen file if need
//! \~russian Устанавливает путь файла на "path" и переоткрывает его при необходимости
void setPath(const PIString & path); void setPath(const PIString & path);
//! Returns file size //! \~english Returns file size in bytes
//! \~russian Возвращает размер файла в байтах
llong size() const; llong size() const;
//! Returns read/write position //! \~english Returns read/write position
//! \~russian Возвращает позицию чтения/записи
llong pos() const; llong pos() const;
//! Returns if position is at the end of file //! \~english Returns if position is at the end of file
//! \~russian Возвращает достигнут ли конец файла
bool isEnd() const; bool isEnd() const;
//! Returns if file is empty //! \~english Returns if file is empty
//! \~russian Возвращает пустой ли файл
bool isEmpty() const {return (size() <= 0);} bool isEmpty() const {return (size() <= 0);}
//! Returns FileInfo of current file //! \~english Returns \a PIFile::FileInfo of current file
//! \~russian Возвращает \a PIFile::FileInfo текущего файла
FileInfo fileInfo() const {return fileInfo(path());} FileInfo fileInfo() const {return fileInfo(path());}
//! Returns float numbers write precision //! \~english Returns float numbers write precision
//! \~russian Возвращает точность записи чисел с плавающей точкой
int precision() const {return prec_;} int precision() const {return prec_;}
//! Set float numbers write precision to "prec_" digits //! \~english Set float numbers write precision to "prec_" digits
//! \~russian Устанавливает точность записи чисел с плавающей точкой
void setPrecision(int prec); void setPrecision(int prec);
//! \~english Write size and content of "v" (serialize)
//! \~russian Пишет в файл размер и содержимое "v" (сериализация)
PIFile & put(const PIByteArray & v); PIFile & put(const PIByteArray & v);
//! \~english Read size of byte array and it content (deserialize)
//! \~russian Читает из файла размер байтового массива и его содержимое (десериализация)
PIByteArray get(); PIByteArray get();
//! Write to file binary content of "v" //! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const llong v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const llong v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const ullong v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const ullong v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;}
//! Write to file binary content of "v"
//! \~english Write to file binary content of "v"
//! \~russian Пишет в файл байтовое содержимое "v"
PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;}
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(const char v); PIFile & operator <<(const char v);
//! Write to file string "v"
//! \~english Write to file string "v"
//! \~russian Пишет в файл строку "v"
PIFile & operator <<(const PIString & v); PIFile & operator <<(const PIString & v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(const PIByteArray & v); PIFile & operator <<(const PIByteArray & v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(short v); PIFile & operator <<(short v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(int v); PIFile & operator <<(int v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(long v); PIFile & operator <<(long v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(llong v); PIFile & operator <<(llong v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(uchar v); PIFile & operator <<(uchar v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(ushort v); PIFile & operator <<(ushort v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(uint v); PIFile & operator <<(uint v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(ulong v); PIFile & operator <<(ulong v);
//! Write to file text representation of "v"
//! \~english Write to file text representation of "v"
//! \~russian Пишет в файл текстовое представление "v"
PIFile & operator <<(ullong v); PIFile & operator <<(ullong v);
//! Write to file text representation of "v" with precision \a precision()
//! \~english Write to file text representation of "v" with precision \a precision()
//! \~russian Пишет в файл текстовое представление "v" с точностью \a precision()
PIFile & operator <<(float v); PIFile & operator <<(float v);
//! Write to file text representation of "v" with precision \a precision()
//! \~english Write to file text representation of "v" with precision \a precision()
//! \~russian Пишет в файл текстовое представление "v" с точностью \a precision()
PIFile & operator <<(double v); PIFile & operator <<(double v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(char & v); PIFile & operator >>(char & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(short & v); PIFile & operator >>(short & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(int & v); PIFile & operator >>(int & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(long & v); PIFile & operator >>(long & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(llong & v); PIFile & operator >>(llong & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(uchar & v); PIFile & operator >>(uchar & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(ushort & v); PIFile & operator >>(ushort & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(uint & v); PIFile & operator >>(uint & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(ulong & v); PIFile & operator >>(ulong & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(ullong & v); PIFile & operator >>(ullong & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(float & v); PIFile & operator >>(float & v);
//! Read from file text representation of "v"
//! \~english Read from file text representation of "v"
//! \~russian Читает из файла текстовое представление "v"
PIFile & operator >>(double & v); PIFile & operator >>(double & v);
EVENT_HANDLER(void, clear); EVENT_HANDLER(void, clear);
@@ -242,44 +420,56 @@ public:
EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);} EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);}
EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill); EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill);
//! //! \~english
//! \~russian
static const char * defaultCharset(); static const char * defaultCharset();
//! //! \~english
//! \~russian
static void setDefaultCharset(const char * c); static void setDefaultCharset(const char * c);
//! Returns if file with path "path" does exists //! \~english Returns if file with path "path" exists
//! \~russian Возвращает существует ли файл с путём "path"
static bool isExists(const PIString & path); static bool isExists(const PIString & path);
//! Remove file with path "path" and returns if remove was successful //! \~english Remove file with path "path" and returns if remove successful
//! \~russian Удаляет файл с путём "path" и возвращает успешность операции
static bool remove(const PIString & path); static bool remove(const PIString & path);
//! Rename file with path "from" to path "to" and returns if rename was successful //! \~english Rename file with path "from" to path "to" and returns if rename successful
//! \~russian Переименовывает файл с путём "path" на "to" и возвращает успешность операции
static bool rename(const PIString & from, const PIString & to); static bool rename(const PIString & from, const PIString & to);
//! Returns FileInfo of file or dir with path "path" //! \~english Returns \a PIFile::FileInfo of file or dir with path "path"
//! \~russian Возвращает \a PIFile::FileInfo файла или директории с путём "path"
static FileInfo fileInfo(const PIString & path); static FileInfo fileInfo(const PIString & path);
//! Apply "info" parameters to file or dir with path "path" //! \~english Apply "info" parameters to file or dir with path "path"
//! \~russian Применяет параметры "info" к файлу или директории с путём "path"
static bool applyFileInfo(const PIString & path, const FileInfo & info); static bool applyFileInfo(const PIString & path, const FileInfo & info);
//! Apply "info" parameters to file or dir with path "info".path //! \~english Apply "info" parameters to file or dir with path "info".path
//! \~russian Применяет параметры "info" к файлу или директории с путём "info".path
static bool applyFileInfo(const FileInfo & info) {return applyFileInfo(info.path, info);} static bool applyFileInfo(const FileInfo & info) {return applyFileInfo(info.path, info);}
//! \handlers //! \handlers
//! \{ //! \{
//! \fn void clear() //! \fn void clear()
//! \brief Clear content of file //! \~english Clear content of file
//! \~russian Очищает содержимое файла
//! \fn void resize(llong new_size) //! \fn void resize(llong new_size)
//! \brief Resize file to "new_size" with "fill" filling //! \~english Resize file to "new_size" with null-byte fill
//! \~russian Изменяет размер файла на "new_size" с заполнением нулевыми байтами
//! \fn void resize(llong new_size, uchar fill) //! \fn void resize(llong new_size, uchar fill)
//! \brief Resize file to "new_size" with "fill" filling //! \~english Resize file to "new_size" with "fill" fill
//! \~russian Изменяет размер файла на "new_size" с заполнением байтами "fill"
//! \fn void remove() //! \fn void remove()
//! \brief Remove file //! \~english Remove file
//! \~russian Удаляет файл
//! \} //! \}
//! \ioparams //! \ioparams
@@ -289,7 +479,6 @@ public:
//! \} //! \}
protected: protected:
PIString fullPathPrefix() const {return PIStringAscii("file");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;
@@ -311,6 +500,10 @@ private:
}; };
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIFile::FileInfo & v) { inline PICout operator <<(PICout s, const PIFile::FileInfo & v) {
s.setControl(0, true); s.setControl(0, true);
s << "FileInfo(\"" << v.path << "\", " << PIString::readableSize(v.size) << ", " s << "FileInfo(\"" << v.path << "\", " << PIString::readableSize(v.size) << ", "
@@ -322,9 +515,17 @@ inline PICout operator <<(PICout s, const PIFile::FileInfo & v) {
} }
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const PIFile::FileInfo & v) {s << v.path << v.size << v.time_access << v.time_modification << inline PIByteArray & operator <<(PIByteArray & s, const PIFile::FileInfo & v) {s << v.path << v.size << v.time_access << v.time_modification <<
(int)v.flags << v.id_user << v.id_group << v.perm_user.raw << v.perm_group.raw << v.perm_other.raw; return s;} (int)v.flags << v.id_user << v.id_group << v.perm_user.raw << v.perm_group.raw << v.perm_other.raw; return s;}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, PIFile::FileInfo & v) {s >> v.path >> v.size >> v.time_access >> v.time_modification >> inline PIByteArray & operator >>(PIByteArray & s, PIFile::FileInfo & v) {s >> v.path >> v.size >> v.time_access >> v.time_modification >>
*(int*)(&(v.flags)) >> v.id_user >> v.id_group >> v.perm_user.raw >> v.perm_group.raw >> v.perm_other.raw; return s;} *(int*)(&(v.flags)) >> v.id_user >> v.id_group >> v.perm_user.raw >> v.perm_group.raw >> v.perm_other.raw; return s;}
#endif // PIFILE_H #endif // PIFILE_H

View File

@@ -28,25 +28,40 @@
#endif #endif
/*! \class PIGPIO //! \class PIGPIO pigpio.h
* \brief GPIO support //! \~english \section PIGPIO_sec0 Synopsis
* //! \~russian \section PIGPIO_sec0 Краткий обзор
* \section PIGPIO_sec0 Synopsis //! \~english
* This class provide initialize, get/set and watch functions for GPIO. //! This class provide initialize, get/set and watch functions for GPIO.
* //!
* Currently supported only \"/sys/class/gpio\" mechanism on Linux. //! This class should be used with \a PIGPIO::instance() singleton.
* //!
* This class should be used with \a PIGPIO::instance() singleton. //! Currently supported only "/sys/class/gpio" mechanism on Linux.
* //!
* //!
* //! \~russian
* \section PIGPIO_sec1 API //! Этот класс предоставляет инициализацию, установку, чтение и наблюдение
* There are several function to directly read or write pin states. //! за GPIO.
* //!
* Also you can start %PIGPIO as thread to watch pin states and receive //! Этот класс используется только через синглтон \a PIGPIO::instance().
* \a pinChanged() event. //!
* //! Сейчас поддерживается только "/sys/class/gpio" для Linux.
*/ //!
//!
//! \~\section PIGPIO_sec1 API
//! \~english
//! There are several function to directly read or write pin states.
//!
//! Also you can start %PIGPIO as thread to watch pin states and receive
//! \a pinChanged() event.
//!
//!
//! \~russian
//! Имеется несколько методов для прямой записи и чтения состояний пинов.
//!
//! Также можно запустить %PIGPIO как поток для наблюдения за пинами и
//! принимать события \a pinChanged().
//!
PIGPIO::PIGPIO(): PIThread() { PIGPIO::PIGPIO(): PIThread() {
@@ -155,20 +170,26 @@ void PIGPIO::begin() {
void PIGPIO::run() { void PIGPIO::run() {
PIMutexLocker ml(mutex); mutex.lock();
if (watch_state.isEmpty()) return; if (watch_state.isEmpty()) {
PIVector<int> ids = watch_state.keys(); mutex.unlock();
for(int i = 0; i < ids.size_s(); i++) { return;
GPIOData & g(gpio_[ids[i]]); }
if (g.num != -1 && !g.name.isEmpty()) { PIVector<PIPair<int, bool>> changed;
auto it = watch_state.makeIterator();
while (it.next()) {
GPIOData & g(gpio_[it.key()]);
if (g.num == -1 || g.name.isEmpty()) continue;
bool v = getPinState(g.num); bool v = getPinState(g.num);
//piCoutObj << "*** pin state ***" << ids[i] << "=" << v; //piCoutObj << "*** pin state ***" << ids[i] << "=" << v;
if (watch_state[g.num] != v) { if (watch_state[g.num] != v) {
watch_state[g.num] = v; watch_state[g.num] = v;
pinChanged(g.num, v); changed.push_back({g.num, v});
}
} }
} }
mutex.unlock();
for (const auto & i: changed)
pinChanged(i.first, i.second);
} }
@@ -199,6 +220,7 @@ void PIGPIO::initPin(int gpio_num, Direction dir) {
} }
g.dir = dir; g.dir = dir;
int ret = 0; int ret = 0;
NO_UNUSED(ret);
switch(dir) { switch(dir) {
case In: case In:
ret = system(("echo in >> /sys/class/gpio/" + g.name + "/direction").dataAscii()); ret = system(("echo in >> /sys/class/gpio/" + g.name + "/direction").dataAscii());
@@ -218,6 +240,7 @@ void PIGPIO::pinSet(int gpio_num, bool value) {
PIMutexLocker ml(mutex); PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]); GPIOData & g(gpio_[gpio_num]);
int ret = 0; int ret = 0;
NO_UNUSED(ret);
if (g.fd != -1) { if (g.fd != -1) {
if (value) ret = ::write(g.fd, "1", 1); if (value) ret = ::write(g.fd, "1", 1);
else ret = ::write(g.fd, "0", 1); else ret = ::write(g.fd, "0", 1);
@@ -233,6 +256,14 @@ bool PIGPIO::pinState(int gpio_num) {
} }
//! \~\details
//! \~english
//! This function doesn`t affect thread state!
//! Pins watching starts only with \a PIThread::start() function
//!
//! \~russian
//! Этот метод не меняет состояние потока наблюдения!
//! Наблюдение за пинами начинается методом \a PIThread::start()
void PIGPIO::pinBeginWatch(int gpio_num) { void PIGPIO::pinBeginWatch(int gpio_num) {
PIMutexLocker ml(mutex); PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]); GPIOData & g(gpio_[gpio_num]);
@@ -246,12 +277,28 @@ void PIGPIO::pinBeginWatch(int gpio_num) {
} }
//! \~\details
//! \~english
//! This function doesn`t affect thread state!
//! Pins watching starts only with \a PIThread::start() function
//!
//! \~russian
//! Этот метод не меняет состояние потока наблюдения!
//! Наблюдение за пинами начинается методом \a PIThread::start()
void PIGPIO::pinEndWatch(int gpio_num) { void PIGPIO::pinEndWatch(int gpio_num) {
PIMutexLocker ml(mutex); PIMutexLocker ml(mutex);
watch_state.remove(gpio_num); watch_state.remove(gpio_num);
} }
//! \~\details
//! \~english
//! This function doesn`t affect thread state!
//! Pins watching starts only with \a PIThread::start() function
//!
//! \~russian
//! Этот метод не меняет состояние потока наблюдения!
//! Наблюдение за пинами начинается методом \a PIThread::start()
void PIGPIO::clearWatch() { void PIGPIO::clearWatch() {
PIMutexLocker ml(mutex); PIMutexLocker ml(mutex);
watch_state.clear(); watch_state.clear();
@@ -259,5 +306,5 @@ void PIGPIO::clearWatch() {
#ifdef __GNUC__ #ifdef __GNUC__
# pragma GCC diagnostic pop //# pragma GCC diagnostic pop
#endif #endif

View File

@@ -29,50 +29,57 @@
#include "pithread.h" #include "pithread.h"
//! \ingroup IO
//! \~\brief
//! \~english GPIO support.
//! \~russian Поддержка GPIO.
class PIP_EXPORT PIGPIO: public PIThread class PIP_EXPORT PIGPIO: public PIThread
{ {
PIOBJECT_SUBCLASS(PIGPIO, PIThread) PIOBJECT_SUBCLASS(PIGPIO, PIThread)
public: public:
PIGPIO();
virtual ~PIGPIO();
//! \brief Work mode for pin //! \~english Work mode for pin
//! \~russian Режим работы пина
enum Direction { enum Direction {
In /** Input direction (read) */, In /** \~english Input direction (read) \~russian Входной (чтение) */,
Out /** Output direction (write) */ Out /** \~english Output direction (write) \~russian Выходной (запись) */
}; };
//! \brief Returns singleton object of %PIGPIO //! \~english Returns singleton object of %PIGPIO
//! \~russian Возвращает синглтон объекта %PIGPIO
static PIGPIO * instance(); static PIGPIO * instance();
//! \brief Initialize pin \"gpio_num\" for \"dir\" mode //! \~english Initialize pin "gpio_num" for "dir" mode
//! \~russian Инициализирует пин "gpio_num" для режима работы "dir"
void initPin(int gpio_num, Direction dir = PIGPIO::In); void initPin(int gpio_num, Direction dir = PIGPIO::In);
//! \brief Set pin \"gpio_num\" value to \"value\" //! \~english Set pin "gpio_num" value to "value"
//! \~russian Устанавливает значение пина "gpio_num" в "value"
void pinSet (int gpio_num, bool value); void pinSet (int gpio_num, bool value);
//! \brief Set pin \"gpio_num\" value to \b true //! \~english Set pin "gpio_num" value to \b true
//! \~russian Устанавливает значение пина "gpio_num" в \b true
void pinHigh (int gpio_num) {pinSet(gpio_num, true );} void pinHigh (int gpio_num) {pinSet(gpio_num, true );}
//! \brief Set pin \"gpio_num\" value to \b false //! \~english Set pin "gpio_num" value to \b false
//! \~russian Устанавливает значение пина "gpio_num" в \b false
void pinLow (int gpio_num) {pinSet(gpio_num, false);} void pinLow (int gpio_num) {pinSet(gpio_num, false);}
//! \brief Returns pin \"gpio_num\" state //!
//! \~english Returns pin "gpio_num" state
//! \~russian Возвращает значение пина "gpio_num"
bool pinState(int gpio_num); bool pinState(int gpio_num);
//! \brief Starts watch for pin \"gpio_num\". //! \~english Starts watch for pin "gpio_num"
//! \details Pins watching starts only with \a PIThread::start() function! //! \~russian Начинает наблюдение за пином "gpio_num"
//! This function doesn`t affect thread state
void pinBeginWatch(int gpio_num); void pinBeginWatch(int gpio_num);
//! \brief End watch for pin \"gpio_num\". //! \~english End watch for pin "gpio_num"
//! \details Pins watching starts only with \a PIThread::start() function! //! \~russian Заканчивает наблюдение за пином "gpio_num"
//! This function doesn`t affect thread state
void pinEndWatch (int gpio_num); void pinEndWatch (int gpio_num);
//! \brief End watch for all pins. //! \~english End watch for all pins
//! \details Pins watching starts only with \a PIThread::start() function! //! \~russian Заканчивает наблюдение за всеми пинами
//! This function doesn`t affect thread state
void clearWatch(); void clearWatch();
EVENT2(pinChanged, int, gpio_num, bool, new_value) EVENT2(pinChanged, int, gpio_num, bool, new_value)
@@ -81,13 +88,20 @@ public:
//! \{ //! \{
//! \fn void pinChanged(int gpio_num, bool new_value) //! \fn void pinChanged(int gpio_num, bool new_value)
//! \brief Raise on pin \"gpio_num\" state changes to \"new_value\" //! \~english Raise on pin "gpio_num" state changes to "new_value"
//! \details Important! This event will be raised only with started //! \~russian Вызывается по смене состояния пина "gpio_num" на "new_value"
//! thread. //! \~\details
//! \~\warning
//! \~english This event raised only when thread started.
//! \~russian Это событие вызывается только при запущенном потоке.
//! \} //! \}
private: private:
PIGPIO();
virtual ~PIGPIO();
NO_COPY_CLASS(PIGPIO)
struct PIP_EXPORT GPIOData { struct PIP_EXPORT GPIOData {
GPIOData() {dir = PIGPIO::In; num = fd = -1;} GPIOData() {dir = PIGPIO::In; num = fd = -1;}
PIString name; PIString name;

View File

@@ -20,12 +20,15 @@
#include "piiobytearray.h" #include "piiobytearray.h"
/*! \class PIIOByteArray //! \class PIIOByteArray piiobytearray.h
* \brief PIIODevice wrapper around PIByteArray //! \details
* //! \~english
* \section PIIOByteArray_sec0 Synopsis //! This class allow you to use PIByteArray as PIIODevice, e.g. to pass it to PIConfig.
* This class sllow you to use PIByteArray as PIIODevice and pass it to, e.g. PIConfig //!
*/ //! \~russian
//! Этот класс позволяет использовать PIByteArray в качестве PIIODevice, например,
//! для передачи в PIConfig.
//!
PIIOByteArray::PIIOByteArray(PIByteArray *buffer, PIIODevice::DeviceMode mode) { PIIOByteArray::PIIOByteArray(PIByteArray *buffer, PIIODevice::DeviceMode mode) {

View File

@@ -29,44 +29,59 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english PIIODevice wrapper around PIByteArray
//! \~russian Обёртка PIIODevice вокруг PIByteArray
class PIP_EXPORT PIIOByteArray: public PIIODevice class PIP_EXPORT PIIOByteArray: public PIIODevice
{ {
PIIODEVICE(PIIOByteArray) PIIODEVICE(PIIOByteArray, "")
public: public:
//! Contructs %PIIOByteArray with \"buffer\" content and \"mode\" open mode //! \~english Contructs %PIIOByteArray with "buffer" content and "mode" open mode
//! \~russian Создает %PIIOByteArray с содержимым "buffer" и режимом открытия "mode"
explicit PIIOByteArray(PIByteArray * buffer = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PIIOByteArray(PIByteArray * buffer = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Contructs %PIIOByteArray with \"buffer\" content only for read //! \~english Contructs %PIIOByteArray with "buffer" content only for read
//! \~russian Создает %PIIOByteArray с содержимым "buffer" только для чтения
explicit PIIOByteArray(const PIByteArray & buffer); explicit PIIOByteArray(const PIByteArray & buffer);
//! Returns content //! \~english Returns content
//! \~russian Возвращает содержимое
PIByteArray * byteArray() const {return data_;} PIByteArray * byteArray() const {return data_;}
//! Clear content buffer //! \~english Clear content buffer
//! \~russian Очищает содержимое буфера
void clear() {if (data_) data_->clear(); pos = 0;} void clear() {if (data_) data_->clear(); pos = 0;}
//! Open \"buffer\" content with \"mode\" open mode //! \~english Open "buffer" content with "mode" open mode
//! \~russian Открывает содержимое "buffer" с режимом открытия "mode"
bool open(PIByteArray * buffer, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(PIByteArray * buffer, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Open \"buffer\" content only for read //! \~english Open "buffer" content only for read
//! \~russian Открывает содержимое "buffer" только для чтения
bool open(const PIByteArray & buffer); bool open(const PIByteArray & buffer);
//! Returns if position is at the end of content //! \~english Returns if position is at the end of content
//! \~russian Возвращает в конце содержимого ли позиция
bool isEnd() const {if (!data_) return true; return pos >= data_->size_s();} bool isEnd() const {if (!data_) return true; return pos >= data_->size_s();}
//! Move read/write position to \"position\" //! \~english Move read/write position to "position"
//! \~russian Перемещает позицию чтения/записи на "position"
void seek(llong position) {pos = position;} void seek(llong position) {pos = position;}
//! Move read/write position to the begin of the string //! \~english Move read/write position to the beginning of the buffer
//! \~russian Перемещает позицию чтения/записи на начало буфера
void seekToBegin() {if (data_) pos = 0;} void seekToBegin() {if (data_) pos = 0;}
//! Move read/write position to the end of the string //! \~english Move read/write position to the end of the buffer
//! \~russian Перемещает позицию чтения/записи на конец буфера
void seekToEnd() {if (data_) pos = data_->size_s();} void seekToEnd() {if (data_) pos = data_->size_s();}
//! Insert data \"ba\" into content at current position //! \~english Insert data "ba" into content at current position
//! \~russian Вставляет данные "ba" в содержимое буфера в текущую позицию
int writeByteArray(const PIByteArray & ba); int writeByteArray(const PIByteArray & ba);
protected: protected:

View File

@@ -23,13 +23,7 @@
#include "pipropertystorage.h" #include "pipropertystorage.h"
//! \addtogroup IO
//! \{
//! \class PIIODevice piiodevice.h //! \class PIIODevice piiodevice.h
//! \brief
//! \~english Base class for input/output classes
//! \~russian Базовый класс утройств ввода/вывода
//!
//! \~\details //! \~\details
//! \section PIIODevice_sec0 Synopsis //! \section PIIODevice_sec0 Synopsis
//! This class provide open/close logic, threaded read/write and virtual input/output //! This class provide open/close logic, threaded read/write and virtual input/output
@@ -84,11 +78,10 @@
//! //!
//! \section PIIODevice_sec7 Creating devices by unambiguous string //! \section PIIODevice_sec7 Creating devices by unambiguous string
//! There are some virtual functions to describe child class without its declaration. //! There are some virtual functions to describe child class without its declaration.
//! \n \a fullPathPrefix() should returns unique prefix of device
//! \n \a constructFullPath() should returns full unambiguous string, contains prefix and all device parameters //! \n \a constructFullPath() should returns full unambiguous string, contains prefix and all device parameters
//! \n \a configureFromFullPath() provide configuring device from full unambiguous string without prefix and "://" //! \n \a configureFromFullPath() provide configuring device from full unambiguous string without prefix and "://"
//! \n Macro PIIODEVICE should be used instead of PIOBJECT //! \n Macro PIIODEVICE should be used instead of PIOBJECT
//! \n Macro REGISTER_DEVICE should be used after definition of class, i.e. at the last line of *.cpp file //! \n Macro REGISTER_DEVICE should be used after declaration of class, i.e. at the last line of *.h file
//! \n \n If custom I/O device corresponds there rules, it can be returned by function \a createFromFullPath(). //! \n \n If custom I/O device corresponds there rules, it can be returned by function \a createFromFullPath().
//! \n Each PIP I/O device has custom unambiguous string description: //! \n Each PIP I/O device has custom unambiguous string description:
//! * PIFile: "file://<path>" //! * PIFile: "file://<path>"
@@ -117,7 +110,6 @@
//! \section PIIODevice_ex0 Example //! \section PIIODevice_ex0 Example
//! \snippet piiodevice.cpp 0 //! \snippet piiodevice.cpp 0
//! //!
//! \}
PIMutex PIIODevice::nfp_mutex; PIMutex PIIODevice::nfp_mutex;
@@ -131,9 +123,6 @@ PIIODevice::PIIODevice(): PIThread() {
} }
/*! \brief Constructs a PIIODevice with path and mode
* \param path path to device
* \param type mode for open */
PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode mode): PIThread() { PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode mode): PIThread() {
mode_ = mode; mode_ = mode;
_init(); _init();
@@ -160,6 +149,34 @@ bool PIIODevice::setOption(PIIODevice::DeviceOption o, bool yes) {
} }
//! \~\details
//! \~english
//! Set external static function of threaded read that will be executed
//! at every successful threaded read. Function should have format
//! "bool func(void * data, uchar * readed, int size)"
//! \~russian
//! Устанавливает внешний статический метод, который будет вызван
//! после каждого успешного потокового чтения. Метод должен быть
//! в формате "bool func(void * data, uchar * readed, int size)"
void PIIODevice::setThreadedReadSlot(ReadRetFunc func) {
ret_func_ = func;
}
//! \~\details
//! \~english
//! Default size is 4096 bytes. If your device can read at single read
//! more than 4096 bytes you should use this function to adjust buffer size
//! \~russian
//! По умолчанию 4096 байт. Если устройство за одно чтение может читать
//! более 4096 байт, необходимо использовать этот метод для установки
//! нужного размера буфера
void PIIODevice::setThreadedReadBufferSize(int new_size) {
threaded_read_buffer_size = new_size;
threadedReadBufferSizeChanged();
}
bool stopThread(PIThread * t, bool hard) { bool stopThread(PIThread * t, bool hard) {
#ifdef MICRO_PIP #ifdef MICRO_PIP
t->stop(true); t->stop(true);
@@ -265,15 +282,12 @@ void PIIODevice::write_func() {
} }
PIIODevice * PIIODevice::newDeviceByPrefix(const PIString & prefix) { PIIODevice * PIIODevice::newDeviceByPrefix(const char * prefix) {
if (prefix.isEmpty()) return 0; if (!prefix) return nullptr;
PIVector<const PIObject * > rd(PICollection::groupElements("__PIIODevices__")); auto fi = fabrics().value(prefix);
piForeachC (PIObject * d, rd) { if (fi.fabricator)
if (prefix == ((const PIIODevice * )d)->fullPathPrefix()) { return fi.fabricator();
return ((const PIIODevice * )d)->copy(); return nullptr;
}
}
return 0;
} }
@@ -427,7 +441,7 @@ bool PIIODevice::configure(const PIString & config_file, const PIString & sectio
PIString PIIODevice::constructFullPath() const { PIString PIIODevice::constructFullPath() const {
return fullPathPrefix() + "://" + constructFullPathDevice() + fullPathOptions(); return fullPathPrefix().toString() + PIStringAscii("://") + constructFullPathDevice() + fullPathOptions();
} }
@@ -462,23 +476,23 @@ void PIIODevice::configureFromVariant(const PIVariantTypes::IODevice & d) {
void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode, DeviceOptions * opts) { void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode, DeviceOptions * opts) {
int dm = 0; int dm = 0;
DeviceOptions op = 0; DeviceOptions op = 0;
if (fpwm.find("(") > 0 && fpwm.find(")") > 0) { if (fpwm.find('(') > 0 && fpwm.find(')') > 0) {
PIString dms(fpwm.right(fpwm.length() - fpwm.findLast("(")).takeRange("(", ")").trim().toLowerCase().removeAll(' ')); PIString dms(fpwm.right(fpwm.length() - fpwm.findLast('(')).takeRange('(', ')').trim().toLowerCase().removeAll(' '));
PIStringList opts(dms.split(",")); PIStringList opts(dms.split(","));
piForeachC (PIString & o, opts) { piForeachC (PIString & o, opts) {
//piCout << dms; //piCout << dms;
if (o == "r" || o == "ro" || o == "read" || o == "readonly") if (o == PIStringAscii("r") || o == PIStringAscii("ro") || o == PIStringAscii("read") || o == PIStringAscii("readonly"))
dm |= ReadOnly; dm |= ReadOnly;
if (o == "w" || o == "wo" || o == "write" || o == "writeonly") if (o == PIStringAscii("w") || o == PIStringAscii("wo") || o == PIStringAscii("write") || o == PIStringAscii("writeonly"))
dm |= WriteOnly; dm |= WriteOnly;
if (o == "br" || o == "blockr" || o == "blockread" || o == "blockingread") if (o == PIStringAscii("br") || o == PIStringAscii("blockr") || o == PIStringAscii("blockread") || o == PIStringAscii("blockingread"))
op |= BlockingRead; op |= BlockingRead;
if (o == "bw" || o == "blockw" || o == "blockwrite" || o == "blockingwrite") if (o == PIStringAscii("bw") || o == PIStringAscii("blockw") || o == PIStringAscii("blockwrite") || o == PIStringAscii("blockingwrite"))
op |= BlockingWrite; op |= BlockingWrite;
if (o == "brw" || o == "bwr" || o == "blockrw" || o == "blockwr" || o == "blockreadrite" || o == "blockingreadwrite") if (o == PIStringAscii("brw") || o == PIStringAscii("bwr") || o == PIStringAscii("blockrw") || o == PIStringAscii("blockwr") || o == PIStringAscii("blockreadrite") || o == PIStringAscii("blockingreadwrite"))
op |= BlockingRead | BlockingWrite; op |= BlockingRead | BlockingWrite;
} }
fpwm.cutRight(fpwm.length() - fpwm.findLast("(")).trim(); fpwm.cutRight(fpwm.length() - fpwm.findLast('(')).trim();
} }
if (dm == 0) dm = ReadWrite; if (dm == 0) dm = ReadWrite;
if (full_path) *full_path = fpwm; if (full_path) *full_path = fpwm;
@@ -489,14 +503,33 @@ void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode *
PIStringList PIIODevice::availablePrefixes() { PIStringList PIIODevice::availablePrefixes() {
PIStringList ret; PIStringList ret;
PIVector<const PIObject * > rd(PICollection::groupElements("__PIIODevices__")); for (const auto & i: fabrics())
piForeachC (PIObject * d, rd) { ret << i.second.prefix.toString();
ret << ((const PIIODevice * )d)->fullPathPrefix();
}
return ret; return ret;
} }
PIStringList PIIODevice::availableClasses() {
PIStringList ret;
for (const auto & i: fabrics())
ret << i.second.classname.toString();
return ret;
}
void PIIODevice::registerDevice(PIConstChars prefix, PIConstChars classname, PIIODevice * (*fabric)()) {
if (prefix.isEmpty()) return;
//printf("registerDevice %s %d %d\n", prefix, p.isEmpty(), fabrics().size());
if (!fabrics().contains(prefix)) {
FabricInfo fi;
fi.prefix = prefix;
fi.classname = classname;
fi.fabricator = fabric;
fabrics()[prefix] = fi;
}
}
PIString PIIODevice::fullPathOptions() const { PIString PIIODevice::fullPathOptions() const {
if (mode_ == ReadWrite && options_ == 0) return PIString(); if (mode_ == ReadWrite && options_ == 0) return PIString();
PIString ret(" ("); PIString ret(" (");
@@ -509,10 +542,17 @@ PIString PIIODevice::fullPathOptions() const {
} }
//! \~\details
//! \~english
//! To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() and "://".
//! See \ref PIIODevice_sec7
//! \~russian
//! В метод \a configureFromFullPath() "full_path" передается без \a fullPathPrefix() и "://".
//! См. \ref PIIODevice_sec7
PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) { PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) {
PIString prefix = full_path.left(full_path.find(":")); PIString prefix = full_path.left(full_path.find(":"));
PIIODevice * nd = newDeviceByPrefix(prefix); PIIODevice * nd = newDeviceByPrefix(prefix.dataAscii());
if (!nd) return 0; if (!nd) return nullptr;
nd->configureFromFullPath(full_path.mid(prefix.length() + 3)); nd->configureFromFullPath(full_path.mid(prefix.length() + 3));
cacheFullPath(full_path, nd); cacheFullPath(full_path, nd);
return nd; return nd;
@@ -520,8 +560,8 @@ PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) {
PIIODevice * PIIODevice::createFromVariant(const PIVariantTypes::IODevice & d) { PIIODevice * PIIODevice::createFromVariant(const PIVariantTypes::IODevice & d) {
PIIODevice * nd = newDeviceByPrefix(d.prefix); PIIODevice * nd = newDeviceByPrefix(d.prefix.dataAscii());
if (!nd) return 0; if (!nd) return nullptr;
nd->configureFromVariant(d); nd->configureFromVariant(d);
return nd; return nd;
} }
@@ -550,6 +590,12 @@ void PIIODevice::cacheFullPath(const PIString & full_path, const PIIODevice * d)
} }
PIMap<PIConstChars, PIIODevice::FabricInfo> & PIIODevice::fabrics() {
static PIMap<PIConstChars, FabricInfo> ret;
return ret;
}
bool PIIODevice::threadedRead(uchar *readed, int size) { bool PIIODevice::threadedRead(uchar *readed, int size) {
// piCout << "iodevice threaded read"; // piCout << "iodevice threaded read";
if (ret_func_ != 0) return ret_func_(ret_data_, readed, size); if (ret_func_ != 0) return ret_func_(ret_data_, readed, size);

View File

@@ -27,7 +27,6 @@
#define PIIODEVICE_H #define PIIODEVICE_H
#include "piinit.h" #include "piinit.h"
#include "picollection.h"
#include "pitimer.h" #include "pitimer.h"
#include "piqueue.h" #include "piqueue.h"
@@ -38,20 +37,46 @@ typedef bool (*ReadRetFunc)(void * , uchar * , int );
#ifdef DOXYGEN #ifdef DOXYGEN
//! \relatesalso PIIODevice \brief Use this macro to enable automatic creation instances of your class with \a createFromFullPath() function //! \relatesalso PIIODevice
//! \brief
//! \~english Enable device instances creation with \a PIIODevice::createFromFullPath() function.
//! \~russian Включить создание экземпляров устройства с помощью метода \a PIIODevice::createFromFullPath().
//! \~\details
//! \~english This macro may be placed in cpp or header file, but preferred place is header
//! \~russian Этот макрос может быть расположен в cpp или заголовочном файле, но предпочтительнее распологать в заголовочном
# define REGISTER_DEVICE(class) # define REGISTER_DEVICE(class)
//! \relatesalso PIIODevice \brief Use this macro instead of PIOBJECT when describe your own PIIODevice //! \relatesalso PIIODevice
# define PIIODEVICE(class) //! \brief
//! \~english Use this macro instead of PIOBJECT when describe your own PIIODevice.
//! \~russian Используйте этот макрос вместо PIOBJECT при объявлении своего PIIODevice.
//! \~\param "prefix"
//! \~english Unique device prefix in quotes, may be ""
//! \~russian Уникальный префикс устройства в кавычках, может быть ""
# define PIIODEVICE(class, "prefix")
#else #else
# define REGISTER_DEVICE(name) ADD_NEW_TO_COLLECTION_WITH_NAME(__PIIODevices__, name, __S__collection_##name##__) # define REGISTER_DEVICE(name) \
# define PIIODEVICE(name) PIOBJECT_SUBCLASS(name, PIIODevice) PIIODevice * copy() const {return new name();} STATIC_INITIALIZER_BEGIN \
PIIODevice::registerDevice(name::fullPathPrefixS(), #name, []()->PIIODevice*{return new name();});\
STATIC_INITIALIZER_END
# define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const {return new name();} \
public: \
virtual PIConstChars fullPathPrefix() const {return prefix;} \
static PIConstChars fullPathPrefixS() {return prefix;} \
private:
#endif #endif
//! \ingroup IO
//! \~\brief
//! \~english Base class for input/output devices.
//! \~russian Базовый класс утройств ввода/вывода.
class PIP_EXPORT PIIODevice: public PIThread class PIP_EXPORT PIIODevice: public PIThread
{ {
PIOBJECT_SUBCLASS(PIIODevice, PIThread) PIOBJECT_SUBCLASS(PIIODevice, PIThread)
@@ -59,207 +84,271 @@ class PIP_EXPORT PIIODevice: public PIThread
public: public:
NO_COPY_CLASS(PIIODevice) NO_COPY_CLASS(PIIODevice)
//! Constructs a empty PIIODevice //! \~english Constructs a empty %PIIODevice
//! \~russian Создает пустой %PIIODevice
explicit PIIODevice(); explicit PIIODevice();
//! \brief Open modes for PIIODevice //! \~english Open modes for PIIODevice
//! \~russian Режимы открытия для PIIODevice
enum DeviceMode { enum DeviceMode {
ReadOnly /*! Device can only read */ = 0x01, ReadOnly /*! \~english Device can only read \~russian Устройство может только читать */ = 0x01,
WriteOnly /*! Device can only write */ = 0x02, WriteOnly /*! \~english Device can only write \~russian Устройство может только писать */ = 0x02,
ReadWrite /*! Device can both read and write */ = 0x03 ReadWrite /*! \~english Device can both read and write \~russian Устройство может читать и писать */ = 0x03
}; };
//! \brief Options for PIIODevice, works with some devices //! \~english Options for PIIODevice, works with some devices
//! \~russian Опции для PIIODevice, работает для некоторых устройств
enum DeviceOption { enum DeviceOption {
BlockingRead /*! \a read block until data is received, default off */ = 0x01, BlockingRead /*! \~english \a read() block until data is received, default off \~russian \a read() блокируется, пока данные не поступят, по умолчанию выключено */ = 0x01,
BlockingWrite /*! \a write block until data is sent, default off */ = 0x02 BlockingWrite /*! \~english \a write() block until data is sent, default off \~russian \a write() блокируется, пока данные не запишутся, по умолчанию выключено */ = 0x02
}; };
//! \brief Characteristics of PIIODevice subclass //! \~english Characteristics of PIIODevice channel
//! \~russian Характеристики канала PIIODevice
enum DeviceInfoFlag { enum DeviceInfoFlag {
Sequential /*! Continuous bytestream without datagrams */ = 0x01, Sequential /*! \~english Continuous bytestream without packets \~russian Непрерывный поток байт, без пакетирования */ = 0x01,
Reliable /*! Channel without data errors / corruptions */ = 0x02 Reliable /*! \~english Channel without data errors or corruptions \~russian Канал без ошибок или повреждений данных */ = 0x02
};
struct FabricInfo {
PIConstChars prefix;
PIConstChars classname;
PIIODevice*(*fabricator)() = nullptr;
}; };
typedef PIFlags<DeviceOption> DeviceOptions; typedef PIFlags<DeviceOption> DeviceOptions;
typedef PIFlags<DeviceInfoFlag> DeviceInfoFlags; typedef PIFlags<DeviceInfoFlag> DeviceInfoFlags;
//! \~english Constructs %PIIODevice with path "path" and open mode "mode"
//! \~russian Создает %PIIODevice с путём "path" и режимом открытия "mode"
explicit PIIODevice(const PIString & path, DeviceMode mode = ReadWrite); explicit PIIODevice(const PIString & path, DeviceMode mode = ReadWrite);
virtual ~PIIODevice(); virtual ~PIIODevice();
//! Current open mode of device //! \~english Returns current open mode of device
//! \~russian Возвращает текущий режим открытия устройства
DeviceMode mode() const {return mode_;} DeviceMode mode() const {return mode_;}
//! Set open mode of device //! \~english Set open mode of device. Don`t reopen device
//! \~russian Устанавливает режим открытия устройства. Не переоткрывает устройство
void setMode(DeviceMode m) {mode_ = m;} void setMode(DeviceMode m) {mode_ = m;}
//! Current device options //! \~english Returns current device options
//! \~russian Возвращает текущие опции устройства
DeviceOptions options() const {return options_;} DeviceOptions options() const {return options_;}
//! Current device option "o" state //! \~english Returns current device option "o" state
//! \~russian Возвращает текущее состояние опции "o"
bool isOptionSet(DeviceOption o) const {return options_[o];} bool isOptionSet(DeviceOption o) const {return options_[o];}
//! Set device options //! \~english Set device options
//! \~russian Устанавливает опции устройства
void setOptions(DeviceOptions o); void setOptions(DeviceOptions o);
//! Set device option "o" to "yes" and return previous state //! \~english Set device option "o" to "yes" and returns previous state
//! \~russian Устанавливает опцию "o" устройства в "yes" и возвращает предыдущее состояние опции
bool setOption(DeviceOption o, bool yes = true); bool setOption(DeviceOption o, bool yes = true);
//! Returns device characteristic flags //! \~english Returns device characteristic flags
//! \~russian Возвращает характеристики канала
DeviceInfoFlags infoFlags() const {return deviceInfoFlags();} DeviceInfoFlags infoFlags() const {return deviceInfoFlags();}
//! Current path of device //! \~english Returns current path of device
PIString path() const {return property(PIStringAscii("path")).toString();} //! \~russian Возвращает текущий путь устройства
PIString path() const {return property("path").toString();}
//! Set path of device //! \~english Set path of device. Don`t reopen device
void setPath(const PIString & path) {setProperty(PIStringAscii("path"), path);} //! \~russian Устанавливает путь устройства. Не переоткрывает устройство
void setPath(const PIString & path) {setProperty("path", path);}
//! Return \b true if mode is ReadOnly or ReadWrite //! \~english Returns if mode is ReadOnly or ReadWrite
//! \~russian Возвращает равен ли режим открытия ReadOnly или ReadWrite
bool isReadable() const {return (mode_ & ReadOnly);} bool isReadable() const {return (mode_ & ReadOnly);}
//! Return \b true if mode is WriteOnly or ReadWrite //! \~english Returns if mode is WriteOnly or ReadWrite
//! \~russian Возвращает равен ли режим открытия WriteOnly или ReadWrite
bool isWriteable() const {return (mode_ & WriteOnly);} bool isWriteable() const {return (mode_ & WriteOnly);}
//! Return \b true if device is successfully opened //! \~english Returns if device is successfully opened
//! \~russian Возвращает успешно ли открыто устройство
bool isOpened() const {return opened_;} bool isOpened() const {return opened_;}
//! Return \b true if device is closed //! \~english Returns if device is closed
//! \~russian Возвращает закрыто ли устройство
bool isClosed() const {return !opened_;} bool isClosed() const {return !opened_;}
//! Return \b true if device can read \b now //! \~english Returns if device can read \b now
//! \~russian Возвращает может ли устройство читать \b сейчас
virtual bool canRead() const {return opened_ && (mode_ & ReadOnly);} virtual bool canRead() const {return opened_ && (mode_ & ReadOnly);}
//! Return \b true if device can write \b now //! \~english Returns if device can write \b now
//! \~russian Возвращает может ли устройство писать \b сейчас
virtual bool canWrite() const {return opened_ && (mode_ & WriteOnly);} virtual bool canWrite() const {return opened_ && (mode_ & WriteOnly);}
//! Set execution of \a open enabled while threaded read on closed device //! \~english Set calling of \a open() enabled while threaded read on closed device
void setReopenEnabled(bool yes = true) {setProperty(PIStringAscii("reopenEnabled"), yes);} //! \~russian Устанавливает возможность вызова \a open() при потоковом чтении на закрытом устройстве
void setReopenEnabled(bool yes = true) {setProperty("reopenEnabled", yes);}
//! Set timeout in milliseconds between \a open tryings if reopen is enabled //!
void setReopenTimeout(int msecs) {setProperty(PIStringAscii("reopenTimeout"), msecs);} //! \~english Set timeout in milliseconds between \a open() tryings if reopen is enabled
//! \~russian Устанавливает задержку в миллисекундах между вызовами \a open() если переоткрытие активно
void setReopenTimeout(int msecs) {setProperty("reopenTimeout", msecs);}
//! \~english Returns reopen enable
//! \~russian Возвращает активно ли переоткрытие
bool isReopenEnabled() const {return property("reopenEnabled").toBool();}
//! \~english Returns reopen timeout in milliseconds
//! \~russian Возвращает задержку переоткрытия в миллисекундах
int reopenTimeout() {return property("reopenTimeout").toInt();}
//! Return reopen enable //! \~english Set threaded read callback
bool isReopenEnabled() const {return property(PIStringAscii("reopenEnabled")).toBool();} //! \~russian Устанавливает callback потокового чтения
void setThreadedReadSlot(ReadRetFunc func);
//! Return reopen timeout //! \~english Set custom data that will be passed to threaded read callback
int reopenTimeout() {return property(PIStringAscii("reopenTimeout")).toInt();} //! \~russian Устанавливает произвольный указатель, который будет передан в callback потокового чтения
/** \brief Set "threaded read slot"
* \details Set external static function of threaded read that will be executed
* at every successful threaded read. Function should have format
* "bool func(void * data, uchar * readed, int size)" */
void setThreadedReadSlot(ReadRetFunc func) {ret_func_ = func;}
//! Set custom data that will be passed to "threaded read slot"
void setThreadedReadData(void * d) {ret_data_ = d;} void setThreadedReadData(void * d) {ret_data_ = d;}
/** \brief Set size of threaded read buffer //! \~english Set size of threaded read buffer
* \details Default size is 4096 bytes. If your device can read at single read //! \~russian Устанавливает размер буфера потокового чтения
* more than 4096 bytes you should use this function to adjust buffer size */ void setThreadedReadBufferSize(int new_size);
void setThreadedReadBufferSize(int new_size) {threaded_read_buffer_size = new_size; threadedReadBufferSizeChanged();}
//! Return size of threaded read buffer //! \~english Returns size of threaded read buffer
//! \~russian Возвращает размер буфера потокового чтения
int threadedReadBufferSize() const {return threaded_read_buffer_size;} int threadedReadBufferSize() const {return threaded_read_buffer_size;}
//! Return content of threaded read buffer //! \~english Returns content of threaded read buffer
//! \~russian Возвращает содержимое буфера потокового чтения
const uchar * threadedReadBuffer() const {return buffer_tr.data();} const uchar * threadedReadBuffer() const {return buffer_tr.data();}
//! Return custom data that will be passed to "threaded read slot" //! \~english Returns custom data that will be passed to threaded read callback
//! \~russian Возвращает произвольный указатель, который будет передан в callback потокового чтения
void * threadedReadData() const {return ret_data_;} void * threadedReadData() const {return ret_data_;}
//! Return \b true if threaded read is started //! \~english Returns if threaded read is started
//! \~russian Возвращает запущен ли поток чтения
bool isThreadedRead() const {return isRunning();} bool isThreadedRead() const {return isRunning();}
//! Start threaded read //! \~english Start threaded read
//! \~russian Запускает потоковое чтение
void startThreadedRead() {if (!isRunning()) PIThread::start();} void startThreadedRead() {if (!isRunning()) PIThread::start();}
//! Start threaded read and assign "threaded read slot" to "func" //! \~english Start threaded read and assign threaded read callback to "func"
//! \~russian Запускает потоковое чтение и устанавливает callback потокового чтения в "func"
void startThreadedRead(ReadRetFunc func) {ret_func_ = func; startThreadedRead();} void startThreadedRead(ReadRetFunc func) {ret_func_ = func; startThreadedRead();}
//! Stop threaded read. Hard stop terminate thread, otherwise wait fo 10 seconds //! \~english Stop threaded read. Hard stop terminate thread, otherwise wait fo 10 seconds
//! \~russian Останавливает потоковое чтение. Жесткая остановка убивает поток, иначе ожидает 10 секунд
void stopThreadedRead(bool hard = true); void stopThreadedRead(bool hard = true);
//! Return \b true if threaded write is started //! \~english Returns if threaded write is started
//! \~russian Возвращает запущен ли поток записи
bool isThreadedWrite() const {return write_thread.isRunning();} bool isThreadedWrite() const {return write_thread.isRunning();}
//! Start threaded write //! \~english Start threaded write
//! \~russian Запускает потоковую запись
void startThreadedWrite() {if (!write_thread.isRunning()) write_thread.startOnce();} void startThreadedWrite() {if (!write_thread.isRunning()) write_thread.startOnce();}
//! Stop threaded write. Hard stop terminate thread, otherwise wait fo 10 seconds //! \~english Stop threaded write. Hard stop terminate thread, otherwise wait fo 10 seconds
//! \~russian Останавливает потоковую запись. Жесткая остановка убивает поток, иначе ожидает 10 секунд
void stopThreadedWrite(bool hard = true); void stopThreadedWrite(bool hard = true);
//! Clear threaded write task queue //! \~english Clear threaded write task queue
//! \~russian Очищает очередь потоковой записи
void clearThreadedWriteQueue(); void clearThreadedWriteQueue();
//! Start both threaded read and threaded write //! \~english Start both threaded read and threaded write
//! \~russian Запускает потоковое чтение и запись
void start(); void start();
//! Stop both threaded read and threaded write. Hard stop terminate threads, otherwise wait fo 10 seconds //! \~english Stop both threaded read and threaded write. Hard stop terminate threads, otherwise wait fo 10 seconds
//! \~russian Останавливает потоковое чтение и запись. Жесткая остановка убивает потоки, иначе ожидает 10 секунд
void stop(bool hard = true); void stop(bool hard = true);
//! Read from device maximum "max_size" bytes to "read_to" //! \~english Read from device maximum "max_size" bytes to "read_to"
//! \~russian Читает из устройства не более "max_size" байт в "read_to"
int read(void * read_to, int max_size) {return readDevice(read_to, max_size);} int read(void * read_to, int max_size) {return readDevice(read_to, max_size);}
//! Read from device maximum "max_size" bytes and return them as PIByteArray //! \~english Read from device maximum "max_size" bytes and returns them as PIByteArray
//! \~russian Читает из устройства не более "max_size" байт и возвращает данные как PIByteArray
PIByteArray read(int max_size); PIByteArray read(int max_size);
//! Write maximum "max_size" bytes of "data" to device //! \~english Write maximum "max_size" bytes of "data" to device
//! \~russian Пишет в устройство не более "max_size" байт из "data"
int write(const void * data, int max_size) {return writeDevice(data, max_size);} int write(const void * data, int max_size) {return writeDevice(data, max_size);}
//! Read from device for "timeout_ms" milliseconds and return readed data as PIByteArray. Timeout should to be greater than 0 //! \~english Read from device for "timeout_ms" milliseconds and return readed data as PIByteArray.
//! Timeout should to be greater than 0
//! \~russian Читает из устройства в течении "timeout_ms" миллисекунд и возвращает данные как PIByteArray.
//! Таймаут должен быть больше 0
PIByteArray readForTime(double timeout_ms); PIByteArray readForTime(double timeout_ms);
//! Add task to threaded write queue and return task ID //! \~english Add task to threaded write queue and return task ID
//! \~russian Добавляет данные в очередь на потоковую запись и возвращает ID задания
ullong writeThreaded(const void * data, int max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));} ullong writeThreaded(const void * data, int max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));}
//! Add task to threaded write queue and return task ID //! \~english Add task to threaded write queue and return task ID
//! \~russian Добавляет данные в очередь на потоковую запись и возвращает ID задания
ullong writeThreaded(const PIByteArray & data); ullong writeThreaded(const PIByteArray & data);
//! Configure device from section "section" of file "config_file", if "parent_section" parent section also will be read //! \~english Configure device from section "section" of file "config_file", if "parent_section" parent section also will be read
//! \~russian
bool configure(const PIString & config_file, const PIString & section, bool parent_section = false); bool configure(const PIString & config_file, const PIString & section, bool parent_section = false);
//! Reimplement to construct full unambiguous string prefix. \ref PIIODevice_sec7 //! \~english Returns full unambiguous string prefix. \ref PIIODevice_sec7
virtual PIString fullPathPrefix() const {return PIString();} //! \~russian Возвращает префикс устройства. \ref PIIODevice_sec7
virtual PIConstChars fullPathPrefix() const {return "";}
//! Returns full unambiguous string, describes this device, \a fullPathPrefix() + "://" static PIConstChars fullPathPrefixS() {return "";}
//! \~english Returns full unambiguous string, describes this device, \a fullPathPrefix() + "://" + ...
//! \~russian Возвращает строку полного описания для этого устройства, \a fullPathPrefix() + "://" + ...
PIString constructFullPath() const; PIString constructFullPath() const;
//! Configure device with parameters of full unambiguous string //! \~english Configure device with parameters of full unambiguous string
//! \~russian Настраивает устройство из параметров строки полного описания
void configureFromFullPath(const PIString & full_path); void configureFromFullPath(const PIString & full_path);
//! Returns PIVariantTypes::IODevice, describes this device //! \~english Returns PIVariantTypes::IODevice, describes this device
//! \~russian Возвращает PIVariantTypes::IODevice, описывающий это устройство
PIVariantTypes::IODevice constructVariant() const; PIVariantTypes::IODevice constructVariant() const;
//! Configure device from PIVariantTypes::IODevice //! \~english Configure device from PIVariantTypes::IODevice
//! \~russian Настраивает устройство из PIVariantTypes::IODevice
void configureFromVariant(const PIVariantTypes::IODevice & d); void configureFromVariant(const PIVariantTypes::IODevice & d);
//! \brief Try to determine suitable device, create new one, configure it with \a configureFromFullPath() and returns it. //! \~english Try to create new device by prefix, configure it with \a configureFromFullPath() and returns it.
//! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://". //! \~russian Пытается создать новое устройство по префиксу, настраивает с помощью \a configureFromFullPath() и возвращает его
//! See \ref PIIODevice_sec7
static PIIODevice * createFromFullPath(const PIString & full_path); static PIIODevice * createFromFullPath(const PIString & full_path);
//! \brief Try to determine suitable device, create new one, configure it with \a configureFromVariant() and returns it. //! \~english Try to create new device by prefix, configure it with \a configureFromVariant() and returns it.
//! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://". //! \~russian Пытается создать новое устройство по префиксу, настраивает с помощью \a configureFromVariant() и возвращает его
//! See \ref PIIODevice_sec7
static PIIODevice * createFromVariant(const PIVariantTypes::IODevice & d); static PIIODevice * createFromVariant(const PIVariantTypes::IODevice & d);
static PIString normalizeFullPath(const PIString & full_path); static PIString normalizeFullPath(const PIString & full_path);
static void splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode = 0, DeviceOptions * opts = 0); static void splitFullPath(PIString fpwm, PIString * full_path, DeviceMode * mode = 0, DeviceOptions * opts = 0);
//! Returns fullPath prefixes of all registered devices //! \~english Returns fullPath prefixes of all registered devices
//! \~russian Возвращает префиксы всех зарегистрированных устройств
static PIStringList availablePrefixes(); static PIStringList availablePrefixes();
//! \~english Returns class names of all registered devices
//! \~russian Возвращает имена классов всех зарегистрированных устройств
static PIStringList availableClasses();
static void registerDevice(PIConstChars prefix, PIConstChars classname, PIIODevice*(*fabric)());
EVENT_HANDLER(bool, open); EVENT_HANDLER(bool, open);
EVENT_HANDLER1(bool, open, const PIString &, _path); EVENT_HANDLER1(bool, open, const PIString &, _path);
@@ -279,114 +368,152 @@ public:
//! \{ //! \{
//! \fn bool open() //! \fn bool open()
//! \brief Open device //! \~english Open device
//! \~russian Открывает устройство
//! \fn bool open(const PIString & path) //! \fn bool open(const PIString & path)
//! \brief Open device with path "path" //! \~english Open device with path "path"
//! \~russian Открывает устройство с путём "path"
//! \fn bool open(const DeviceMode & mode) //! \fn bool open(const DeviceMode & mode)
//! \brief Open device with mode "mode" //! \~english Open device with mode "mode"
//! \~russian Открывает устройство с режимом открытия "mode"
//! \fn bool open(const PIString & path, const DeviceMode & mode) //! \fn bool open(const PIString & path, const DeviceMode & mode)
//! \brief Open device with path "path" and mode "mode" //! \~english Open device with path "path" and mode "mode"
//! \~russian Открывает устройство с путём "path" и режимом открытия "mode"
//! \fn bool close() //! \fn bool close()
//! \brief Close device //! \~english Close device
//! \~russian Закрывает устройство
//! \fn int write(PIByteArray data) //! \fn int write(PIByteArray data)
//! \brief Write "data" to device //! \~english Write "data" to device
//! \~russian Пишет "data" в устройство
//! \} //! \}
//! \vhandlers //! \vhandlers
//! \{ //! \{
//! \fn void flush() //! \fn void flush()
//! \brief Immediate write all buffers //! \~english Immediate write all buffers
//! \~russian Немедленно записать все буферизированные данные
//! \} //! \}
//! \events //! \events
//! \{ //! \{
//! \fn void opened() //! \fn void opened()
//! \brief Raise if succesfull open //! \~english Raise if succesfull open
//! \~russian Вызывается при успешном открытии
//! \fn void closed() //! \fn void closed()
//! \brief Raise if succesfull close //! \~english Raise if succesfull close
//! \~russian Вызывается при успешном закрытии
//! \fn void threadedReadEvent(uchar * readed, int size) //! \fn void threadedReadEvent(uchar * readed, int size)
//! \brief Raise if read thread succesfull read some data //! \~english Raise if read thread succesfull read some data
//! \~russian Вызывается при успешном потоковом чтении данных
//! \fn void threadedWriteEvent(ullong id, int written_size) //! \fn void threadedWriteEvent(ullong id, int written_size)
//! \brief Raise if write thread successfull write some data of task with ID "id" //! \~english Raise if write thread successfull write some data of task with ID "id"
//! \~russian Вызывается при успешной потоковой записи данных с ID задания "id"
//! \} //! \}
//! \ioparams //! \ioparams
//! \{ //! \{
#ifdef DOXYGEN #ifdef DOXYGEN
//! \brief setReopenEnabled, default "true" //! \~english setReopenEnabled, default "true"
//! \~russian setReopenEnabled, по умолчанию "true"
bool reopenEnabled; bool reopenEnabled;
//! \brief setReopenTimeout in ms, default 1000 //! \~english setReopenTimeout in milliseconds, default 1000
//! \~russian setReopenTimeout в миллисекундах, по умолчанию 1000
int reopenTimeout; int reopenTimeout;
//! \brief setThreadedReadBufferSize in bytes, default 4096 //! \~english setThreadedReadBufferSize in bytes, default 4096
//! \~russian setThreadedReadBufferSize в байтах, по умолчанию 4096
int threadedReadBufferSize; int threadedReadBufferSize;
#endif #endif
//! \} //! \}
protected: protected:
//! Function executed before first \a openDevice() or from constructor //! \~english Function executed before first \a openDevice() or from constructor
//! \~russian Метод вызывается перед первым \a openDevice() или из конструктора
virtual bool init() {return true;} virtual bool init() {return true;}
//! Reimplement to configure device from entries "e_main" and "e_parent", cast arguments to \a PIConfig::Entry* //! \~english Reimplement to configure device from entries "e_main" and "e_parent", cast arguments to \a PIConfig::Entry*
//! \~russian
virtual bool configureDevice(const void * e_main, const void * e_parent = 0) {return true;} virtual bool configureDevice(const void * e_main, const void * e_parent = 0) {return true;}
//! Reimplement to open device, return value will be set to "opened_" variable; don't call this function in subclass, use open() //! \~english Reimplement to open device, return value will be set to "opened_" variable.
//! Don't call this function in subclass, use \a open()!
//! \~russian Переопределите для открытия устройства, возвращаемое значение будет установлено в
//! переменную "opened_". Не используйте напрямую, только через \a open()!
virtual bool openDevice() = 0; // use path_, type_, opened_, init_ variables virtual bool openDevice() = 0; // use path_, type_, opened_, init_ variables
//! Reimplement to close device, inverse return value will be set to "opened_" variable //! \~english Reimplement to close device, inverse return value will be set to "opened_" variable
//! \~russian Переопределите для закрытия устройства, обратное возвращаемое значение будет установлено в переменную "opened_"
virtual bool closeDevice() {return true;} // use path_, type_, opened_, init_ variables virtual bool closeDevice() {return true;} // use path_, type_, opened_, init_ variables
//! Reimplement this function to read from your device //! \~english Reimplement this function to read from your device
//! \~russian Переопределите для чтения данных из устройства
virtual int readDevice(void * read_to, int max_size) {piCoutObj << "\"read\" is not implemented!"; return -2;} virtual int readDevice(void * read_to, int max_size) {piCoutObj << "\"read\" is not implemented!"; return -2;}
//! Reimplement this function to write to your device //! \~english Reimplement this function to write to your device
//! \~russian Переопределите для записи данных в устройство
virtual int writeDevice(const void * data, int max_size) {piCoutObj << "\"write\" is not implemented!"; return -2;} virtual int writeDevice(const void * data, int max_size) {piCoutObj << "\"write\" is not implemented!"; return -2;}
//! Function executed when thread read some data, default implementation execute external slot "ret_func_" //! \~english Function executed when thread read some data, default implementation execute external callback "ret_func_"
//! \~russian Метод вызывается после каждого успешного потокового чтения, по умолчанию вызывает callback "ret_func_"
virtual bool threadedRead(uchar * readed, int size); virtual bool threadedRead(uchar * readed, int size);
//! Reimplement to construct full unambiguous string, describes this device. Default implementation returns \a path() //! \~english Reimplement to construct full unambiguous string, describes this device.
//! Default implementation returns \a path()
//! \~russian Переопределите для создания строки полного описания устройства.
//! По умолчанию возвращает \a path()
virtual PIString constructFullPathDevice() const {return path();} virtual PIString constructFullPathDevice() const {return path();}
//! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing //! \~english Reimplement to configure your device with parameters of full unambiguous string.
//! Default implementation call \a setPath()
//! \~russian Переопределите для настройки устройства из строки полного описания.
//! По умолчанию вызывает \a setPath()
virtual void configureFromFullPathDevice(const PIString & full_path) {setPath(full_path);} virtual void configureFromFullPathDevice(const PIString & full_path) {setPath(full_path);}
//! Reimplement to construct device properties. //! \~english Reimplement to construct device properties.
//! Default implementation return PIPropertyStorage with \"path\" entry //! Default implementation return PIPropertyStorage with \"path\" entry
//! \~russian Переопределите для создания свойств устройства.
//! По умолчанию возвращает PIPropertyStorage со свойством \"path\"
virtual PIPropertyStorage constructVariantDevice() const; virtual PIPropertyStorage constructVariantDevice() const;
//! Reimplement to configure your device from PIPropertyStorage. Options and mode already applied. //! \~english Reimplement to configure your device from PIPropertyStorage. Options and mode already applied.
//! Default implementation apply \"path\" entry //! Default implementation apply \"path\" entry
//! \~russian Переопределите для настройки устройства из PIPropertyStorage. Опции и режим уже применены.
//! По умолчанию устанавливает свойство \"path\"
virtual void configureFromVariantDevice(const PIPropertyStorage & d); virtual void configureFromVariantDevice(const PIPropertyStorage & d);
//! Reimplement to apply new device options //! \~english Reimplement to apply new device options
//! \~russian Переопределите для применения новых опций устройства
virtual void optionsChanged() {;} virtual void optionsChanged() {;}
//! Reimplement to return correct \a DeviceInfoFlags. Default implementation returns 0 //! \~english Reimplement to return correct \a DeviceInfoFlags. Default implementation returns 0
//! \~russian Переопределите для возврата правильных \a DeviceInfoFlags. По умолчанию возвращает 0
virtual DeviceInfoFlags deviceInfoFlags() const {return 0;} virtual DeviceInfoFlags deviceInfoFlags() const {return 0;}
//! Reimplement to apply new \a threadedReadBufferSize() //! \~english Reimplement to apply new \a threadedReadBufferSize()
//! \~russian Переопределите для применения нового \a threadedReadBufferSize()
virtual void threadedReadBufferSizeChanged() {;} virtual void threadedReadBufferSizeChanged() {;}
//! Invoked after hard read thread stop //! \~english Invoked after hard read thread stop
//! \~russian Вызывается после жесткой остановки потока чтения
virtual void threadedReadTerminated() {;} virtual void threadedReadTerminated() {;}
//! Invoked after hard write thread stop //! \~english Invoked after hard write thread stop
//! \~russian Вызывается после жесткой остановки потока записи
virtual void threadedWriteTerminated() {;} virtual void threadedWriteTerminated() {;}
static PIIODevice * newDeviceByPrefix(const PIString & prefix); static PIIODevice * newDeviceByPrefix(const char * prefix);
void terminate(); void terminate();
@@ -408,6 +535,7 @@ private:
void run(); void run();
void end() {terminate();} void end() {terminate();}
static void cacheFullPath(const PIString & full_path, const PIIODevice * d); static void cacheFullPath(const PIString & full_path, const PIIODevice * d);
static PIMap<PIConstChars, FabricInfo> & fabrics();
PITimer timer; PITimer timer;
PITimeMeasurer tm; PITimeMeasurer tm;

View File

@@ -16,16 +16,16 @@
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 IO //! \defgroup IO IO
//! \~\brief //! \~\brief
//! \~english Input/output devices. //! \~english Input/output devices.
//! \~russian Устройства ввода/вывода. //! \~russian Устройства ввода/вывода.
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_IO Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_IO Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP) //! target_link_libraries([target] PIP)
//! \endcode //! \endcode

View File

@@ -20,12 +20,15 @@
#include "piiostring.h" #include "piiostring.h"
/*! \class PIIOString //! \class PIIOString piiostring.h
* \brief PIIODevice wrapper around PIString //! \details
* //! \~english
* \section PIIOString_sec0 Synopsis //! This class allow you to use PIString as PIIODevice, e.g. to pass it to PIConfig.
* This class allow you to use PIString as PIIODevice and pass it to, e.g. PIConfig //!
*/ //! \~russian
//! Этот класс позволяет использовать PIString в качестве PIIODevice, например,
//! для передачи в PIConfig.
//!
PIIOString::PIIOString(PIString * string, PIIODevice::DeviceMode mode) { PIIOString::PIIOString(PIString * string, PIIODevice::DeviceMode mode) {
@@ -67,8 +70,9 @@ int PIIOString::readDevice(void * read_to, int max_size) {
PIString rs = str->mid(pos, max_size); PIString rs = str->mid(pos, max_size);
pos += max_size; pos += max_size;
if (pos > str->size_s()) pos = str->size_s(); if (pos > str->size_s()) pos = str->size_s();
int ret = rs.lengthAscii(); const char * cc = rs.data();
memcpy(read_to, rs.data(), rs.lengthAscii()); int ret = strlen(cc);
memcpy(read_to, cc, ret);
return ret; return ret;
} }
@@ -81,7 +85,7 @@ int PIIOString::writeDevice(const void * data, int max_size) {
if (rs.size_s() > max_size) rs.resize(max_size); if (rs.size_s() > max_size) rs.resize(max_size);
str->insert(pos, rs); str->insert(pos, rs);
pos += rs.size_s(); pos += rs.size_s();
return rs.lengthAscii(); return strlen((const char *)data);
} }
@@ -90,7 +94,7 @@ int PIIOString::writeString(const PIString & string) {
if (pos > str->size_s()) pos = str->size_s(); if (pos > str->size_s()) pos = str->size_s();
str->insert(pos, string); str->insert(pos, string);
pos += string.size_s(); pos += string.size_s();
return string.lengthAscii(); return string.size_s();
} }

View File

@@ -29,47 +29,63 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english PIIODevice wrapper around PIString.
//! \~russian Обёртка PIIODevice вокруг PIString.
class PIP_EXPORT PIIOString: public PIIODevice class PIP_EXPORT PIIOString: public PIIODevice
{ {
PIIODEVICE(PIIOString) PIIODEVICE(PIIOString, "")
public: public:
//! Contructs %PIIOString with \"string\" content and \"mode\" open mode //! \~english Contructs %PIIOString with "string" content and "mode" open mode
//! \~russian Создает %PIIOString с содержимым "string" и режимом открытия "mode"
explicit PIIOString(PIString * string = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PIIOString(PIString * string = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Contructs %PIIOString with \"string\" content only for read //! \~english Contructs %PIIOString with "string" content only for read
//! \~russian Создает %PIIOString с содержимым "string" только для чтения
explicit PIIOString(const PIString & string); explicit PIIOString(const PIString & string);
//! Returns content //! \~english Returns content
//! \~russian Возвращает содержимое
PIString * string() const {return str;} PIString * string() const {return str;}
//! Clear content string //! \~english Clear content string
//! \~russian Очищает содержимое строки
void clear() {if (str) str->clear(); pos = 0;} void clear() {if (str) str->clear(); pos = 0;}
//! Open \"string\" content with \"mode\" open mode //! \~english Open "string" content with "mode" open mode
//! \~russian Открывает содержимое "string" с режимом открытия "mode"
bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Open \"string\" content only for read //! \~english Open "string" content only for read
//! \~russian Открывает содержимое "string" только для чтения
bool open(const PIString & string); bool open(const PIString & string);
//! Returns if position is at the end of content //! \~english Returns if position is at the end of content
//! \~russian Возвращает в конце содержимого ли позиция
bool isEnd() const {if (!str) return true; return pos >= str->size_s();} bool isEnd() const {if (!str) return true; return pos >= str->size_s();}
//! Move read/write position to \"position\" //! \~english Move read/write position to "position"
//! \~russian Перемещает позицию чтения/записи на "position"
void seek(llong position) {pos = position;} void seek(llong position) {pos = position;}
//! Move read/write position to the begin of the string //! \~english Move read/write position to the beginning of the string
//! \~russian Перемещает позицию чтения/записи на начало строки
void seekToBegin() {if (str) pos = 0;} void seekToBegin() {if (str) pos = 0;}
//! Move read/write position to the end of the string //! \~english Move read/write position to the end of the string
//! \~russian Перемещает позицию чтения/записи на конец строки
void seekToEnd() {if (str) pos = str->size_s();} void seekToEnd() {if (str) pos = str->size_s();}
//! Read one text line and return it //! \~english Read one text line and return it
//! \~russian Читает одну строку и возвращает её
PIString readLine(); PIString readLine();
//! Insert string \"string\" into content at current position //! \~english Insert string "string" into content at current position
//! \~russian Вставляет строку "string" в содержимое буфера в текущую позицию
int writeString(const PIString & string); int writeString(const PIString & string);
protected: protected:

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PIPeer: public PIIODevice class PIP_EXPORT PIPeer: public PIIODevice
{ {
PIIODEVICE(PIPeer) PIIODEVICE(PIPeer, "peer")
private: private:
class PeerData; class PeerData;
@@ -168,7 +168,6 @@ private:
bool openDevice(); bool openDevice();
bool closeDevice(); bool closeDevice();
PIString fullPathPrefix() const {return PIStringAscii("peer");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString &full_path); void configureFromFullPathDevice(const PIString &full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;

View File

@@ -137,21 +137,33 @@
#endif #endif
/*! \class PISerial //! \class PISerial piserial.h
* \brief Serial device //! \details
* //! \~english \section PISerial_sec0 Synopsis
* \section PISerial_sec0 Synopsis //! \~russian \section PISerial_sec0 Краткий обзор
* This class provide access to serial device, e.g. COM port. It can read, //! \~english
* write, wait for write. There are several read and write functions. //! This class provide access to serial device, e.g. COM port. It can read,
* //! write, wait for write. There are several read and write functions.
* \section PISerial_sec1 FullPath //!
* Since version 1.16.0 you can use as \a path DeviceInfo::id() USB identifier. //! \~russian
* \code //! Этот класс предоставляет доступ к последовательному порту, например, COM-порт.
* PISerial * s = new PISerial("0403:6001"); //!
* PIIODevice * d = PIIODevice::createFromFullPath("ser://0403:6001:115200"); //! \~english \section PISerial_sec1 FullPath
* \endcode //! \~russian \section PISerial_sec1 Строка полного описания
* //! \~english
*/ //! Since version 1.16.0 you can use as \a path \a PISerial::DeviceInfo::id() USB identifier
//! for USB devices.
//!
//! \~russian
//! Начиная с версии 1.16.0 можно в качестве \a path использовать \a PISerial::DeviceInfo::id()
//! USB идентификатор для USB устройств.
//!
//! \~\code
//! PISerial * s = new PISerial("0403:6001");
//! PIIODevice * d = PIIODevice::createFromFullPath("ser://0403:6001:115200");
//! \endcode
//!
REGISTER_DEVICE(PISerial) REGISTER_DEVICE(PISerial)
@@ -289,6 +301,16 @@ bool PISerial::isRNG() const {return isBit(TIOCM_RNG, "RNG");}
bool PISerial::isDSR() const {return isBit(TIOCM_DSR, "DSR");} bool PISerial::isDSR() const {return isBit(TIOCM_DSR, "DSR");}
//! \~\details
//! \~english
//! If enabled, sends a continuous stream of zero bits.
//! Returns if state changed successfully.
//! \note The serial port has to be open before using this method
//!
//! \~russian
//! Если включено, отсылается непрерывный поток нулей.
//! Возвращает успешна ли смена состояния.
//! \note Порт должен быть открыт перед использованием этого метода
bool PISerial::setBreak(bool enabled) { bool PISerial::setBreak(bool enabled) {
if (fd < 0) { if (fd < 0) {
piCoutObj << "sendBreak error: \"" << path() << "\" is not opened!"; piCoutObj << "sendBreak error: \"" << path() << "\" is not opened!";
@@ -416,14 +438,24 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
} }
/** \brief Advanced read function //! \details
* \details Read to pointer "read_to" no more than "max_size" and no longer //! \~english
* than "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be //! Read to pointer "read_to" no more than "max_size" and no longer
* wait forever until "max_size" will be readed. If size <= 0 function //! than "timeout_ms" milliseconds.\n
* immediate returns \b false. For read data with unknown size use function //! If "timeout_ms" < 0 function will be wait forever until "max_size" will be readed.\n
* \a readData(). //! If "size" <= 0 function immediate returns \b false.\n
* \returns \b True if readed bytes count = "max_size", else \b false //! For read data with unknown size use function \a readData().
* \sa \a readData() */ //! \returns If readed bytes count = "max_size"
//!
//! \~russian
//! Читает в указатель "read_to" не более "max_size" байт и не дольше
//! чем "timeout_ms" миллисекунд.\n
//! Если "timeout_ms" < 0 метод ожидает бесконечно, пока не будет прочитано "max_size" байт.\n
//! Если "size" <= 0, то метод немедленно возвращает \b false.\n
//! Для чтения данных неизвестного размера используется метод \a readData().
//! \returns Если количество прочитанных байт = "max_size"
//!
//! \sa \a readString(), \a readData()
bool PISerial::read(void * data, int size, double timeout_ms) { bool PISerial::read(void * data, int size, double timeout_ms) {
if (data == 0 || size <= 0) return false; if (data == 0 || size <= 0) return false;
int ret, all = 0; int ret, all = 0;
@@ -454,15 +486,25 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
} }
/** \brief Advanced read function //! \details
* \details Read all or no more than "size" and no longer than //! \~english
* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be //! Read all or no more than "size" bytes and no longer than "timeout_ms" milliseconds.\n
* wait forever until "size" will be readed. If "size" <= 0 //! If "timeout_ms" < 0 function will be wait forever until "max_size" will be readed.\n
* function will be read all until "timeout_ms" elaped. \n If size <= 0 //! If "size" <= 0 function will be read all until "timeout_ms" elaped.\n
* and "timeout_ms" <= 0 function immediate returns empty string. //! If "size" <= 0 and "timeout_ms" <= 0 function immediate returns empty string.\n
* \n This function similar to \a readData() but returns data as string. //! This function similar to \a readData() but returns data as string.
* \sa \a readData() */ //! \returns If readed bytes count = "max_size"
PIString PISerial::read(int size, double timeout_ms) { //!
//! \~russian
//! Читает всё или не более "size" байт и не дольше чем "timeout_ms" миллисекунд.\n
//! Если "timeout_ms" < 0 метод ожидает бесконечно, пока не будет прочитано "max_size" байт.\n
//! Если "size" <= 0, то читает всё в течении "timeout_ms" миллисекунд.\n
//! Если "size" <= 0 и "timeout_ms" <= 0, то метод немедленно возвращает пустую строку.\n
//! Этот метод аналогичен \a readData(), но возвращает строку.
//! \returns Если количество прочитанных байт = "max_size"
//!
//! \sa \a readData()
PIString PISerial::readString(int size, double timeout_ms) {
PIString str; PIString str;
if (size <= 0 && timeout_ms <= 0.) return str; if (size <= 0 && timeout_ms <= 0.) return str;
int ret, all = 0; int ret, all = 0;
@@ -506,14 +548,24 @@ PIString PISerial::read(int size, double timeout_ms) {
} }
/** \brief Advanced read function //! \details
* \details Read all or no more than "size" and no longer than //! \~english
* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be //! Read all or no more than "size" bytes and no longer than "timeout_ms" milliseconds.\n
* wait forever until "size" will be readed. If "size" <= 0 //! If "timeout_ms" < 0 function will be wait forever until "max_size" will be readed.\n
* function will be read all until "timeout_ms" elaped. \n If size <= 0 //! If "size" <= 0 function will be read all until "timeout_ms" elaped.\n
* and "timeout_ms" <= 0 function immediate returns empty byte array. //! If "size" <= 0 and "timeout_ms" <= 0 function immediate returns empty string.\n
* \n This function similar to \a read() but returns data as byte array. //! This function similar to \a readString() but returns data as byte array.
* \sa \a read() */ //! \returns If readed bytes count = "max_size"
//!
//! \~russian
//! Читает всё или не более "size" байт и не дольше чем "timeout_ms" миллисекунд.\n
//! Если "timeout_ms" < 0 метод ожидает бесконечно, пока не будет прочитано "max_size" байт.\n
//! Если "size" <= 0, то читает всё в течении "timeout_ms" миллисекунд.\n
//! Если "size" <= 0 и "timeout_ms" <= 0, то метод немедленно возвращает пустую строку.\n
//! Этот метод аналогичен \a readString(), но возвращает массив байт.
//! \returns Если количество прочитанных байт = "max_size"
//!
//! \sa \a readString()
PIByteArray PISerial::readData(int size, double timeout_ms) { PIByteArray PISerial::readData(int size, double timeout_ms) {
PIByteArray str; PIByteArray str;
if (size <= 0 && timeout_ms <= 0.) return str; if (size <= 0 && timeout_ms <= 0.) return str;
@@ -722,11 +774,20 @@ void PISerial::setTimeouts() {
} }
/** \brief Basic read function //! \details
* \details Read to pointer "read_to" no more than "max_size". If read is //! \~english
* set to blocking this function will be wait at least one byte. //! Read to pointer "read_to" no more than "max_size".
* \returns Readed bytes count //! If \a PIIODevice::BlockingRead option set this function
* \sa \a readData() */ //! will be wait at least one byte.
//! \returns Readed bytes count, -1 for error
//!
//! \~russian
//! Читает в указатель "read_to" не более "max_size" байт.
//! Если установлена опция \a PIIODevice::BlockingRead,
//! то этот метод ожидает хотя бы одного байта.
//! \returns Количество прочитанных байт, -1 при ошибке
//!
//! \~\sa \a readData(), \a readString()
int PISerial::readDevice(void * read_to, int max_size) { int PISerial::readDevice(void * read_to, int max_size) {
#ifdef WINDOWS #ifdef WINDOWS
if (!canRead()) return -1; if (!canRead()) return -1;

View File

@@ -29,22 +29,32 @@
#include "pitimer.h" #include "pitimer.h"
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english Serial device.
//! \~russian Последовательный порт.
class PIP_EXPORT PISerial: public PIIODevice class PIP_EXPORT PISerial: public PIIODevice
{ {
PIIODEVICE(PISerial) PIIODEVICE(PISerial, "ser")
public: public:
//! Contructs an empty %PISerial //! \~english Contructs an empty %PISerial
//! \~russian Создает пустой %PISerial
explicit PISerial(); explicit PISerial();
//! \brief Parameters of PISerial virtual ~PISerial();
//! \~english Parameters of PISerial
//! \~russian Параметры PISerial
enum Parameters { enum Parameters {
ParityControl /*! Enable parity check and generate */ = 0x1, ParityControl /*! \~english Enable parity check and generate \~russian Включить генерацию и проверку контроля чётности */ = 0x1,
ParityOdd /*! Parity is odd instead of even */ = 0x2, ParityOdd /*! \~english Parity is odd instead of even \~russian Нечётный контроль чётности вместо чётного */ = 0x2,
TwoStopBits /*! Two stop bits instead of one */ = 0x4 TwoStopBits /*! \~english Two stop bits instead of one \~russian Два стоповых бита вместо одного */ = 0x4
}; };
//! \brief Speed of PISerial //! \~english Speed of PISerial
//! \~russian Скорость PISerial
enum Speed { enum Speed {
S50 /*! 50 baud */ = 50, S50 /*! 50 baud */ = 50,
S75 /*! 75 baud */ = 75, S75 /*! 75 baud */ = 75,
@@ -75,72 +85,93 @@ public:
S4000000 /*! 4000000 baud */ = 4000000 S4000000 /*! 4000000 baud */ = 4000000
}; };
//! \brief Information about serial device //! \ingroup IO
//! \~\brief
//! \~english Information about serial device
//! \~russian Информация о последовательном устройстве
struct PIP_EXPORT DeviceInfo { struct PIP_EXPORT DeviceInfo {
DeviceInfo(); DeviceInfo();
//! \brief String representation of USB ID in format \"xxxx:xxxx\" //! \~english Returns string representation of USB ID in format "xxxx:xxxx" (vID:pID)
//! \~russian Возвращает строковое представление USB ID в формате "xxxx:xxxx" (vID:pID)
PIString id() const; PIString id() const;
//! \brief USB Vendor ID //! \~english USB Vendor ID
//! \~russian USB Vendor ID
uint vID; uint vID;
//! \brief USB Product ID //! \~english USB Product ID
//! \~russian USB Product ID
uint pID; uint pID;
//! \brief Path to device, e.g. "COM2" or "/dev/ttyUSB0" //! \~english Path to device, e.g. "COM2" or "/dev/ttyUSB0"
//! \~russian Путь к устройству, например "COM2" или "/dev/ttyUSB0"
PIString path; PIString path;
//! \brief Device description //! \~english Device description
//! \~russian Описание устройства
PIString description; PIString description;
//! \brief Device manufacturer //! \~english Device manufacturer
//! \~russian Описание производителя
PIString manufacturer; PIString manufacturer;
}; };
//! Contructs %PISerial with device name "device", speed "speed" and parameters "params" //! \~english Contructs %PISerial with device name "device", speed "speed" and parameters "params"
//! \~russian Создает %PISerial с именем устройства "device", скоростью "speed" и параметрами "params"
explicit PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags<PISerial::Parameters> params = 0); explicit PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags<PISerial::Parameters> params = 0);
virtual ~PISerial();
//! \~english Set both input and output speed to "speed"
//! Set both input and output speed to "speed" //! \~russian Устанавливает скорости приема и передачи в "speed"
void setSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); setProperty("inSpeed", (int)speed); applySettings();} void setSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); setProperty("inSpeed", (int)speed); applySettings();}
//! Set output speed to "speed" //! \~english Set output speed to "speed"
//! \~russian Устанавливает скорость передачи в "speed"
void setOutSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); applySettings();} void setOutSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); applySettings();}
//! Set input speed to "speed" //! \~english Set input speed to "speed"
//! \~russian Устанавливает скорость приема в "speed"
void setInSpeed(PISerial::Speed speed) {setProperty("inSpeed", (int)speed); applySettings();} void setInSpeed(PISerial::Speed speed) {setProperty("inSpeed", (int)speed); applySettings();}
//! Set device name to "dev" //! \~english Set device name to "dev"
//! \~russian Устанавливает имя устройства в "dev"
void setDevice(const PIString & dev) {setPath(dev); if (isOpened()) {close(); open();};} void setDevice(const PIString & dev) {setPath(dev); if (isOpened()) {close(); open();};}
//! Set parameters to "parameters_" //! \~english Set parameters to "parameters_"
//! \~russian Устанавливает параметры в "parameters_"
void setParameters(PIFlags<PISerial::Parameters> parameters_) {setProperty("parameters", (int)parameters_); applySettings();} void setParameters(PIFlags<PISerial::Parameters> parameters_) {setProperty("parameters", (int)parameters_); applySettings();}
//! Set parameter "parameter" to "on" state //! \~english Set parameter "parameter" to "on" state
//! \~russian Устанавливает параметр "parameter" в "on"
void setParameter(PISerial::Parameters parameter, bool on = true); void setParameter(PISerial::Parameters parameter, bool on = true);
//! Returns if parameter "parameter" is set //! \~english Returns if parameter "parameter" is set
//! \~russian Возвращает установлен ли параметр "parameter"
bool isParameterSet(PISerial::Parameters parameter) const; bool isParameterSet(PISerial::Parameters parameter) const;
//! Returns parameters //! \~english Returns parameters
//! \~russian Возвращает параметры
PIFlags<PISerial::Parameters> parameters() const {return (PIFlags<Parameters>)(property("parameters").toInt());} PIFlags<PISerial::Parameters> parameters() const {return (PIFlags<Parameters>)(property("parameters").toInt());}
//! Set data bits count. Valid range is from 5 to 8, befault is 8 //! \~english Set data bits count. Valid range is from 5 to 8, befault is 8
//! \~russian Устанавливает количество бит данных. Разрешены значения от 5 до 8, по умолчанию 8
void setDataBitsCount(int bits) {setProperty("dataBitsCount", bits); applySettings();} void setDataBitsCount(int bits) {setProperty("dataBitsCount", bits); applySettings();}
//! Returns data bits count //! \~english Returns data bits count
//! \~russian Возвращает количество бит данных
int dataBitsCount() const {return property("dataBitsCount").toInt();} int dataBitsCount() const {return property("dataBitsCount").toInt();}
//! Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS) //! \~english Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS)
//! \~russian Устанавливает пин с номером "number" в логический уровень "on". Разрешены номера 4 (DTR) и 7 (RTS)
bool setPin(int number, bool on); bool setPin(int number, bool on);
//! Returns pin number "number" logic level. Valid numbers range is from 1 to 9 //! \~english Returns pin number "number" logic level. Valid numbers range is from 1 to 9
//! \~russian Возвращает логический уровень пина с номером "number". Разрешены номера от 1 до 9
bool isPin(int number) const; bool isPin(int number) const;
bool setLE(bool on); // useless function, just formally bool setLE(bool on); // useless function, just formally
@@ -163,75 +194,94 @@ public:
bool isRNG() const; bool isRNG() const;
bool isDSR() const; bool isDSR() const;
//! Switch transmission line in break if enabled. //! \~english Switch transmission line in break
//! i.e. sends a continuous stream of zero bits. //! \~russian Переключает состояние передачи в break
//! If successful, returns true; otherwise returns false.
//! The serial port has to be open before trying to send a break duration; otherwise returns false
bool setBreak(bool enabled); bool setBreak(bool enabled);
void setVTime(int t) {vtime = t; applySettings();} void setVTime(int t) {vtime = t; applySettings();}
//! Returns device name //! \~english Returns device name
//! \~russian Возвращает имя устройства
PIString device() const {return path();} PIString device() const {return path();}
//! Returns output speed //! \~english Returns output speed
//! \~russian Возвращает скорость передачи
PISerial::Speed outSpeed() const {return (PISerial::Speed)(property("outSpeed").toInt());} PISerial::Speed outSpeed() const {return (PISerial::Speed)(property("outSpeed").toInt());}
//! Returns input speed //! \~english Returns input speed
//! \~russian Возвращает скорость приема
PISerial::Speed inSpeed() const {return (PISerial::Speed)(property("inSpeed").toInt());} PISerial::Speed inSpeed() const {return (PISerial::Speed)(property("inSpeed").toInt());}
int VTime() const {return vtime;} int VTime() const {return vtime;}
//! Discard all buffered input and output data //! \~english Discard all buffered input and output data
//! \~russian Откидывает все буферизированные данные для передачи и приема
void flush(); void flush();
int read(void * read_to, int max_size) {return readDevice(read_to, max_size);} int read(void * read_to, int max_size) {return readDevice(read_to, max_size);}
//! \~english Read from device no more "max_size" bytes into "read_to" with "timeout_ms" timeout
//! \~russian Читает из устройства не более "max_size" байт в "read_to" с таймаутом "timeout_ms"
bool read(void * read_to, int max_size, double timeout_ms); bool read(void * read_to, int max_size, double timeout_ms);
PIString read(int size = -1, double timeout_ms = 1000.);
//! \~english Read from device for "timeout_ms" timeout or for "size" bytes
//! \~russian Читает из устройства в течении таймаута "timeout_ms" или до "size" байт
PIString readString(int size = -1, double timeout_ms = 1000.);
//! \~english Read from device for "timeout_ms" timeout or for "size" bytes
//! \~russian Читает из устройства в течении таймаута "timeout_ms" или до "size" байт
PIByteArray readData(int size = -1, double timeout_ms = 1000.); PIByteArray readData(int size = -1, double timeout_ms = 1000.);
//! \brief Write to device data "data" with maximum size "size" and wait for data written if "wait" is \b true. //! \~english Write to device data "data" with maximum size "size". Returns if sended bytes count = "size"
//! \returns \b true if sended bytes count = "size" //! \~russian Пишет в порт не более "size" байт данных "data". Возвращает если количество записанных байт = "size"
bool send(const void * data, int size); bool send(const void * data, int size);
//! \brief Write to device byte array "data" //! \~english Write to device byte array "data". Returns if sended bytes count = size of "data"
//! \returns \b true if sended bytes count = size of string //! \~russian Пишет в порт байтовый массив "data". Возвращает если количество записанных байт = размер "data"
bool send(const PIByteArray & data) {return send(data.data(), data.size_s());} bool send(const PIByteArray & data) {return send(data.data(), data.size_s());}
//! \brief Returns all available speeds for serial devices //! \~english Returns all available speeds for serial devices
//! \~russian Возвращает все возможные скорости для устройств
static PIVector<int> availableSpeeds(); static PIVector<int> availableSpeeds();
//! \brief Returns all available system devices path. If "test" each device will be tried to open //! \~english Returns all available system devices path. If "test" each device will be tried to open
//! \~russian Возвращает пути всех доступных устройств в системе. Если "test", то каждое устройство будет опробовано на открытие
static PIStringList availableDevices(bool test = false); static PIStringList availableDevices(bool test = false);
//! \brief Returns all available system devices. If "test" each device will be tried to open //! \~english Returns all available system devices. If "test" each device will be tried to open
//! \~russian Возвращает все доступные устройства в системе. Если "test", то каждое устройство будет опробовано на открытие
static PIVector<DeviceInfo> availableDevicesInfo(bool test = false); static PIVector<DeviceInfo> availableDevicesInfo(bool test = false);
//! \ioparams //! \ioparams
//! \{ //! \{
#ifdef DOXYGEN #ifdef DOXYGEN
//! \brief device, default "" //! \~english device, default ""
//! \~russian устройство, по умолчанию ""
string device; string device;
//! \brief input/output speed, default 115200 //! \~english input/output speed, default 115200
//! \~russian скорость чтения/записи, по умолчанию 115200
int speed; int speed;
//! \brief dataBitsCount, default 8 //! \~english dataBitsCount, default 8
//! \~russian количесво бит данных, по умолчанию 8
int dataBitsCount; int dataBitsCount;
//! \brief parityControl, default false //! \~english parityControl, default false
//! \~russian контроль четности, по умолчанию false
bool parityControl; bool parityControl;
//! \brief parityOdd, default false //! \~english parityOdd, default false
//! \~russian нечётный контроль четности, по умолчанию false
bool parityOdd; bool parityOdd;
//! \brief twoStopBits, default false //! \~english twoStopBits, default false
//! \~russian два стоповых бита, по умолчанию false
bool twoStopBits; bool twoStopBits;
#endif #endif
//! \} //! \}
protected: protected:
PIString fullPathPrefix() const {return PIStringAscii("ser");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;
@@ -239,6 +289,9 @@ protected:
bool configureDevice(const void * e_main, const void * e_parent = 0); bool configureDevice(const void * e_main, const void * e_parent = 0);
void optionsChanged(); void optionsChanged();
void threadedReadBufferSizeChanged(); void threadedReadBufferSizeChanged();
//! \~english Basic read function
//! \~russian Базовое чтение
int readDevice(void * read_to, int max_size); int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size); int writeDevice(const void * data, int max_size);
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Sequential;} DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Sequential;}
@@ -264,14 +317,30 @@ protected:
}; };
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PISerial::DeviceInfo & v) { inline PICout operator <<(PICout s, const PISerial::DeviceInfo & v) {
s << v.path << " (" << v.id() << ", \"" << v.manufacturer << "\", \"" << v.description << "\")"; s << v.path << " (" << v.id() << ", \"" << v.manufacturer << "\", \"" << v.description << "\")";
return s; return s;
} }
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator ==(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) {return v0.path == v1.path;} inline bool operator ==(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) {return v0.path == v1.path;}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) {return v0.path != v1.path;} inline bool operator !=(const PISerial::DeviceInfo & v0, const PISerial::DeviceInfo & v1) {return v0.path != v1.path;}
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const PISerial::DeviceInfo & v) {s << v.vID << v.pID << v.path << v.description << v.manufacturer; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PISerial::DeviceInfo & v) {s << v.vID << v.pID << v.path << v.description << v.manufacturer; return s;}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, PISerial::DeviceInfo & v) {s >> v.vID >> v.pID >> v.path >> v.description >> v.manufacturer; return s;} inline PIByteArray & operator >>(PIByteArray & s, PISerial::DeviceInfo & v) {s >> v.vID >> v.pID >> v.path >> v.description >> v.manufacturer; return s;}

View File

@@ -40,25 +40,24 @@
#endif #endif
/*! \class PISharedMemory //! \class PISharedMemory pisharedmemory.h
* \brief Shared memory //! \details
* //! \~english
* \section PISharedMemory_sec0 Synopsis //!
* This class provide access to local file. You can manipulate //!
* binary content or use this class as text stream. To binary //! \~russian
* access there are function \a read(), \a write(), and many //! Разделяемая память используется как единое хранилище данных,
* \a writeBinary() functions. For write variables to file in //! доступное различным процессам по имени. При первом открытии
* their text representation threr are many "<<" operators. //! объекта разделяемой памяти выделяется \a size() байт, по умолчанию
* //! 65 Кб. Все процессы должны использовать один и тот же \a size()
* \section PISharedMemory_sec1 Position //! во избежании ошибок.
* Each opened file has a read/write position - logical position //!
* in the file content you read from or you write to. You can //! У объекта разделяемой памяти нету позиции чтения/записи,
* find out current position with function \a pos(). Function //! каждый вызов \a read() или \a write() обращается
* \a seek(llong position) move position to position "position", //! к началу памяти. Для работы с конкретным участком памяти
* \a seekToBegin() move position to the begin of file, //! используются перегруженные методы с указанием "offset".
* \a seekToEnd() move position to the end of file. //!
*
*/
REGISTER_DEVICE(PISharedMemory) REGISTER_DEVICE(PISharedMemory)

View File

@@ -29,54 +29,70 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english Shared memory.
//! \~russian Разделяемая память.
class PIP_EXPORT PISharedMemory: public PIIODevice class PIP_EXPORT PISharedMemory: public PIIODevice
{ {
PIIODEVICE(PISharedMemory) PIIODEVICE(PISharedMemory, "shm")
public: public:
//! \~english Constructs empty %PISharedMemory
//! \~russian Создает пустой %PISharedMemory
explicit PISharedMemory(); explicit PISharedMemory();
//! Constructs a shared memory object with name "shm_name", size "size" and open mode "mode" //! \~english Constructs a shared memory object with name "shm_name", size "size" and open mode "mode"
//! \~russian Создает объект разделяемой памяти с именем "shm_name", размером "size" и режимом открытия "mode"
explicit PISharedMemory(const PIString & shm_name, int size, DeviceMode mode = ReadWrite); explicit PISharedMemory(const PIString & shm_name, int size, DeviceMode mode = ReadWrite);
virtual ~PISharedMemory(); virtual ~PISharedMemory();
//! Read all shared memory object content to byte array and return it
//! \~english Read all shared memory content and return it as byte array
//! \~russian Читает всю разделяемую память и возвращает её как байтовый массив
PIByteArray readAll(); PIByteArray readAll();
//! Returns shared memory object size //! \~english Returns shared memory size
//! \~russian Возвращает размер разделяемой памяти
llong size() const; llong size() const;
//! Set shared memory object size //! \~english Set shared memory size
//! \~russian Устанавливает размер разделяемой памяти
void setSize(llong s); void setSize(llong s);
//! Returns if shared memory object is empty //! \~english Returns if shared memory object is empty (by size)
//! \~russian Возвращает пустой ли объект разделяемой памяти (по размеру)
bool isEmpty() const {return (size() <= 0);} bool isEmpty() const {return (size() <= 0);}
//! Read from shared memory object to "read_to" no more than "max_size" and return readed bytes count //! \~english Read from shared memory to "read_to" no more than "max_size" and return readed bytes count
//! \~russian Читает из разделяемой памяти в "read_to" не более "max_size" и возвращает количество прочитанных байт
int read(void * read_to, int max_size); int read(void * read_to, int max_size);
//! Read from shared memory object to "read_to" no more than "max_size" and return readed bytes count //! \~english Read from shared memory started from "offset" to "read_to" no more than "max_size" and return readed bytes count
//! \~russian Читает из разделяемой памяти с начала "offset" в "read_to" не более "max_size" и возвращает количество прочитанных байт
int read(void * read_to, int max_size, int offset); int read(void * read_to, int max_size, int offset);
//! Write to shared memory object "data" with size "max_size" and return written bytes count //! \~english Write to shared memory "data" with size "max_size" and return written bytes count
//! \~russian Пишет в разделяемую память "data" размером "max_size" и возвращает количество записанных байт
int write(const void * data, int max_size); int write(const void * data, int max_size);
//! Write to shared memory object "data" with size "max_size" and return written bytes count //! \~english Write to shared memory started from "offset" "data" with size "max_size" and return written bytes count
//! \~russian Пишет в разделяемую память с начала "offset" "data" размером "max_size" и возвращает количество записанных
int write(const void * data, int max_size, int offset); int write(const void * data, int max_size, int offset);
//! Write "data" to shared memory object //! \~english Write "data" to shared memory
//! \~russian Пишет в разделяемую память "data"
int write(const PIByteArray & data) {return write(data.data(), data.size_s());} int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
//! Write "data" to shared memory object //! \~english Write "data" to shared memory
//! \~russian Пишет в разделяемую память "data"
int write(const PIByteArray & data, int offset) {return write(data.data(), data.size_s(), offset);} int write(const PIByteArray & data, int offset) {return write(data.data(), data.size_s(), offset);}
protected: protected:
bool openDevice(); bool openDevice();
bool closeDevice(); bool closeDevice();
PIString fullPathPrefix() const {return PIStringAscii("shm");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PISPI: public PIIODevice class PIP_EXPORT PISPI: public PIIODevice
{ {
PIIODEVICE(PISPI) PIIODEVICE(PISPI, "spi")
public: public:
explicit PISPI(const PIString & path = PIString(), uint speed_hz = 1000000, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PISPI(const PIString & path = PIString(), uint speed_hz = 1000000, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PISPI(); virtual ~PISPI();
@@ -67,7 +67,6 @@ protected:
int readDevice(void * read_to, int max_size); int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size); int writeDevice(const void * data, int max_size);
PIString fullPathPrefix() const {return PIStringAscii("spi");}
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const; PIPropertyStorage constructVariantDevice() const;

View File

@@ -20,15 +20,21 @@
#include "pitransparentdevice.h" #include "pitransparentdevice.h"
/*! \class PITransparentDevice //! \class PITransparentDevice pitransparentdevice.h
* \brief PIIODevice that pass write to read //! \details
* //! \~english
* \section PITransparentDevice_sec0 Synopsis //! This class pass all data from \a write() function to \a read().
* This class pass all data from \a write() function to \a read(). //! %PITransparentDevice contains internal queue and works in
* %PITransparentDevice contains internal queue and works in //! packets mode. If you write 3 different packets into this device,
* packets mode. If you write 3 different packets into this device, //! read will return this 3 packets.
* read will return this 3 packets. //!
*/ //! \~russian
//! Этот класс транслирует все данные с метода \a write() на метод
//! \a read(). %PITransparentDevice содержит внутреннюю очередь и работает
//! в пакетном режиме. Если запишется 3 различных пакета в устройство,
//! то чтение вернет по очереди эти 3 пакета.
//!
REGISTER_DEVICE(PITransparentDevice) REGISTER_DEVICE(PITransparentDevice)

View File

@@ -29,12 +29,17 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english PIIODevice that pass write to read.
//! \~russian PIIODevice который транслирует запись на чтение.
class PIP_EXPORT PITransparentDevice: public PIIODevice class PIP_EXPORT PITransparentDevice: public PIIODevice
{ {
PIIODEVICE(PITransparentDevice) PIIODEVICE(PITransparentDevice, "tr")
public: public:
//! Contructs empty %PITransparentDevice //! \~english Contructs empty %PITransparentDevice
//! \~russian Создает пустой %PITransparentDevice
explicit PITransparentDevice(); explicit PITransparentDevice();
virtual ~PITransparentDevice(); virtual ~PITransparentDevice();
@@ -44,7 +49,6 @@ protected:
bool closeDevice(); bool closeDevice();
int readDevice(void * read_to, int max_size); int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size); int writeDevice(const void * data, int max_size);
PIString fullPathPrefix() const {return PIStringAscii("tr");}
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;} DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
PIMutex que_mutex; PIMutex que_mutex;

View File

@@ -22,16 +22,16 @@
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 USB //! \defgroup USB USB
//! \~\brief //! \~\brief
//! \~english USB support via libusb //! \~english USB support via libusb
//! \~russian Поддержка USB с помощью libusb //! \~russian Поддержка USB с помощью libusb
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_USB Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_USB Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::USB) //! target_link_libraries([target] PIP::USB)
//! \endcode //! \endcode
@@ -63,7 +63,7 @@ struct usb_dev_handle;
class PIP_EXPORT PIUSB: public PIIODevice class PIP_EXPORT PIUSB: public PIIODevice
{ {
PIIODEVICE(PIUSB) PIIODEVICE(PIUSB, "usb")
public: public:
explicit PIUSB(ushort vid = 0, ushort pid = 0); explicit PIUSB(ushort vid = 0, ushort pid = 0);
virtual ~PIUSB(); virtual ~PIUSB();
@@ -160,7 +160,6 @@ public:
void flush(); void flush();
protected: protected:
PIString fullPathPrefix() const {return PIStringAscii("usb");}
bool configureDevice(const void * e_main, const void * e_parent = 0); bool configureDevice(const void * e_main, const void * e_parent = 0);
PIString constructFullPathDevice() const; PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path); void configureFromFullPathDevice(const PIString & full_path);

View File

@@ -225,7 +225,7 @@ PIDiagnostics::Entry PIDiagnostics::calcHistory(PIQueue<Entry> & hist, int & cnt
} }
void PIDiagnostics::propertyChanged(const PIString &) { void PIDiagnostics::propertyChanged(const char *) {
float disct = property("disconnectTimeout").toFloat(); float disct = property("disconnectTimeout").toFloat();
changeDisconnectTimeout(disct); changeDisconnectTimeout(disct);
} }

View File

@@ -140,7 +140,7 @@ private:
void tick(void *, int); void tick(void *, int);
Entry calcHistory(PIQueue<Entry> & hist, int & cnt); Entry calcHistory(PIQueue<Entry> & hist, int & cnt);
void propertyChanged(const PIString &); void propertyChanged(const char *);
void changeDisconnectTimeout(float disct); void changeDisconnectTimeout(float disct);
PIQueue<Entry> history_rec, history_send; PIQueue<Entry> history_rec, history_send;

View File

@@ -16,16 +16,16 @@
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 IO-Utils //! \defgroup IO-Utils IO-Utils
//! \~\brief //! \~\brief
//! \~english Complex channel transport //! \~english Complex channel transport
//! \~russian Сложный канальный транспорт //! \~russian Сложный канальный транспорт
//! //!
//! \~\details //! \~\details
//! \~english \section cmake_module Building with CMake //! \~english \section cmake_module_IO_Utils Building with CMake
//! \~russian \section cmake_module Сборка с использованием CMake //! \~russian \section cmake_module_IO_Utils Сборка с использованием CMake
//! //!
//! \code //! \~\code
//! find_package(PIP REQUIRED) //! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::IOUtils) //! target_link_libraries([target] PIP::IOUtils)
//! \endcode //! \endcode

View File

@@ -107,7 +107,7 @@ void PIPacketExtractor::construct() {
} }
void PIPacketExtractor::propertyChanged(const PIString &) { void PIPacketExtractor::propertyChanged(const char *) {
packetSize_ = property("packetSize").toInt(); packetSize_ = property("packetSize").toInt();
mode_ = (SplitMode)(property("splitMode").toInt()); mode_ = (SplitMode)(property("splitMode").toInt());
dataSize = property("payloadSize").toInt(); dataSize = property("payloadSize").toInt();

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