2 Commits

Author SHA1 Message Date
e96b399da7 pip_cmg fix 2022-06-24 16:43:22 +03:00
33eefd7453 pip_cmg namespace fix 2022-06-24 14:46:55 +03:00
187 changed files with 4190 additions and 12439 deletions

View File

@@ -2,52 +2,15 @@ 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 39) set(pip_MINOR 34)
set(pip_REVISION 0) set(pip_REVISION 1)
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)
@@ -488,7 +451,7 @@ if (NOT CROSSTOOLS)
#target_link_libraries(pip_plugin pip) #target_link_libraries(pip_plugin pip)
add_executable(pip_test "main.cpp") add_executable(pip_test "main.cpp")
target_link_libraries(pip_test pip) target_link_libraries(pip_test pip pip_cloud pip_lua)
endif() endif()
else() else()
@@ -587,11 +550,6 @@ 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}\"")
@@ -616,9 +574,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\";\"${CMAKE_CURRENT_SOURCE_DIR}/doc/pages\"") string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/libs\"")
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_INCLUDES}") string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_INCLUDES}")
string(REPLACE ";" " " DOXY_DEFINES "${DOXY_DEFINES}") string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS}")
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

@@ -33,10 +33,6 @@ You should add ${<out_var>} to your target.
## Documentation ## Documentation
[🇺🇸 Online documentation](https://shs.tools/pip/html/en/index.html) [Online documentation 🇺🇸](https://shs.tools/pip/html/en/index.html)
[🇺🇸 Qt-help](https://shs.tools/pip/pip_en.qch) [Онлайн документация 🇷🇺](https://shs.tools/pip/html/ru/index.html)
[🇷🇺 Онлайн документация](https://shs.tools/pip/html/ru/index.html)
[🇷🇺 Qt-help](https://shs.tools/pip/pip_ru.qch)

View File

@@ -617,7 +617,7 @@ HIDE_COMPOUND_REFERENCE= NO
# the files that are included by a file in the documentation of that file. # the files that are included by a file in the documentation of that file.
# The default value is: YES. # The default value is: YES.
SHOW_INCLUDE_FILES = YES SHOW_INCLUDE_FILES = NO
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader # grouped member an include statement to the documentation, telling the reader

View File

@@ -1,6 +1,25 @@
#include "pip.h" #include "pip.h"
//! [main] //! [main]
int main(int argc, char ** argv) {
PICLI cli(argc, argv);
cli.addArgument("console");
cli.addArgument("debug");
cli.addArgument("Value", "v", "value", true);
if (cli.hasArgument("console"))
piCout << "console active";
if (cli.hasArgument("debug"))
piCout << "debug active";
piCout << "Value =" << cli.argumentValue("Value");
return 0;
}
These executions are similar:
a.out -cd -v 10
a.out --value 10 -dc
a.out -c -v 10 -d
a.out --console -d -v 10
a.out --debug -c --value 10
//! [main] //! [main]
void _() { void _() {

View File

@@ -3,7 +3,7 @@ void _() {
//! [0] //! [0]
class SomeIO: public PIIODevice { class SomeIO: public PIIODevice {
PIIODEVICE(SomeIO, "myio") PIIODEVICE(SomeIO)
public: public:
SomeIO(): PIIODevice() {} SomeIO(): PIIODevice() {}
protected: protected:
@@ -19,8 +19,9 @@ 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 here // parse full_path and configure device there
} }
}; };
REGISTER_DEVICE(SomeIO) REGISTER_DEVICE(SomeIO)

View File

@@ -2,5 +2,8 @@
void _() { void _() {
//! [main] //! [main]
mutex.lock();
// ... your code here
mutex.unlock();
//! [main] //! [main]
} }

348
doc/examples/pistring.cpp Normal file
View File

@@ -0,0 +1,348 @@
#include "pip.h"
void _() {
//! [PIString(char * )]
PIString s("string");
//! [PIString(char * )]
//! [PIString(wchar_t * )]
PIString s(L"string");
//! [PIString(wchar_t * )]
//! [PIString(char * , int)]
PIString s("string", 3); // s = "str"
//! [PIString(char * , int)]
//! [PIString(int, char)]
PIString s(5, 'p'); // s = "ppppp"
//! [PIString(int, char)]
//! [PIString(int, PIChar)]
PIString s(5, ""); // s = "№№№№№"
//! [PIString(int, PIChar)]
//! [PIString::char*]
PIString s("pip");
cout << (char*)s << endl; // pip
//! [PIString::char*]
//! [PIString::<<(PIString)]
PIString s("this"), s1(" is"), s2(" string");
s << s1 << s2; // s = "this is string"
//! [PIString::<<(PIString)]
//! [PIString::<<(PIChar)]
PIString s("stri");
s << PIChar('n') << PIChar('g'); // s = "string"
//! [PIString::<<(PIChar)]
//! [PIString::<<(char * )]
PIString s("this");
s << " is" << " string"; // s = "this is string"
//! [PIString::<<(char * )]
//! [PIString::<<(wchar_t * )]
PIString s;
s << L"№ -" << " number"; // s = "№ - number"
//! [PIString::<<(wchar_t * )]
//! [PIString::<<(int)]
PIString s("ten - ");
s << 10; // s = "ten - 10"
//! [PIString::<<(int)]
//! [PIString::mid]
PIString s("0123456789");
piCout << s.mid(-2, -1); // s = "0123456789"
piCout << s.mid(-2, 4); // s = "01"
piCout << s.mid(3, -1); // s = "3456789"
piCout << s.mid(3, 4); // s = "3456"
//! [PIString::mid]
//! [PIString::left]
PIString s("0123456789");
piCout << s.left(-1); // s = ""
piCout << s.left(1); // s = "0"
piCout << s.left(5); // s = "01234"
piCout << s.left(15); // s = "0123456789"
//! [PIString::left]
//! [PIString::right]
PIString s("0123456789");
piCout << s.right(-1); // s = ""
piCout << s.right(1); // s = "9"
piCout << s.right(5); // s = "56789"
piCout << s.right(15); // s = "0123456789"
//! [PIString::right]
//! [PIString::cutMid]
PIString s("0123456789");
s.cutMid(1, 3);
piCout << s; // s = "0456789"
s.cutMid(-1, 3);
piCout << s; // s = "56789"
s.cutMid(3, -1);
piCout << s; // s = "567"
//! [PIString::cutMid]
//! [PIString::cutLeft]
PIString s("0123456789");
s.cutLeft(1);
piCout << s; // s = "123456789"
s.cutLeft(3);
piCout << s; // s = "456789"
s.cutLeft(30);
piCout << s; // s = ""
//! [PIString::cutLeft]
//! [PIString::cutRight]
PIString s("0123456789");
s.cutRight(1);
piCout << s; // s = "012345678"
s.cutRight(3);
piCout << s; // s = "012345"
s.cutRight(30);
piCout << s; // s = ""
//! [PIString::cutRight]
//! [PIString::trim]
PIString s(" string ");
s.trim();
piCout << s; // s = "string"
//! [PIString::trim]
//! [PIString::trimmed]
PIString s(" string ");
piCout << s.trimmed(); // s = "string"
piCout << s; // s = " string "
//! [PIString::trimmed]
//! [PIString::replace_0]
PIString s("0123456789");
s.replace(2, 3, "_cut_");
piCout << s; // s = "01_cut_56789"
s.replace(0, 1, "one_");
piCout << s; // s = "one_1_cut_56789"
//! [PIString::replace_0]
//! [PIString::replaced_0]
PIString s("0123456789");
piCout << s.replaced(2, 3, "_cut_"); // s = "01_cut_56789"
piCout << s.replaced(0, 1, "one_"); // s = "one_123456789"
//! [PIString::replaced_0]
//! [PIString::replace_1]
PIString s("pip string");
bool ok;
s.replace("string", "conf", &ok);
piCout << s << ok; // s = "pip conf", true
s.replace("PIP", "PlInPr", &ok);
piCout << s << ok; // s = "pip conf", false
//! [PIString::replace_1]
//! [PIString::replaced_1]
PIString s("pip string");
bool ok;
piCout << s.replace("string", "conf", &ok); // s = "pip conf", true
piCout << s.replace("PIP", "PlInPr", &ok); // s = "pip string", false
//! [PIString::replaced_1]
//! [PIString::replaceAll]
PIString s("substrings");
s.replaceAll("s", "_");
piCout << s; // s = "_ub_tring_"
//! [PIString::replaceAll]
//! [PIString::repeat]
PIString s(" :-) ");
s.repeat(3);
piCout << s; // :-) :-) :-)
//! [PIString::repeat]
//! [PIString::repeated]
PIString s(" :-) ");
piCout << s.repeated(3); // :-) :-) :-)
piCout << s; // :-)
//! [PIString::repeated]
//! [PIString::insert_0]
PIString s("pp");
s.insert(1, "i");
piCout << s; // s = "pip"
//! [PIString::insert_0]
//! [PIString::insert_1]
PIString s("pp");
s.insert(1, 'i');
piCout << s; // s = "pip"
//! [PIString::insert_1]
//! [PIString::insert_2]
PIString s("stg");
s.insert(2, "rin");
piCout << s; // s = "string"
//! [PIString::insert_2]
//! [PIString::expandRightTo]
PIString s("str");
s.expandRightTo(2, "_");
piCout << s; // s = "str"
s.expandRightTo(6, "_");
piCout << s; // s = "str___"
//! [PIString::expandRightTo]
//! [PIString::expandLeftTo]
PIString s("str");
s.expandLeftTo(2, "_");
piCout << s; // s = "str"
s.expandLeftTo(6, "_");
piCout << s; // s = "___str"
//! [PIString::expandLeftTo]
//! [PIString::reverse]
PIString s("0123456789");
s.reverse();
piCout << s; // s = "9876543210"
//! [PIString::reverse]
//! [PIString::reversed]
PIString s("0123456789");
piCout << s.reversed(); // s = "9876543210"
piCout << s; // s = "0123456789"
//! [PIString::reversed]
//! [PIString::elided]
piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideLeft); // ..ABCDEF
piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideCenter); // 123..DEF
piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideRight); // 123456..
piCout << PIString("123456789ABCDEF").elided(8, 0.25); // 12..CDEF
//! [PIString::elided]
//! [PIString::lengthAscii]
piCout << PIString("0123456789").lengthAscii(); // 10
piCout << PIString("№1").lengthAscii(); // 3
//! [PIString::lengthAscii]
//! [PIString::data]
piCout << PIString("0123456789").data(); // 0123456789
piCout << PIString("№1").data(); // №1
//! [PIString::data]
//! [PIString::split]
PIString s("1 2 3");
piCout << s.split(" "); // {"1", "2", "3"}
//! [PIString::split]
//! [PIString::find]
PIString s("012345012345");
piCout << s.find("-"); // -1
piCout << s.find("3"); // 3
piCout << s.find("3", 4); // 9
piCout << s.find("3", 10); // -1
//! [PIString::find]
//! [PIString::findLast]
PIString s("012345012345");
piCout << s.find("-"); // -1
piCout << s.find("3"); // 9
piCout << s.find("3", 4); // 9
piCout << s.find("3", 10); // -1
//! [PIString::findLast]
//! [PIString::findAny]
piCout << PIString("1.str").findAny(".,:"); // 1
piCout << PIString("1,str").findAny(".,:"); // 1
piCout << PIString("1:str").findAny(".,:"); // 1
//! [PIString::findAny]
//! [PIString::findAnyLast]
piCout << PIString("str.0").findAny(".,:"); // 3
piCout << PIString("str,0").findAny(".,:"); // 3
piCout << PIString("str:0").findAny(".,:"); // 3
//! [PIString::findAnyLast]
//! [PIString::findWord]
PIString s("this is <PIP>");
piCout << s.find("this"); // 0
piCout << s.find("is"); // 5
piCout << s.find("PIP", 4); // -1
piCout << s.find("<PIP>", 10); // 8
//! [PIString::findWord]
//! [PIString::findCWord]
PIString s("this::is <PIP>");
piCout << s.find("this"); // 0
piCout << s.find("is"); // 6
piCout << s.find("PIP", 4); // 10
piCout << s.find("<PIP>", 10); // 9
//! [PIString::findCWord]
//! [PIString::toNumber]
piCout << PIString("123").toInt(); // 123
piCout << PIString("123").toInt(16); // 291
piCout << PIString("0x123").toInt(); // 291
piCout << PIString("1001").toInt(2); // 9
//! [PIString::toNumber]
//! [PIString::toFloat]
piCout << PIString("123").toFloat(); // 123
piCout << PIString("1.2E+2").toFloat(); // 120
piCout << PIString("0.01").toFloat(); // 0.01
//! [PIString::toFloat]
//! [PIString::setNumber]
PIString s;
s.setNumber(123);
piCout << s; // 123
s.setNumber(123, 16);
piCout << s; // 7B
//! [PIString::setNumber]
//! [PIString::setFloat]
PIString s;
s.setNumber(12.3);
piCout << s; // 12.3
//! [PIString::setFloat]
//! [PIString::setReadableSize]
PIString s;
s.setReadableSize(512);
piCout << s; // 512 B
s.setReadableSize(5120);
piCout << s; // 5.0 kB
s.setReadableSize(512000);
piCout << s; // 500.0 kB
s.setReadableSize(5120000);
piCout << s; // 4.8 MB
s.setReadableSize(512000000);
piCout << s; // 488.2 MB
s.setReadableSize(51200000000);
piCout << s; // 47.6 GB
//! [PIString::setReadableSize]
//! [PIString::fromNumber]
piCout << PIString::fromNumber(123); // 123
piCout << PIString::fromNumber(123, 16); // 7B
//! [PIString::fromNumber]
//! [PIString::fromFloat]
piCout << PIString::fromNumber(12.3); // 12.3
//! [PIString::fromFloat]
//! [PIString::readableSize]
piCout << PIString::readableSize(512); // 512 B
piCout << PIString::readableSize(5120); // 5.0 kB
piCout << PIString::readableSize(512000); // 500.0 kB
piCout << PIString::readableSize(5120000); // 4.8 MB
piCout << PIString::readableSize(512000000); // 488.2 MB
piCout << PIString::readableSize(51200000000); // 47.6 GB
//! [PIString::readableSize]
//! [PIString::takeSymbol]
PIString s("\t ! word");
piCout << s.takeSymbol(); // "!"
piCout << s.takeSymbol(); // "w"
piCout << s.takeSymbol(); // "o"
piCout << s; // "rd"
//! [PIString::takeSymbol]
//! [PIString::takeWord]
PIString s("some words\nnew line ");
piCout << s.takeWord(); // "some"
piCout << s.takeWord(); // "words"
piCout << s.takeWord(); // "new"
piCout << s; // " line "
//! [PIString::takeWord]
//! [PIString::takeLine]
PIString s("some words\nnew line \n\nend");
piCout << s.takeLine(); // "some words"
piCout << s.takeLine(); // "new line "
piCout << s.takeLine(); // ""
piCout << s; // "end"
//! [PIString::takeLine]
//! [PIString::takeNumber]
PIString s(" 0xFF -99 1.2E+5f 1000L");
piCout << s.takeNumber(); // "0xFF"
piCout << s.takeNumber(); // "-99"
piCout << s.takeNumber(); // "1.2E+5f"
piCout << s.takeNumber(); // "1000L"
piCout << s; // ""
//! [PIString::takeNumber]
//! [PIString::takeRange]
PIString s(" {figures{inside}}");
piCout << s.takeRange('{', '}'); // "figures{inside}"
piCout << s; // ""
s = "\"text\\\"shielded\" next";
piCout << s.takeRange('"', '"'); // "text\"shielded"
piCout << s; // " next"
//! [PIString::takeRange]
//! [PIStringList::join]
PIStringList sl("1", "2");
sl << "3";
piCout << sl.join(" < "); // 1 < 2 < 3
//! [PIStringList::join]
//! [PIStringList::removeStrings]
PIStringList sl("1", "2");
sl << "1" << "2" << "3";
piCout << sl; // {"1", "2", "1", "2", "3"}
piCout << sl.removeStrings("1"); // {"2", "2", "3"}
//! [PIStringList::removeStrings]
//! [PIStringList::removeDuplicates]
PIStringList sl("1", "2");
sl << "1" << "2" << "3";
piCout << sl; // {"1", "2", "1", "2", "3"}
piCout << sl.removeDuplicates(); // {"1", "2", "3"}
//! [PIStringList::removeDuplicates]
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,44 +0,0 @@
\~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.

View File

@@ -1,104 +0,0 @@
\~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)

View File

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

View File

@@ -689,7 +689,13 @@ bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
case PIKbdListener::F12: case PIKbdListener::F12:
break; break;
default: default:
text.insert(cur, PIChar((ushort)key.key)); PIChar tc
#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,12 +812,11 @@ 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];
PIByteArray shell = PRIVATE->shell.toByteArray(); argv[0] = new char[PRIVATE->shell.lengthAscii() + 1];
argv[0] = new char[shell.size() + 1]; memcpy(argv[0], PRIVATE->shell.dataAscii(), PRIVATE->shell.lengthAscii());
memcpy(argv[0], shell.data(), shell.size()); argv[0][PRIVATE->shell.lengthAscii()] = 0;
argv[0][shell.size()] = 0;
argv[1] = 0; argv[1] = 0;
execvp(argv[0], argv); execvp(PRIVATE->shell.dataAscii(), argv);
delete[] argv[0]; delete[] argv[0];
delete[] argv; delete[] argv;
exit(0); exit(0);

View File

@@ -1,9 +1,6 @@
/*! \file picloudbase.h /*! \file picloudbase.h
* \ingroup Cloud * \brief PICloud Base - Base class for PICloudClient and PICloud Server
* \~\brief */
* \~english Base class for PICloudClient and PICloudServer
* \~russian Базовый класс для PICloudClient и PICloudServer
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Base - Base class for PICloudClient and PICloud Server PICloud Base - Base class for PICloudClient and PICloud Server

View File

@@ -1,9 +1,6 @@
/*! \file picloudclient.h /*! \file picloudclient.h
* \ingroup Cloud * \brief PICloud Client
* \~\brief */
* \~english PICloud Client
* \~russian Клиент PICloud
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Client PICloud Client
@@ -34,7 +31,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,37 +16,6 @@
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 Cloud
//! \~\brief
//! \~english Cloud transport over ethernet
//! \~russian Облачный транспорт через ethernet
//!
//! \~\details
//! \~english \section cmake_module_Cloud Building with CMake
//! \~russian \section cmake_module_Cloud Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Cloud)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! These files provides server-side and client-side of PICloud transport.
//!
//! \~russian
//! Эти файлы обеспечивают серверную и клиентскую сторону транспорта PICloud.
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PICLOUDMODULE_H #ifndef PICLOUDMODULE_H
#define PICLOUDMODULE_H #define PICLOUDMODULE_H

View File

@@ -1,9 +1,6 @@
/*! \file picloudserver.h /*! \file picloudserver.h
* \ingroup Cloud * \brief PICloud Server
* \~\brief */
* \~english PICloud Server
* \~russian Сервер PICloud
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Server PICloud Server
@@ -32,14 +29,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

@@ -1,9 +1,6 @@
/*! \file picloudtcp.h /*! \file picloudtcp.h
* \ingroup Cloud * \brief PICloud TCP transport
* \~\brief */
* \~english PICloud TCP transport
* \~russian TCP слой PICloud
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud TCP transport PICloud TCP transport

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.toString(); return e.name;
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.toString() == name_) if (e.name == 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.toString()); PIVariantTypes::Enum en(name);
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<PIConstChars, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo; PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
PIMap<PIConstChars, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo; PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions; PIMap<PIString, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions;
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * PICodeInfo::accessTypeFunctions; PIMap<PIString, 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(class_name, (AccessTypeFunction)0); AccessTypeFunction atf = accessTypeFunctions->value(PIStringAscii(class_name), (AccessTypeFunction)0);
AccessValueFunction avf = accessValueFunctions->value(class_name, (AccessValueFunction)0); AccessValueFunction avf = accessValueFunctions->value(PIStringAscii(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

@@ -1,9 +1,6 @@
/*! \file picodeinfo.h /*! \file picodeinfo.h
* \ingroup Code * \brief C++ code info structs
* \~\brief */
* \~english C++ code info structs
* \~russian Структуры для C++ кода
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
C++ code info structs C++ code info structs
@@ -27,7 +24,6 @@
#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"
@@ -53,18 +49,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 PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {name = n; type = t; flags = f; bits = b;} TypeInfo(const PIString & n = PIString(), const PIString & t = PIString(), 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;
PIConstChars name; PIString name;
PIConstChars type; PIString type;
PICodeInfo::TypeFlags flags; PICodeInfo::TypeFlags flags;
int bits; int bits;
}; };
struct PIP_EXPORT FunctionInfo { struct PIP_EXPORT FunctionInfo {
MetaMap meta; MetaMap meta;
PIConstChars name; PIString name;
TypeInfo return_type; TypeInfo return_type;
PIVector<PICodeInfo::TypeInfo> arguments; PIVector<PICodeInfo::TypeInfo> arguments;
}; };
@@ -73,19 +69,19 @@ struct PIP_EXPORT ClassInfo {
ClassInfo() {has_name = true;} ClassInfo() {has_name = true;}
MetaMap meta; MetaMap meta;
bool has_name; bool has_name;
PIConstChars type; PIString type;
PIConstChars name; PIString name;
PIVector<PIConstChars> parents; PIStringList 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 PIConstChars & n = PIConstChars(), int v = 0) {name = n; value = v;} EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;}
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name.toString());} PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name);}
MetaMap meta; MetaMap meta;
PIConstChars name; PIString name;
int value; int value;
}; };
@@ -94,7 +90,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;
PIConstChars name; PIString name;
PIVector<PICodeInfo::EnumeratorInfo> members; PIVector<PICodeInfo::EnumeratorInfo> members;
}; };
@@ -120,17 +116,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;
for (const auto & i: v.parents) { piForeachC (PIString & 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";
for (const auto & i: v.functions) { piForeachC (FunctionInfo & 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;
for (const auto & a: i.arguments) { piForeachC (TypeInfo & a, i.arguments) {
if (fa) fa = false; if (fa) fa = false;
else s << ", "; else s << ", ";
s << a; s << a;
@@ -139,7 +135,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";
for (const auto & i: v.variables) { piForeachC (TypeInfo & i, v.variables) {
s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n"; s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n";
} }
s << "}\n"; s << "}\n";
@@ -150,7 +146,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";
for (const auto & i: v.members) { piForeachC (EnumeratorInfo & i, v.members) {
bool f = true; bool f = true;
if (f) f = false; if (f) f = false;
else s << ", "; else s << ", ";
@@ -161,21 +157,21 @@ inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
return s; return s;
} }
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::ClassInfo * > * classesInfo; extern PIP_EXPORT PIMap<PIString, PICodeInfo::ClassInfo * > * classesInfo;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::EnumInfo * > * enumsInfo; extern PIP_EXPORT PIMap<PIString, PICodeInfo::EnumInfo * > * enumsInfo;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions; extern PIP_EXPORT PIMap<PIString, PICodeInfo::AccessValueFunction> * accessValueFunctions;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions; extern PIP_EXPORT PIMap<PIString, 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(class_name, (AccessValueFunction)0); AccessValueFunction af = accessValueFunctions->value(PIStringAscii(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(class_name, (AccessTypeFunction)0); AccessTypeFunction af = accessTypeFunctions->value(PIStringAscii(class_name), (AccessTypeFunction)0);
if (!af) return ""; if (!af) return "";
return af(member_name); return af(member_name);
} }
@@ -196,10 +192,10 @@ public:
__PICodeInfoInitializer__() { __PICodeInfoInitializer__() {
if (_inited_) return; if (_inited_) return;
_inited_ = true; _inited_ = true;
PICodeInfo::classesInfo = new PIMap<PIConstChars, PICodeInfo::ClassInfo * >; PICodeInfo::classesInfo = new PIMap<PIString, PICodeInfo::ClassInfo * >;
PICodeInfo::enumsInfo = new PIMap<PIConstChars, PICodeInfo::EnumInfo * >; PICodeInfo::enumsInfo = new PIMap<PIString, PICodeInfo::EnumInfo * >;
PICodeInfo::accessValueFunctions = new PIMap<PIConstChars, PICodeInfo::AccessValueFunction>; PICodeInfo::accessValueFunctions = new PIMap<PIString, PICodeInfo::AccessValueFunction>;
PICodeInfo::accessTypeFunctions = new PIMap<PIConstChars, PICodeInfo::AccessTypeFunction>; PICodeInfo::accessTypeFunctions = new PIMap<PIString, PICodeInfo::AccessTypeFunction>;
} }
static bool _inited_; static bool _inited_;
}; };

View File

@@ -16,37 +16,6 @@
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 Code
//! \~\brief
//! \~english C++ code parsing
//! \~russian Разбор C++ кода
//!
//! \~\details
//! \~english \section cmake_module_Code Building with CMake
//! \~russian \section cmake_module_Code Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! These files provides parsing C++ code and storage to use results of \a pip_cmg utility.
//!
//! \~russian
//! Эти файлы обеспечивают разбор C++ кода и хранение результатов работы утилиты \a pip_cmg.
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PICODEMODULE_H #ifndef PICODEMODULE_H
#define PICODEMODULE_H #define PICODEMODULE_H

View File

@@ -1,10 +1,6 @@
/*! \file picompress.h /*! \file picompress.h
* \brief * \brief Compress class using zlib
* \ingroup Compress */
* \~\brief
* \~english Compress class zlib
* \~russian Сжатие с помощью zlib
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Compress class using zlib Compress class using zlib
@@ -23,37 +19,6 @@
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 Compress
//! \~\brief
//! \~english Compression support
//! \~russian Поддержка сжатия
//!
//! \~\details
//! \~english \section cmake_module_Compress Building with CMake
//! \~russian \section cmake_module_Compress Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Compress)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! These files provides simple compression and decompression support.
//!
//! \~russian
//! Эти файлы обеспечивают простое сжатие и распакову.
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PICOMPRESS_H #ifndef PICOMPRESS_H
#define PICOMPRESS_H #define PICOMPRESS_H
@@ -61,16 +26,8 @@
#include "pip_compress_export.h" #include "pip_compress_export.h"
#include "pibytearray.h" #include "pibytearray.h"
//! \~english Compress "ba" with compression level "level", return empty %PIByteArray if no compression supports
//! \~russian Сжимает "ba" с уровнем сжатия "level", возвращает пустой %PIByteArray если нет поддержки
//! \~\ingroup Compress
//! \~\details
PIP_COMPRESS_EXPORT PIByteArray piCompress(const PIByteArray & ba, int level = 6); PIP_COMPRESS_EXPORT PIByteArray piCompress(const PIByteArray & ba, int level = 6);
//! \~english Decompress "zba", return empty %PIByteArray if no compression supports
//! \~russian Распаковывает "zba", возвращает пустой %PIByteArray если нет поддержки
//! \~\ingroup Compress
//! \~\details
PIP_COMPRESS_EXPORT PIByteArray piDecompress(const PIByteArray & zba); PIP_COMPRESS_EXPORT PIByteArray piDecompress(const PIByteArray & zba);
#endif // PICOMPRESS_H #endif // PICOMPRESS_H

View File

@@ -16,37 +16,6 @@
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 Console
//! \~\brief
//! \~english Console graphic
//! \~russian Графика в консоли
//!
//! \~\details
//! \~english \section cmake_module_Console Building with CMake
//! \~russian \section cmake_module_Console Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Console)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! These files provides grab keyboard from console, simple tiling manager and virtual terminal.
//!
//! \~russian
//! Эти файлы обеспечивают захват клавиатуры в консоли, простой тайловый менеджер и виртуальный терминал.
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PICONSOLEMODULE_H #ifndef PICONSOLEMODULE_H
#define PICONSOLEMODULE_H #define PICONSOLEMODULE_H

View File

@@ -323,18 +323,12 @@ 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)
std::cout << "'" << (char)(rc[i]) << "' " << (int)(uchar)(rc[i]); cout << "'" << (char)(rc[i]) << "' ";
std::cout << std::endl;*/ cout << 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) { if (PRIVATE->ret == 1) ke.key = PIChar::fromConsole(rc[0]).unicode16Code();
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

@@ -1,9 +1,6 @@
/*! \file pikbdlistener.h /*! \file pikbdlistener.h
* \ingroup Console * \brief Keyboard console input listener
* \~\brief */
* \~english Keyboard console input listener
* \~russian Консольный захват клавиатуры
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Keyboard grabber for console Keyboard grabber for console

View File

@@ -1,9 +1,6 @@
/*! \file piscreen.h /*! \file piscreen.h
* \ingroup Console * \brief Console GUI class
* \~\brief */
* \~english Console tiling manager
* \~russian Консольный тайловый менеджер
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console GUI Console GUI

View File

@@ -1,9 +1,8 @@
/*! \file piscreenconsole.h /*! \file piscreenconsole.h
* \ingroup Console * \brief Tile for PIScreen with PIConsole API
* \~\brief *
* \~english Tile for PIScreen with PIConsole API * This file declares TileVars
* \~russian Тайл для PIScreen с API PIConsole */
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API Tile for PIScreen with PIConsole API

View File

@@ -1,9 +1,6 @@
/*! \file piscreendrawer.h /*! \file piscreendrawer.h
* \ingroup Console * \brief Drawer for PIScreen
* \~\brief */
* \~english Drawer for PIScreen
* \~russian Отрисовщик для PIScreen
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Drawer for PIScreen Drawer for PIScreen

View File

@@ -1,9 +1,6 @@
/*! \file piscreentile.h /*! \file piscreentile.h
* \ingroup Console * \brief Basic PIScreen tile
* \~\brief */
* \~english Basic PIScreen tile
* \~russian Базовый тайл для PIScreen
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile

View File

@@ -1,9 +1,6 @@
/*! \file piscreentiles.h /*! \file piscreentiles.h
* \ingroup Console * \brief Various tiles for PIScreen
* \~\brief */
* \~english Various tiles for PIScreen
* \~russian Различные тайлы для PIScreen
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Various tiles for PIScreen Various tiles for PIScreen

View File

@@ -1,9 +1,6 @@
/*! \file piscreentypes.h /*! \file piscreentypes.h
* \ingroup Console * \brief Types for PIScreen
* \~\brief */
* \~english Types for PIScreen
* \~russian Типы для PIScreen
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Types for PIScreen Types for PIScreen

View File

@@ -1,9 +1,6 @@
/*! \file piterminal.h /*! \file piterminal.h
* \ingroup Console * \brief Virtual terminal
* \~\brief */
* \~english Virtual terminal
* \~russian Виртуальный терминал
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal

View File

@@ -1,34 +0,0 @@
/*
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

@@ -1,17 +1,17 @@
//! \addtogroup Containers /*! \addtogroup Containers
//! \{ * \{
//! \file picontainers.h * \file picontainers.h
//! \brief * \brief
//! \~english Base macros for generic containers * \~english Base macros for generic containers
//! \~russian Базовые макросы для контейнеров * \~russian Базовые макросы для контейнеров
//! \~\authors * \~\authors
//! \~english * \~english
//! Ivan Pelipenko peri4ko@yandex.ru; * Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru; * Andrey Bychkov work.a.b@yandex.ru;
//! \~russian * \~russian
//! Иван Пелипенко peri4ko@yandex.ru; * Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru; * Андрей Бычков work.a.b@yandex.ru;
//! \~\} * \~\} */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Base macros for generic containers Base macros for generic containers
@@ -45,8 +45,6 @@
#include <type_traits> #include <type_traits>
#include <string.h> #include <string.h>
#include <new> #include <new>
#include <algorithm>
#include <functional>
template <typename C> template <typename C>
@@ -63,122 +61,106 @@ private:
}; };
class PIP_EXPORT _PIContainerConstantsBase { /*! \brief
public: * \~english Template reverse wrapper over any container
static ssize_t calcMinCountPoT(ssize_t szof); * \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
}; */
template<typename T>
class _PIContainerConstants {
public:
static ssize_t minCountPoT() {static ssize_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
};
//! \brief
//! \~english Template reverse wrapper over any container
//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
template <typename C> _PIReverseWrapper<C> PIReverseWrap(C & c) {return _PIReverseWrapper<C>(c);} template <typename C> _PIReverseWrapper<C> PIReverseWrap(C & c) {return _PIReverseWrapper<C>(c);}
template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _PIReverseWrapper<C>(c);} template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _PIReverseWrapper<C>(c);}
//! \brief /*! \brief
//! \~english Macro for short replacement of standart "for" * \~english Macro for short replacement of standart "for"
//! \~russian Макрос для короткой записи стандартного цикла "for" * \~russian Макрос для короткой записи стандартного цикла "for"
//! \~\param c * \~\param c
//! \~english Iteration times in loop * \~english Iteration times in loop
//! \~russian Количество итераций цикла * \~russian Количество итераций цикла
*/
#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c) #define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
//! \brief /*! \brief
//! \~english Macro for iterate any container * \~english Macro for iterate any container
//! \~russian Макрос для перебора любых контейнеров * \~russian Макрос для перебора любых контейнеров
//! \~\deprecated * \~\deprecated
//! \~english Deprecated, using only for backward compatibility. Use * \~english Deprecated, using only for backward compatibility. Use
//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
//! \~russian Устарело, используется только для обратной совместимости. Используйте * \~russian Устарело, используется только для обратной совместимости. Используйте
//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
//! \~\details * \~\details
//! \~english Get read/write access to each element of container. * \~english Get read/write access to each element of container.
//! Iterating in forward direction. * Iterating in forward direction.
//! Example of using: * Example of using:
//! \~russian Перебор всех элементов контейнера с доступом на чтение и запись. * \~russian Перебор всех элементов контейнера с доступом на чтение и запись.
//! Перебор осуществляется в прямом порядке. * Перебор осуществляется в прямом порядке.
//! Пример использования: * Пример использования:
//! \~\code * \~\code
//! PIVector<int> vec; * PIVector<int> vec;
//! vec << 1 << 2 << 3; * vec << 1 << 2 << 3;
//! piForeach(int & i, vec) piCout << i; * piForeach(int & i, vec) piCout << i;
//! // 1 * // 1
//! // 2 * // 2
//! // 3 * // 3
//! piForeach(int & i, vec) i++; * piForeach(int & i, vec) i++;
//! piForeach(int & i, vec) piCout << i; * piForeach(int & i, vec) piCout << i;
//! // 2 * // 2
//! // 3 * // 3
//! // 4 * // 4
//! \endcode * \endcode
//! \sa \a piForeachC, \a piForeachR, \a piForeachRC * \sa \a piForeachC, \a piForeachR, \a piForeachRC
*/
#define piForeach(i, c) for(i : c) #define piForeach(i, c) for(i : c)
//! \brief /*! \brief
//! \~english Macro for iterate any container * \~english Macro for iterate any container
//! \~russian Макрос для перебора любых контейнеров * \~russian Макрос для перебора любых контейнеров
//! \~\deprecated * \~\deprecated
//! \~english Deprecated, using only for backward compatibility. Use * \~english Deprecated, using only for backward compatibility. Use
//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
//! \~russian Устарело, используется только для обратной совместимости. Используйте * \~russian Устарело, используется только для обратной совместимости. Используйте
//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
//! \~\details * \~\details
//! \~english Get read only access to each element of container. * \~english Get read only access to each element of container.
//! Iterating in forward direction. * Iterating in forward direction.
//! \~russian Перебор всех элементов контейнера с доступом только на чтение. * \~russian Перебор всех элементов контейнера с доступом только на чтение.
//! Перебор осуществляется в прямом порядке. * Перебор осуществляется в прямом порядке.
//! \~ \sa \a piForeach, \a piForeachR, \a piForeachRC * \~ \sa \a piForeach, \a piForeachR, \a piForeachRC
*/
#define piForeachC(i, c) for(const i : c) #define piForeachC(i, c) for(const i : c)
//! \brief /*! \brief
//! \~english Macro for iterate any container * \~english Macro for iterate any container
//! \~russian Макрос для перебора любых контейнеров * \~russian Макрос для перебора любых контейнеров
//! \~\deprecated * \~\deprecated
//! \~english Deprecated, using only for backward compatibility. Use * \~english Deprecated, using only for backward compatibility. Use
//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
//! \~russian Устарело, используется только для обратной совместимости. Используйте * \~russian Устарело, используется только для обратной совместимости. Используйте
//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
//! \~\details * \~\details
//! \~english Get read/write access to each element of container. * \~english Get read/write access to each element of container.
//! Iterating in backward direction. * Iterating in backward direction.
//! \~russian Перебор всех элементов контейнера с доступом на чтение и запись. * \~russian Перебор всех элементов контейнера с доступом на чтение и запись.
//! Перебор осуществляется в обратном порядке. * Перебор осуществляется в обратном порядке.
//! \~ \sa \a piForeach, \a piForeachC, \a piForeachRC * \~ \sa \a piForeach, \a piForeachC, \a piForeachRC
*/
#define piForeachR(i, c) for(i : PIReverseWrap(c)) #define piForeachR(i, c) for(i : PIReverseWrap(c))
//! \brief /*! \brief
//! \~english Macro for iterate any container * \~english Macro for iterate any container
//! \~russian Макрос для перебора любых контейнеров * \~russian Макрос для перебора любых контейнеров
//! \~\deprecated * \~\deprecated
//! \~english Deprecated, using only for backward compatibility. Use * \~english Deprecated, using only for backward compatibility. Use
//! [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
//! \~russian Устарело, используется только для обратной совместимости. Используйте * \~russian Устарело, используется только для обратной совместимости. Используйте
//! [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for). * [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
//! \~\details * \~\details
//! \~english Get read only access to each element of container. * \~english Get read only access to each element of container.
//! Iterating in backward direction. Also has alias **piForeachCR** * Iterating in backward direction. Also has alias **piForeachCR**
//! \~russian Перебор всех элементов контейнера с доступом только на чтение. * \~russian Перебор всех элементов контейнера с доступом только на чтение.
//! Перебор осуществляется в обратном порядке. Также можно писать **piForeachCR** * Перебор осуществляется в обратном порядке. Также можно писать **piForeachCR**
//! \~ \sa \a piForeach, \a piForeachC, \a piForeachR * \~ \sa \a piForeach, \a piForeachC, \a piForeachR
*/
#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,166 +16,30 @@
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 Containers /** \defgroup Containers
//! \~\brief * \~\brief
//! \~english Various standart containers realization * \~english This module contains various standart containers realization.
//! \~russian Различные классы контейнеров * \~russian Модуль содержит основные классы контейнеров.
//! *
//! \~\details * \~\details
//! \~english \section cmake_module_Containers Building with CMake * Scope | Use
//! \~russian \section cmake_module_Containers Сборка с использованием CMake * ----- | -------
//! * C++ | #include <picontainersmodule.h>
//! \~\code * CMake | PIP
//! find_package(PIP REQUIRED) *
//! target_link_libraries([target] PIP) * \~english This includes
//! \endcode * \~russian В него входят
//! * \~ \a PIVector, \a PIDeque, \a PIMap, \a PISet,
//! \~english \section containers_module_list Content * \a PIStack, \a PIQueue, \a PIPair, \a PIVector2D.
//! \~russian \section containers_module_list Состав *
//! * \authors
//! \~english * \~english
//! Class | Description * Ivan Pelipenko peri4ko@yandex.ru;
//! ------------- | ----------- * Andrey Bychkov work.a.b@yandex.ru;
//! \a PIVector | Linear array, fast back insert * \~russian
//! \a PIDeque | Linear array, fast back and front insert * Иван Пелипенко peri4ko@yandex.ru;
//! \a PIMap | Dictionary container, key/value array * Андрей Бычков work.a.b@yandex.ru;
//! \a PISet | Set container */
//! \a PIStack | Stack
//! \a PIQueue | Queue
//! \a PIPair | Pair
//! \a PIVector2D | Linear 2D rectangle array
//!
//! \~russian
//! Класс | Описание
//! ------------- | -----------
//! \a PIVector | Линейный массив, быстрое добавление в конец
//! \a PIDeque | Линейный массив, быстрое добавление вначало и конец
//! \a PIMap | Массив ключ/значение, словарь
//! \a PISet | Множество
//! \a PIStack | Стек
//! \a PIQueue | Очередь
//! \a PIPair | Пара
//! \a PIVector2D | Линейный двумерный прямоугольный массив
//!
//!
//! \~english \section stl_iterators STL-Style Iterators
//! \~russian \section stl_iterators Итераторы в стиле STL
//! \~english
//! \brief They are compatible with Qt's and STL's generic algorithms and are optimized for speed.
//! \details
//! For each container class, there are two STL-style iterator types:
//! one that provides read-only access and one that provides read-write access.
//! Read-only iterators should be used wherever possible
//! because they are faster than read-write iterators.
//! Read-only iterator - `const_iterator.`
//! Read-write iterator - `iterator.`
//!
//! The API of the STL iterators is modelled on pointers in an array.
//! For example, the `++` operator advances the iterator to the next item,
//! and the `*` operator returns the item that the iterator points to.
//! The `iterator` type is just a `typedef` for `T *`,
//! and the `const_iterator` type is just a `typedef` for `const T *`.
//! STL-style iterators point directly at items.
//! The `begin()` function of a container
//! returns an iterator that points to the first item in the container.
//! The `end()` function of a container returns an iterator to the imaginary item
//! one position past the last item in the container.
//! `end()` marks an invalid position; it must never be dereferenced.
//! It is typically used in a loop's break condition.
//!
//! Example:
//! \code
//! for (PIVector<int>::const_iterator i = v.begin(); i != v.end(); ++i) piCout << *i;
//! std::for_each(v.begin(), v.end(), [](int n){std::cout << n << ' ';});
//! \endcode
//!
//! If the list is empty, `begin()` equals `end()`, so we never execute the loop.
//!
//! ![iterators](doc/images/pivector_rbegin.png)
//!
//! The following table summarizes the STL-style iterators' API:
//! Expression | Behavior
//! ---------- | --------------------
//! `*i` | Returns the current item
//! `++i` | Advances the iterator to the next item
//! `i += n` | Advances the iterator by `n` items
//! `--i` | Moves the iterator back by one item
//! `i -= n` | Moves the iterator back by `n` items
//! `i - j` | Returns the number of items between iterators `i` and `j`
//!
//! The `++` and `--` operators are available both as prefix `(++i, --i)`
//! and postfix `(i++, i--)` operators.
//! The prefix versions modify the iterators
//! and return a reference to the modified iterator;
//! the postfix versions take a copy of the iterator before they modify it, and return that copy.
//! In expressions where the return value is ignored,
//! we recommend that you use the prefix operators `(++i, --i)`, as these are slightly faster.
//! For non-const iterator types, the return value of the unary `*` operator
//! can be used on the left side of the assignment operator.
//!
//! \~russian
//! \brief Они совместимы с базовыми алгоритмами Qt и STL и оптимизированы по скорости.
//! \details
//! Для каждого контейнерного класса есть два типа итераторов в стиле STL:
//! один из них предоставляет доступ только для чтения, а другой - доступ для чтения-записи.
//! Итераторы только для чтения должны использоваться везде, где это только возможно,
//! так как они быстрее, чем итераторы для чтения-записи.
//! Итератор только для чтения - `const_iterator.`
//! Итератор для чтения-записи - `iterator.`
//!
//! API итераторов в стиле STL сделан по образцу указателей в массиве.
//! Например, оператор `++` перемещает итератор к следующему элементу,
//! а оператор `*` возвращает элемент, на который позиционирован итератор.
//! Тип `iterator` - это как `typedef` для `T *`,
//! а тип `const_iterator` - как `typedef` для `const T *`.
//! Итераторы в стиле STL указывают непосредственно на элемент.
//! Функция контейнера `begin()` возвращает итератор, указывающий на первый элемент контейнера.
//! Функция контейнера `end()` возвращает итератор, указывающий на воображаемый элемент,
//! находящийся в позиции, следующей за последним элементом контейнера.
//! `end()` обозначает несуществующую позицию;
//! он никогда не должен разыменовываться.
//! Обычно, он используется, как условие выхода из цикла.
//!
//! Например:
//! \code
//! for (PIVector<int>::const_iterator i = v.begin(); i != v.end(); ++i) piCout << *i;
//! std::for_each(v.begin(), v.end(), [](int n){std::cout << n << ' ';});
//! \endcode
//!
//! Если список пуст, то begin() равен end(), поэтому цикл никогда не выполнится.
//!
//! ![итераторы](doc/images/pivector_rbegin.png)
//!
//! В следующей таблице подводится итог API итераторов в стиле STL:
//! Выражение | Поведение
//! --------- | --------------------
//! `*i` | Возвращает текущий элемент
//! `++i` | Перемещает итератор к следующему элементу
//! `i += n` | Перемещает итератор вперед на `n` элементов
//! `--i` | Перемещает итератор на один элемент назад
//! `i -= n` | Перемещает итератор назад на `n` элементов
//! `i - j` | Возвращает количество элементов, находящихся между итераторами `i` и `j`
//!
//! Оба оператора `++` и `--` могут использоваться и как префиксные `(++i, --i)`
//! и как постфиксные `(i++, i--)` операторы.
//! Префиксная версия изменяет итератор, и возвращает ссылку на измененный итератор;
//! постфиксная версия, берет копию итератора перед его изменением, и возвращает эту копию.
//! В выражениях, в которых возвращаемое значение игнорируется,
//! мы рекомендуем использовать префиксную версию `(++i, --i)`,
//! так как она несколько быстрее.
//!
//! Для неконстантных итераторов, возвращаемое значение унарного оператора `*`
//! может быть использовано с левой стороны от оператора присваивания.
//!
//!
//! \authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
#ifndef PICONTAINERSMODULE_H #ifndef PICONTAINERSMODULE_H
#define PICONTAINERSMODULE_H #define PICONTAINERSMODULE_H
@@ -188,5 +52,4 @@
#include "pistack.h" #include "pistack.h"
#include "pivector2d.h" #include "pivector2d.h"
#endif // PICONTAINERSMODULE_H #endif // PICONTAINERSMODULE_H

View File

@@ -1,17 +1,8 @@
//! \addtogroup Containers /*! \file pideque.h
//! \{ * \brief Dynamic array of any type
//! \file pideque.h *
//! \brief * This file declares PIDeque
//! \~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
@@ -37,165 +28,39 @@
#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 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_forward(other.pid_size); alloc(other.pid_size, true);
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_forward(init_list.size()); alloc(init_list.size(), true);
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_forward(size); alloc(size, true);
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, e); resize(pid_size, f);
} }
//! \~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))
@@ -204,515 +69,118 @@ 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_forward(other.pid_size); alloc(other.pid_size, true);
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:
inline iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {} inline iterator(PIDeque<T> * v, size_t p): parent(v), pos(p) {}
PIDeque<T> * parent; PIDeque<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline iterator(): parent(0), pos(0) {} inline iterator(): parent(0), pos(0) {}
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 T & operator ->() {return (*parent)[pos];} inline void operator ++() {++pos;}
inline const T & operator ->() const {return (*parent)[pos];} inline void operator ++(int) {++pos;}
inline void operator --() {--pos;}
inline iterator & operator ++() { inline void operator --(int) {--pos;}
++pos;
return *this;
}
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 +=(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 -(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;
}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
return it1.pos - it2.pos;
}
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) {
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 {
friend class PIDeque<T>; friend class PIDeque<T>;
private: private:
inline const_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {} inline const_iterator(const PIDeque<T> * v, size_t p): parent(v), pos(p) {}
const PIDeque<T> * parent; const PIDeque<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_iterator(): parent(0), pos(0) {} inline const_iterator(): parent(0), pos(0) {}
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 void operator ++() {++pos;}
inline void operator ++(int) {++pos;}
inline const_iterator & operator ++() { inline void operator --() {--pos;}
++pos; inline void operator --(int) {--pos;}
return *this;
}
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 +=(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 -(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;
}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
return it1.pos - it2.pos;
}
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) {
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 {
friend class PIDeque<T>; friend class PIDeque<T>;
private: private:
inline reverse_iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {} inline reverse_iterator(PIDeque<T> * v, size_t p): parent(v), pos(p) {}
PIDeque<T> * parent; PIDeque<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline reverse_iterator(): parent(0), pos(0) {} inline reverse_iterator(): parent(0), pos(0) {}
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 T & operator ->() {return (*parent)[pos];} inline void operator ++() {--pos;}
inline const T & operator ->() const {return (*parent)[pos];} inline void operator ++(int) {--pos;}
inline void operator --() {++pos;}
inline reverse_iterator & operator ++() { inline void operator --(int) {++pos;}
--pos;
return *this;
}
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 +=(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 -(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;
}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
return it2.pos - it1.pos;
}
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) {
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 {
friend class PIDeque<T>; friend class PIDeque<T>;
private: private:
inline const_reverse_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {} inline const_reverse_iterator(const PIDeque<T> * v, size_t p): parent(v), pos(p) {}
const PIDeque<T> * parent; const PIDeque<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_reverse_iterator(): parent(0), pos(0) {} inline const_reverse_iterator(): parent(0), pos(0) {}
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 void operator ++() {--pos;}
inline void operator ++(int) {--pos;}
inline const_reverse_iterator & operator ++() { inline void operator --() {++pos;}
--pos; inline void operator --(int) {++pos;}
return *this;
}
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 +=(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 -(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;
}
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 +(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) {
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;
@@ -720,222 +188,64 @@ 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]) return false; if (v[i] != (*this)[i]) {
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 {
//! \~english Tests if element `e` exists in the array. if (pid_size != v.pid_size) return pid_size < v.pid_size;
//! \~russian Проверяет наличие элемента `e` в массиве. for (size_t i = 0; i < pid_size; ++i) {
//! \~\details if ((*this)[i] != v[i]) return (*this)[i] < v[i];
//! \~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 {
//! \~english Count elements equal `e` in the array. if (pid_size != v.pid_size) return pid_size > v.pid_size;
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. for (size_t i = 0; i < pid_size; ++i) {
//! \~\details if ((*this)[i] != v[i]) return (*this)[i] > v[i];
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! 0 is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается 0, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\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;
if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
} }
return false;
}
inline bool contains(const T & e) const {
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
if (e == pid_data[i]) {
return true;
}
}
return false;
}
inline int etries(const T & e, size_t start = 0) const {
int ec = 0;
if (start >= pid_size) return ec;
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 < 0) { if (start >= pid_size) return ec;
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 < 0) { if (start >= pid_size) return -1;
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;
@@ -943,40 +253,8 @@ 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 < 0) { if (start >= pid_size) return -1;
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;
@@ -984,44 +262,9 @@ 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 >= size_s()) start = pid_size - 1; if (start < 0) start = pid_size - 1;
if (start < 0) start = pid_size + start; else start = piMin<ssize_t>(pid_size - 1, 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;
@@ -1029,35 +272,9 @@ 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 >= size_s()) start = pid_size - 1; if (start < 0) start = pid_size - 1;
if (start < 0) start = pid_size + start; else start = piMin<ssize_t>(pid_size - 1, 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;
@@ -1066,69 +283,15 @@ 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>
@@ -1146,33 +309,14 @@ public:
return *this; return *this;
} }
//! \~english Assigns element 'e' to all items in the array. inline PIDeque<T> & fill(const T & f = T()) {
//! \~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, e); elementNew(pid_data + i, f);
} }
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)
@@ -1181,42 +325,23 @@ 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 & e) { inline PIDeque<T> & assign(size_t new_size, const T & f) {
resize(new_size); resize(new_size);
return fill(e); return fill(f);
} }
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 & e) { inline PIDeque<T> & assign(size_t new_size, const T & f) {
_resizeRaw(new_size); _resizeRaw(new_size);
return fill(e); return fill(f);
} }
//! \~english Sets size of the array, new elements are copied from `e`. inline PIDeque<T> & resize(size_t new_size, const T & f = T()) {
//! \~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;
@@ -1226,26 +351,14 @@ public:
} }
if (new_size > pid_size) { if (new_size > pid_size) {
size_t os = pid_size; size_t os = pid_size;
alloc_forward(new_size); alloc(new_size, true);
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, e); elementNew(pid_data + i, f);
} }
} }
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);
@@ -1256,7 +369,7 @@ public:
} }
if (new_size > pid_size) { if (new_size > pid_size) {
size_t os = pid_size; size_t os = pid_size;
alloc_forward(new_size); alloc(new_size, true);
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));
@@ -1275,59 +388,30 @@ 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_forward(new_size); alloc(new_size, true);
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_forward(new_size); alloc(new_size, true);
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_forward(pid_size + 1); alloc(pid_size + 1, true);
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_backward(pid_size + 1, -1); alloc(pid_size + 1, false, -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));
} }
@@ -1335,25 +419,18 @@ 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_forward(pid_size + 1); alloc(pid_size + 1, true);
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_backward(pid_size + 1, -1); alloc(pid_size + 1, false, -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));
} }
@@ -1361,75 +438,26 @@ 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) {
//! \~english Inserts array `v` at `index` position in the array. if (other.isEmpty()) return *this;
//! \~russian Вставляет массив `v` в позицию `index` в массиве. assert(&other != this);
//! \~\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
if (&v == this) {
printf("error with PIDeque<%s>::insert\n", __PIP_TYPENAME__(T));
}
#endif
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_forward(pid_size + v.pid_size); alloc(pid_size + other.pid_size, true);
if (os > 0) { if (os > 0) {
memmove((void*)(&(pid_data[index + pid_start + v.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T)); memmove((void*)(&(pid_data[index + pid_start + other.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
} }
} else { } else {
alloc_backward(pid_size + v.pid_size, -v.pid_size); alloc(pid_size + other.pid_size, false, -other.pid_size);
if (index > 0) { if (index > 0) {
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + v.pid_size])), index * sizeof(T)); memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + other.pid_size])), index * sizeof(T));
} }
} }
newT(pid_data + pid_start + index, v.pid_data + v.pid_start, v.pid_size); newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.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) {
@@ -1452,11 +480,6 @@ 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);
@@ -1464,114 +487,13 @@ public:
piSwap<ssize_t>(pid_start, other.pid_start); piSwap<ssize_t>(pid_start, other.pid_start);
} }
//! \~english Sorts the elements in non-descending order. typedef int (*CompareFunc)(const T * , const T * );
//! \~russian Сортировка элементов в порядке возрастания. static int compare_func(const T * t0, const T * t1) {return (*t0) < (*t1) ? -1 : ((*t0) == (*t1) ? 0 : 1);}
//! \~\details inline PIDeque<T> & sort(CompareFunc compare = compare_func) {
//! \~english The order of equal elements is not guaranteed to be preserved. piqsort(pid_data + pid_start, pid_size, sizeof(T), (int(*)(const void * , const void * ))compare);
//! Elements are compared using operator<.
//! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort).
//! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
//! Для сравнения элементов используется оператор `operator<`.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`.
//! \~\code
//! PIDeque<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
//! v.sort();
//! piCout << v; // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
//! \endcode
//! \~\sa \a sort(std::function<bool(const T &a, const T &b)> comp)
inline PIDeque<T> & sort() {
std::sort(begin(), end());
return *this; return *this;
} }
//! \~english Sorts the elements in non-descending order.
//! \~russian Сортировка элементов в порядке возрастания.
//! \~\details
//! \~english The order of equal elements is not guaranteed to be preserved.
//! Elements are compared using the given binary comparison function `comp`.
//! which returns `true` if the first argument is less than (i.e. is ordered before) the second.
//! The signature of the comparison function should be equivalent to the following:
//! \code
//! bool comp(const T &a, const T &b);
//! \endcode
//! 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).
//! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
//! Для сравнения элементов используется функция сравнения `comp`.
//! Функция сравнения, возвращает `true` если первый аргумент меньше второго.
//! Сигнатура функции сравнения должна быть эквивалентна следующей:
//! \code
//! bool comp(const T &a, const T &b);
//! \endcode
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
//! Функция обязана возвращать `false` для одинаковых элементов,
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`.
//! \~\code
//! PIDeque<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
//! v.sort([](const int & a, const int & b){return a > b;});
//! piCout << v; // 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
//! \endcode
//! \~\sa \a sort()
inline PIDeque<T> & sort(std::function<bool(const T &a, const T &b)> comp) {
std::sort(begin(), end(), comp);
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();
@@ -1579,15 +501,6 @@ 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) {
@@ -1597,16 +510,6 @@ 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) {
@@ -1616,18 +519,6 @@ 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])) {
@@ -1638,389 +529,44 @@ 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_forward(pid_size + 1); alloc(pid_size + 1, true);
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_forward(pid_size + 1); alloc(pid_size + 1, true);
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);}
//! \~english Appends the given elements to the end of the array. inline PIDeque<T> & append(T && e) {return push_back(std::move(e));}
//! \~russian Добавляет элементы в конец массива. inline PIDeque<T> & append(const PIDeque<T> & v) {
//! \~\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
if (&v == this) {
printf("error with PIDeque<%s>::append\n", __PIP_TYPENAME__(T));
}
#endif
assert(&v != this); assert(&v != this);
size_t ps = pid_size; size_t ps = pid_size;
alloc_forward(pid_size + v.pid_size); alloc(pid_size + v.pid_size, true);
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);}
//! \~english Appends the given element `e` to the begin of the array. inline PIDeque<T> & push_front(const T & e) {insert(0, e); return *this;}
//! \~russian Добавляет элемент `e` в начало массива. inline PIDeque<T> & push_front(T && e) {insert(0, std::move(e)); return *this;}
//! \~\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));}
//! \~english Appends the given array `v` to the begin of the array. inline PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;}
//! \~russian Добавляет массив `v` в начало массива. inline PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;}
//! \~\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);}
//! \~english Appends the given elements to the begin of the array. inline T take_back() {T e(back()); pop_back(); return e;}
//! \~russian Добавляет элементы в начало массива. inline T take_front() {T e(front()); pop_front(); return e;}
//! \~\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>
inline PIDeque<ST> toType() const { 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]);
@@ -2028,176 +574,55 @@ public:
return ret; return ret;
} }
//! \~english Returns a new array with all elements const PIDeque<T> & forEach(std::function<void(const T & e)> f) const {
//! that pass the test implemented by the provided function `test`. for (size_t i = 0; i < pid_size; ++i) {
//! \~russian Возвращает новый массив со всеми элементами, f(pid_data[i + pid_start]);
//! прошедшими проверку, задаваемую в передаваемой функции `test`.
//! \~\details
//! \~\code
//! PIDeque<int> v{3, 2, 5, 2, 7};
//! PIDeque<int> v2 = v.filter([](const int & i){return i > 2;});
//! piCout << v2; // {3, 5, 7}
//! \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;
}
//! \~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
//! 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;
} }
PIDeque<T> copyForEach(std::function<T(const T & e)> f) const {
//! \~english Сreates a new array populated with the results PIDeque<T> ret; ret.reserve(pid_size);
//! of calling a provided function `ST f(const T & e)` on every element in the calling array. for (size_t i = 0; i < pid_size; ++i) {
//! \~russian Создаёт новый массив с результатом вызова указанной функции ret << f(pid_data[i + pid_start]);
//! `ST f(const T & e)` для каждого элемента массива. }
//! \~\details return ret;
//! \~english Calls a provided function`ST f(const T & e)` }
//! once for each element in an array, in order, PIDeque<T> & forEachInplace(std::function<T(const T & e)> f) {
//! and constructs a new array from the results. for (size_t i = 0; i < pid_size; ++i)
//! \~russian Метод `map` вызывает переданную функцию `ST f(const T & e)` pid_data[i + pid_start] = f(pid_data[i + pid_start]);
//! один раз для каждого элемента в порядке их появления return *this;
//! и конструирует новый массив из результатов её вызова. }
//! \~\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>
inline PIDeque<ST> map(std::function<ST(const T & e)> f) const { 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 = pid_start; i < pid_start + pid_size; ++i) { for (size_t i = 0; i < pid_size; ++i) {
ret << f(pid_data[i]); ret << f(pid_data[i + pid_start]);
} }
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
//! 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>
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const { PIDeque<ST> toType(std::function<ST(const T & e)> f) const {return map(f);}
template <typename ST>
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 = pid_start; i < pid_start + pid_size; ++i) { for (size_t i = 0; i < pid_size; ++i) {
ret = f(pid_data[i], ret); ret = f(pid_data[i + pid_start], ret);
} }
return ret; return ret;
} }
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array. inline PIDeque<PIDeque<T>> reshape(size_t rows, size_t cols, int order = byRow) const {
//! \~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
if (rows*cols != pid_size) {
printf("error with PIDeque<%s>::reshape\n", __PIP_TYPENAME__(T));
}
#endif
assert(rows*cols == pid_size); assert(rows*cols == pid_size);
ret.resize(rows); ret.resize(rows);
if (order == ReshapeByRow) { if (order == byRow) {
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 == ReshapeByColumn) { if (order == byColumn) {
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++) {
@@ -2208,35 +633,21 @@ 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> flatten(ReshapeOrder order = ReshapeByRow) const { inline PIDeque<C> reshape(int order = byRow) 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 == ReshapeByRow) { if (order == byRow) {
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 == ReshapeByColumn) { if (order == byColumn) {
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];
@@ -2247,32 +658,6 @@ 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) {
@@ -2280,9 +665,10 @@ 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 = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1; ssize_t t = 0, 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<
@@ -2345,7 +731,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() { inline void checkMove(bool direction) {
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))) {
@@ -2364,10 +750,11 @@ private:
} }
} }
} }
inline void alloc_forward(size_t new_size) { // direction == true -> alloc forward inline void alloc(size_t new_size, bool direction, ssize_t start_offset = 0) { // 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(); checkMove(direction);
return; return;
} }
pid_size = new_size; pid_size = new_size;
@@ -2375,17 +762,11 @@ private:
if (as != pid_rsize) { if (as != pid_rsize) {
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize)) PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T))); T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T)));
#ifndef NDEBUG
if (!p_d) {
printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
}
#endif
assert(p_d); assert(p_d);
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);
@@ -2406,7 +787,8 @@ private:
} }
pid_start += start_offset; pid_start += start_offset;
pid_size = new_size; pid_size = new_size;
checkMove(); checkMove(direction);
}
} }
T * pid_data; T * pid_data;
@@ -2416,8 +798,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).
//! \~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 << "{";
@@ -2430,10 +810,6 @@ 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();
@@ -2448,8 +824,7 @@ inline PICout operator <<(PICout s, const PIDeque<T> & v) {
return s; return s;
} }
template<typename T> template<typename T> inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);}
inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);}
#endif // PIDEQUE_H #endif // PIDEQUE_H

View File

@@ -30,6 +30,41 @@
#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;
@@ -40,19 +75,16 @@ 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)) {} PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
for (auto i: init_list)
insert(std::get<0>(i), std::get<1>(i));
}
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;
} }
@@ -167,45 +199,38 @@ 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) pim_content.insert(i, PIPair<Key, T>(key, T())); if (f) return pim_content[pim_index[i].index];
return pim_content[i].second; pim_content.push_back(T());
} pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
const T operator [](const Key & key) const { return pim_content.back();
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) {
#ifndef NDEBUG
if (&other == this) {
printf("error with PIMap<%s, %s>::<<\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
}
#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_content.size_s(); ++i) for (int i = 0; i < other.pim_index.size_s(); ++i)
insert(other.pim_content[i].first, other.pim_content[i].second); insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]);
return *this; return *this;
} }
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content);} bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content && 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 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);return *this;} PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;}
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;} PIMap<Key, T> & 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(); return *this;} PIMap<Key, T> & clear() {pim_content.clear(); pim_index.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) {
@@ -213,9 +238,10 @@ 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[i].second = value; pim_content[pim_index[i].index] = value;
} else { } else {
pim_content.insert(i, PIPair<Key, T>(key, value)); pim_content.push_back(value);
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
} }
return *this; return *this;
} }
@@ -224,34 +250,20 @@ 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[i].second = std::move(value); pim_content[pim_index[i].index] = 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 { 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];}
bool f(false); PIVector<T> values() const {return pim_content;}
ssize_t i = _find(key, f); 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_;}
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 (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].first; for (int i = 0; i < pim_index.size_s(); ++i)
ret << pim_index[i].key;
return ret; return ret;
} }
@@ -259,53 +271,66 @@ 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_content[mid].first) first = mid + 1; if (key > pim_index[mid].key) first = mid + 1;
else if (key < pim_content[mid].first) last = mid - 1; else if (key < pim_index[mid].key) 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_content.isEmpty()) { if (pim_index.isEmpty()) {
found = false; found = false;
return 0; return 0;
} }
return binarySearch(0, pim_content.size_s() - 1, k, found); return binarySearch(0, pim_index.size_s() - 1, k, found);
} }
void _remove(ssize_t index) { void _remove(ssize_t index) {
pim_content.remove(index); //if (index >= pim_index.size()) return;
size_t ci = pim_index[index].index, bi = pim_index.size() - 1;
pim_index.remove(index);
for (size_t i = 0; i < pim_index.size(); ++i)
if (pim_index[i].index == bi) {
pim_index[i].index = ci;
break;
}
piSwap<T>(pim_content[ci], pim_content.back());
pim_content.resize(pim_index.size());
} }
const value_type _pair(ssize_t index) const { const value_type _pair(ssize_t index) const {
if (index < 0 || index >= pim_content.size_s()) return value_type(); if (index < 0 || index >= pim_index.size_s())
return pim_content[index]; return value_type();
//piCout << "_pair" << index << pim_index[index].index;
return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
} }
Key & _key(ssize_t index) {return pim_content[index].first;} Key & _key(ssize_t index) {return pim_index[index].key;}
T & _value(ssize_t index) {return pim_content[index].second;} T & _value(ssize_t index) {return pim_content[pim_index[index].index];}
PIDeque<PIPair<Key, T>> pim_content; PIVector<T> pim_content;
PIDeque<MapIndex> pim_index;
}; };

View File

@@ -1,17 +1,8 @@
//! \addtogroup Containers /*! \file pipair.h
//! \{ * \brief pair
//! \file pipair.h *
//! \brief * This file declare PIPair
//! \~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
@@ -34,111 +25,32 @@
#ifndef PIPAIR_H #ifndef PIPAIR_H
#define PIPAIR_H #define PIPAIR_H
#include "picout.h" #include "pibase.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();}
//! \~english Constructs an empty PIPair. PIPair(std::tuple<Type0, Type1> tuple) {first = std::get<0>(tuple); second = std::get<1>(tuple);}
//! \~russian Создает пустой PIPair. PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}
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) { inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;}
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) { inline bool operator ==(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return (value0.first == value1.first) && (value0.second == value1.second);}
return (value0.first != value1.first) || (value0.second != value1.second); 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);}
#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) { inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> & v) {s << "(" << v.first << ", " << v.second << ")"; return s;}
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) { 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;}
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 piqueue.h /*! \file pideque.h
* \brief Queue container * \brief Queue container
* *
* This file declare PIQueue * This file declare PIQueue

View File

@@ -1,17 +1,17 @@
//! \addtogroup Containers /*! \addtogroup Containers
//! \{ * \{
//! \file pivector.h * \file pivector.h
//! \brief * \brief
//! \~english Declares \a PIVector * \~english Declares \a PIVector
//! \~russian Объявление \a PIVector * \~russian Объявление \a PIVector
//! \~\authors * \~\authors
//! \~english * \~english
//! Ivan Pelipenko peri4ko@yandex.ru; * Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru; * Andrey Bychkov work.a.b@yandex.ru;
//! \~russian * \~russian
//! Иван Пелипенко peri4ko@yandex.ru; * Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru; * Андрей Бычков work.a.b@yandex.ru;
//! \~\} * \~\} */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Sequence linear container aka dynamic size array of any type Sequence linear container aka dynamic size array of any type
@@ -36,166 +36,98 @@
#include "picontainers.h" #include "picontainers.h"
/*! \addtogroup Containers
//! \addtogroup Containers * \{
//! \{ * \class PIVector pivector.h
//! \class PIVector * \brief
//! \brief * \~english Sequence linear container - dynamic size array of any type
//! \~english Sequence linear container - dynamic size array of any type. * \~russian Последовательный контейнер с линейной памятью - динамический массив любого типа
//! \~russian Последовательный контейнер с линейной памятью - динамический массив любого типа. * \~\}
//! \~\} * \details
//! \details * \~english
//! \~english * 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(), * The storage of the vector is handled automatically,
//! to remove elements you can use functions \a remove() and \a removeOne(), \a removeWhere(). * being expanded and contracted as needed.
//! Change size by function \a resize() and \a assign(). * Vectors usually occupy more space than static arrays,
//! Items in an array are numbered, starting from zero. * because more memory is allocated to handle future growth.
//! This number is called the item's index. * This way a vector does not need to reallocate each time an element is inserted,
//! So the first item has index 0, the last has index `size() - 1`. * but only when the additional memory is exhausted.
//! A set of various convenient functions is also available for the array, * The total amount of allocated memory can be queried using \a capacity() function.
//! for example: \a indexOf(), \a contains(), \a entries(), \a isEmpty(), \a isNotEmpty(), * Reallocations are usually costly operations in terms of performance.
//! \a every(), \a any(), \a forEach(), \a indexWhere(), \a getRange(), \a sort(), * The \a reserve() function can be used to eliminate reallocations
//! \a map(), \a reduce(), \a filter(), \a flatten(), \a reshape() and others. * if the number of elements is known beforehand.
//! *
//! The storage of the PIVector is handled automatically, * The complexity (efficiency) of common operations on vectors is as follows:
//! being expanded as needed. * - Random access - constant 𝓞(1)
//! PIVector usually occupy more space than static arrays, * - Insertion or removal of elements at the end - amortized constant 𝓞(1)
//! because more memory is allocated to handle future growth. * - Insertion or removal of elements - linear in the distance to the end of the vector 𝓞(n)
//! This way a PIVector does not need to reallocate each time an element is inserted, *
//! but only when the additional memory is exhausted. * \~russian
//! 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 PIVector is as follows: * Память вектора обрабатывается автоматически,
//! - Random access - 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 array 𝓞(n) * поскольку больше памяти выделяется для обработки будущего роста.
//! * Таким образом, память для вектора требуется выделять
//! \~russian * не при каждой вставке элемента,
//! Элементы хранятся непрерывно, а значит доступны не только через итераторы, * а только после исчерпания дополнительной памяти.
//! но и с помощью смещений для обычных указателей на элементы. * Общий объём выделенной памяти можно получить с помощью функции \a capacity().
//! Это означает, что указатель на элемент PIVector может передаваться в любую функцию, *
//! ожидающую указатель на элемент массива. * Выделение памяти обычно является дорогостоящей операцией
//! Добавить элементы можно с помощью функции \a append() или \a insert(), * с точки зрения производительности.
//! а удалить с помощью \a remove() или \a removeOne(), \a removeWhere(). * Функцию \a reserve() можно использовать для исключения выделения памяти,
//! Изменить размер можно функцией \a resize() или \a assign(). * если количество элементов известно заранее.
//! Массив индексируется с нуля: *
//! первый элемент массива имеет индекс, равный `0`, * Сложность (эффективность) обычных операций над векторами следующая:
//! а индекс последнего элемента равен `size() - 1`. * - Произвольный доступ — постоянная 𝓞(1)
//! Также для массива доступен набор различных удобных функций, * - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1)
//! например: \a indexOf(), \a contains(), \a entries(), \a isEmpty(), \a isNotEmpty(), * - Вставка и удаление элементов — линейная по расстоянию до конца вектора 𝓞(n)
//! \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 reserve() можно использовать для исключения выделения памяти,
//! если количество элементов известно заранее.
//!
//! Сложность (эффективность) обычных операций над PIVector следующая:
//! - Произвольный доступ — постоянная 𝓞(1)
//! - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1)
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива 𝓞(n)
//!
//! \~\sa \a PIDeque, \a PIMap
template <typename T> template <typename T>
class PIVector { class PIVector {
public: public:
typedef bool (*CompareFunc)(const T & , const T & ); //! Contructs an empty vector
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 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 Contructs vector with size "size" filled elements "value"
//! \~english Contructs array from raw `data`.
//! This constructor reserve `size` and copy from `data` pointer.
//! \~russian Создает массив из указателя на данные `data` и размер `size`.
//! То есть выделяет память для `size` элементов и копирует данные из указателя `data`.
inline PIVector(const T * data, size_t size): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(const T * data, size_t size): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(size); alloc(size);
newT(piv_data, data, piv_size); newT(piv_data, data, piv_size);
} }
//! \~english Copy constructor.
//! \~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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(v.piv_size); alloc(v.piv_size);
newT(piv_data, v.piv_data, piv_size); newT(piv_data, v.piv_data, piv_size);
} }
//! \brief Contructs vector from C++11 initializer list
//! \~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
//! PIVector <int> v{1,2,3};
//! piCout << v; // {1, 2, 3}
//! \endcode
inline PIVector(std::initializer_list<T> init_list): piv_data(0), piv_size(0), piv_rsize(0) { inline PIVector(std::initializer_list<T> init_list): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(init_list.size()); alloc(init_list.size());
newT(piv_data, init_list.begin(), init_list.size()); newT(piv_data, init_list.begin(), init_list.size());
} }
inline PIVector(size_t piv_size, const T & f = T()): piv_data(0), piv_size(0), piv_rsize(0) {
//! \~english Contructs array with size `size` filled elements `e`.
//! \~russian Создает массив из `size` элементов заполненных `e`.
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(piv_size, f);
} }
inline PIVector(size_t piv_size, std::function<T(size_t i)> f): piv_data(0), piv_size(0), piv_rsize(0) {
//! \~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
//! PIVector <int> v(5, [](size_t i){return i*2;});
//! piCout << v; // {0, 2, 4, 6, 8}
//! \endcode
inline PIVector(size_t size, std::function<T(size_t i)> f): piv_data(0), piv_size(0), piv_rsize(0) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(size, f); resize(piv_size, f);
} }
//! \~english Move constructor.
//! \~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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
v._reset(); v._reset();
} }
inline virtual ~PIVector() { inline virtual ~PIVector() {
PIINTROSPECTION_CONTAINER_DELETE(T) PIINTROSPECTION_CONTAINER_DELETE(T)
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize)) PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
@@ -204,8 +136,6 @@ public:
_reset(); _reset();
} }
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIVector<T> & operator =(const PIVector<T> & v) { inline PIVector<T> & operator =(const PIVector<T> & v) {
if (this == &v) return *this; if (this == &v) return *this;
clear(); clear();
@@ -215,502 +145,107 @@ public:
return *this; return *this;
} }
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIVector<T> & operator =(PIVector<T> && v) { inline PIVector<T> & operator =(PIVector<T> && v) {
swap(v); swap(v);
return *this; return *this;
} }
enum ReshapeOrder {
byRow,
byColumn
};
class iterator { class iterator {
friend class PIVector<T>; friend class PIVector<T>;
private: private:
inline iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {} inline iterator(PIVector<T> * v, size_t p): parent(v), pos(p) {}
PIVector<T> * parent; PIVector<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline iterator(): parent(0), pos(0) {} inline iterator(): parent(0), pos(0) {}
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 T & operator ->() {return (*parent)[pos];} inline void operator ++() {++pos;}
inline const T & operator ->() const {return (*parent)[pos];} inline void operator ++(int) {++pos;}
inline void operator --() {--pos;}
inline iterator & operator ++() { inline void operator --(int) {--pos;}
++pos;
return *this;
}
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 +=(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 -(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;
}
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
return it1.pos - it2.pos;
}
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) {
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 {
friend class PIVector<T>; friend class PIVector<T>;
private: private:
inline const_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {} inline const_iterator(const PIVector<T> * v, size_t p): parent(v), pos(p) {}
const PIVector<T> * parent; const PIVector<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_iterator(): parent(0), pos(0) {} inline const_iterator(): parent(0), pos(0) {}
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 void operator ++() {++pos;}
inline void operator ++(int) {++pos;}
inline const_iterator & operator ++() { inline void operator --() {--pos;}
++pos; inline void operator --(int) {--pos;}
return *this;
}
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 +=(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 -(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;
}
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
return it1.pos - it2.pos;
}
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) {
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 {
friend class PIVector<T>; friend class PIVector<T>;
private: private:
inline reverse_iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {} inline reverse_iterator(PIVector<T> * v, size_t p): parent(v), pos(p) {}
PIVector<T> * parent; PIVector<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline reverse_iterator(): parent(0), pos(0) {} inline reverse_iterator(): parent(0), pos(0) {}
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 T & operator ->() {return (*parent)[pos];} inline void operator ++() {--pos;}
inline const T & operator ->() const {return (*parent)[pos];} inline void operator ++(int) {--pos;}
inline void operator --() {++pos;}
inline reverse_iterator & operator ++() { inline void operator --(int) {++pos;}
--pos;
return *this;
}
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 +=(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 -(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;
}
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
return it2.pos - it1.pos;
}
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) {
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 {
friend class PIVector<T>; friend class PIVector<T>;
private: private:
inline const_reverse_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {} inline const_reverse_iterator(const PIVector<T> * v, size_t p): parent(v), pos(p) {}
const PIVector<T> * parent; const PIVector<T> * parent;
ssize_t pos; size_t pos;
public: public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
inline const_reverse_iterator(): parent(0), pos(0) {} inline const_reverse_iterator(): parent(0), pos(0) {}
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 void operator ++() {--pos;}
inline void operator ++(int) {--pos;}
inline const_reverse_iterator & operator ++() { inline void operator --() {++pos;}
--pos; inline void operator --(int) {++pos;}
return *this;
}
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 +=(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 -(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;
}
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 +(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) {
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, piv_size);} inline iterator end() {return iterator(this, piv_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, piv_size);} inline const_iterator end() const {return const_iterator(this, piv_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, piv_size - 1);} inline reverse_iterator rbegin() {return reverse_iterator(this, piv_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, 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);}
//! \~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 piv_size;} inline size_t size() const {return piv_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 piv_size;} inline ssize_t size_s() const {return piv_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 piv_size;} inline size_t length() const {return piv_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 piv_rsize;} inline size_t capacity() const {return piv_rsize;}
//! \~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 (piv_size == 0);} inline bool isEmpty() const {return (piv_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 (piv_size > 0);} inline bool isNotEmpty() const {return (piv_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
//! PIVector<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 (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;
} }
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
//! PIVector<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 (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
if (!test(piv_data[i])) return false; if (!test(piv_data[i])) return false;
@@ -718,407 +253,111 @@ 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
//! PIVector<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 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];}
//! \~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 piv_data[index];} inline const T & at(size_t index) const {return piv_data[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 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];}
//! \~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 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];}
inline bool operator ==(const PIVector<T> & t) const {
//! \~english Compare operator with array `v`. if (piv_size != t.piv_size) {
//! \~russian Оператор сравнения с массивом `v`. return false;
inline bool operator ==(const PIVector<T> & v) const { }
if (piv_size != v.piv_size) return false;
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
if (v[i] != piv_data[i]) return false; if (t[i] != piv_data[i]) {
return false;
}
} }
return true; return true;
} }
inline bool operator !=(const PIVector<T> & t) const {return !(*this == t);}
//! \~english Compare operator with array `v`. inline bool operator <(const PIVector<T> & t) const {
//! \~russian Оператор сравнения с массивом `v`. if (piv_size != t.piv_size) return piv_size < t.piv_size;
inline bool operator !=(const PIVector<T> & v) const {return !(*this == v);} for (size_t i = 0; i < piv_size; ++i) {
if ((*this)[i] != t[i]) return (*this)[i] < t[i];
//! \~english Tests if element `e` exists in the array.
//! \~russian Проверяет наличие элемента `e` в массиве.
//! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! **false** is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается **false**, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIVector<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 = piv_size + start;
if (start < 0) start = 0;
}
for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) return true;
} }
return false; return false;
} }
inline bool operator >(const PIVector<T> & t) const {
//! \~english Count elements equal `e` in the array. if (piv_size != t.piv_size) return piv_size > t.piv_size;
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. for (size_t i = 0; i < piv_size; ++i) {
//! \~\details if ((*this)[i] != t[i]) return (*this)[i] > t[i];
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! 0 is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается 0, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIVector<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, ssize_t start = 0) const {
int ec = 0;
if (start < 0) {
start = piv_size + start;
if (start < 0) start = 0;
} }
return false;
}
inline bool contains(const T & e) const {
for (size_t i = 0; i < piv_size; ++i) {
if (e == piv_data[i]) {
return true;
}
}
return false;
}
inline int etries(const T & e, size_t start = 0) const {
int ec = 0;
if (start >= piv_size) return ec;
for (size_t i = start; i < piv_size; ++i) { for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) ++ec; if (e == piv_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, ssize_t start = 0) const {
int ec = 0; int ec = 0;
if (start < 0) { if (start >= piv_size) return ec;
start = piv_size + start;
if (start < 0) start = 0;
}
for (size_t i = start; i < piv_size; ++i) { for (size_t i = start; i < piv_size; ++i) {
if (test(piv_data[i])) ++ec; if (test(piv_data[i])) ++ec;
} }
return ec; return ec;
} }
inline ssize_t indexOf(const T & e, size_t start = 0) const {
//! \~english Returns the first index at which a given element `e` if (start >= piv_size) return -1;
//! 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
//! PIVector<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, ssize_t start = 0) const {
if (start < 0) {
start = piv_size + start;
if (start < 0) start = 0;
}
for (size_t i = start; i < piv_size; ++i) { for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) return i; if (e == piv_data[i]) {
return i;
}
} }
return -1; return -1;
} }
inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
//! \~english Returns the first index passes the test implemented by the provided function `test`, if (start >= piv_size) return -1;
//! 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
//! PIVector<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, ssize_t start = 0) const {
if (start < 0) {
start = piv_size + start;
if (start < 0) start = 0;
}
for (size_t i = start; i < piv_size; ++i) { for (size_t i = start; i < piv_size; ++i) {
if (test(piv_data[i])) return i; if (test(piv_data[i])) {
return i;
}
} }
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
//! PIVector<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 >= size_s()) start = piv_size - 1; if (start < 0) start = piv_size - 1;
if (start < 0) start = piv_size + start; else start = piMin<ssize_t>(piv_size - 1, start);
for (ssize_t i = start; i >= 0; --i) { for (ssize_t i = start; i >= 0; --i) {
if (e == piv_data[i]) return i; if (e == piv_data[i]) {
return i;
}
} }
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 >= size_s()) start = piv_size - 1; if (start < 0) start = piv_size - 1;
if (start < 0) start = piv_size + start; else start = piMin<ssize_t>(piv_size - 1, start);
for (ssize_t i = start; i >= 0; --i) { for (ssize_t i = start; i >= 0; --i) {
if (test(piv_data[i])) return i; if (test(piv_data[i])) {
return i;
}
} }
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
//! PIVector<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 &(piv_data[index]);} inline T * data(size_t index = 0) {return &(piv_data[index]);}
//! \~english Read only pointer to array
//! \~russian Указатель на память массива только для чтения.
//! \~\details
//! \~english The pointer can be used to access and modify the items in the array.
//! The pointer remains valid as long as the array isn't reallocated.
//! Optional argument `index` the position in this array,
//! where is pointer. Default: start of array.
//! \~russian Указатель можно использовать для доступа и изменения элементов в массиве.
//! Указатель остается действительным только до тех пор, пока массив не будет перераспределен.
//! Опциональный аргумент `index` указывает на индекс c которого брать указатель.
//! По умолчанию указывает на начало массива.
//! \~\code
//! PIVector<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 &(piv_data[index]);} inline const T * data(size_t index = 0) const {return &(piv_data[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`).
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);
} }
//! \~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>
@@ -1135,33 +374,14 @@ public:
return *this; return *this;
} }
//! \~english Assigns element 'e' to all items in the array. inline PIVector<T> & fill(const T & f = T()) {
//! \~russian Заполняет весь массив копиями элемента 'e'.
//! \~\details
//! \code
//! PIVector<int> v{1, 3, 5};
//! v.fill(7);
//! piCout << v; // {7, 7, 7}
//! \endcode
//! \~\sa \a resize()
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, e); elementNew(piv_data + i, f);
} }
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
//! PIVector<int> v{1, 3, 5};
//! v.fill([](size_t i){return i*2;});
//! piCout << v; // {0, 2, 4}
//! \endcode
//! \~\sa \a resize()
inline PIVector<T> & fill(std::function<T(size_t i)> f) { inline PIVector<T> & fill(std::function<T(size_t i)> f) {
deleteT(piv_data, piv_size); deleteT(piv_data, piv_size);
PIINTROSPECTION_CONTAINER_USED(T, piv_size) PIINTROSPECTION_CONTAINER_USED(T, piv_size)
@@ -1170,15 +390,7 @@ public:
} }
return *this; return *this;
} }
inline PIVector<T> & assign(const T & f = T()) {return fill(f);}
//! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize()
inline PIVector<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>
@@ -1194,18 +406,7 @@ public:
return fill(f); return fill(f);
} }
//! \~english Sets size of the array, new elements are copied from `e`. inline PIVector<T> & resize(size_t new_size, const T & f = T()) {
//! \~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 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);
@@ -1216,23 +417,11 @@ 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, e); elementNew(piv_data + i, f);
} }
} }
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 PIVector<T> & resize(size_t new_size, std::function<T(size_t i)> f) { inline PIVector<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
if (new_size < piv_size) { if (new_size < piv_size) {
T * de = &(piv_data[new_size]); T * de = &(piv_data[new_size]);
@@ -1249,7 +438,6 @@ public:
} }
return *this; return *this;
} }
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>
@@ -1263,25 +451,10 @@ public:
alloc(new_size); alloc(new_size);
return *this; return *this;
} }
inline void _copyRaw(T * dst, const T * src, size_t size) { inline void _copyRaw(T * dst, const T * src, size_t size) {
newT(dst, src, 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 PIVector<T> & reserve(size_t new_size) { inline PIVector<T> & reserve(size_t new_size) {
if (new_size <= piv_rsize) return *this; if (new_size <= piv_rsize) return *this;
size_t os = piv_size; size_t os = piv_size;
@@ -1290,17 +463,6 @@ public:
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
//! PIVector<int> v{1, 3, 5};
//! v.insert(2, 7);
//! piCout << v; // {1, 3, 7, 5}
//! \endcode
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIVector<T> & insert(size_t index, const T & e = T()) { inline PIVector<T> & insert(size_t index, const T & e = T()) {
alloc(piv_size + 1); alloc(piv_size + 1);
if (index < piv_size - 1) { if (index < piv_size - 1) {
@@ -1311,13 +473,6 @@ public:
elementNew(piv_data + index, e); elementNew(piv_data + 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 PIVector<T> & insert(size_t index, T && e) { inline PIVector<T> & insert(size_t index, T && e) {
alloc(piv_size + 1); alloc(piv_size + 1);
if (index < piv_size - 1) { if (index < piv_size - 1) {
@@ -1328,20 +483,8 @@ public:
elementNew(piv_data + index, std::move(e)); elementNew(piv_data + index, std::move(e));
return *this; 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 PIVector<T> & insert(size_t index, const PIVector<T> & v) { inline PIVector<T> & insert(size_t index, const PIVector<T> & v) {
if (v.isEmpty()) return *this; if (v.isEmpty()) return *this;
#ifndef NDEBUG
if (&v == this) {
printf("error with PIVector<%s>::insert\n", __PIP_TYPENAME__(T));
}
#endif
assert(&v != this); assert(&v != this);
ssize_t os = piv_size - index; ssize_t os = piv_size - index;
alloc(piv_size + v.piv_size); alloc(piv_size + v.piv_size);
@@ -1352,35 +495,6 @@ public:
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 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.
//! \~russian Удаляет элементы из массива, начиная с позиции `index` в количестве `count`.
//! \~\details
//! \code
//! PIVector<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 PIVector<T> & remove(size_t index, size_t count = 1) { inline PIVector<T> & remove(size_t index, size_t count = 1) {
if (count == 0) return *this; if (count == 0) return *this;
if (index + count >= piv_size) { if (index + count >= piv_size) {
@@ -1394,140 +508,30 @@ 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(PIVector<T> & v) { inline void swap(PIVector<T> & v) {
piSwap<T*>(piv_data, v.piv_data); piSwap<T*>(piv_data, v.piv_data);
piSwap<size_t>(piv_size, v.piv_size); piSwap<size_t>(piv_size, v.piv_size);
piSwap<size_t>(piv_rsize, v.piv_rsize); piSwap<size_t>(piv_rsize, v.piv_rsize);
} }
//! \~english Sorts the elements in non-descending order. typedef int (*CompareFunc)(const T * , const T * );
//! \~russian Сортировка элементов в порядке возрастания. static int compare_func(const T * t0, const T * t1) {return (*t0) < (*t1) ? -1 : ((*t0) == (*t1) ? 0 : 1);}
//! \~\details inline PIVector<T> & sort(CompareFunc compare = compare_func) {
//! \~english The order of equal elements is not guaranteed to be preserved. piqsort(piv_data, piv_size, sizeof(T), (int(*)(const void * , const void * ))compare);
//! Elements are compared using operator<.
//! Sorting provided by [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort).
//! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
//! Для сравнения элементов используется оператор `operator<`.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`.
//! \~\code
//! PIVector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
//! v.sort();
//! piCout << v; // {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
//! \endcode
//! \~\sa \a sort(std::function<bool(const T &a, const T &b)> comp)
inline PIVector<T> & sort() {
std::sort(begin(), end());
return *this; return *this;
} }
//! \~english Sorts the elements in non-descending order. inline PIVector<T> & enlarge(llong piv_size) {
//! \~russian Сортировка элементов в порядке возрастания. llong ns = size_s() + piv_size;
//! \~\details
//! \~english The order of equal elements is not guaranteed to be preserved.
//! Elements are compared using the given binary comparison function `comp`.
//! which returns `true` if the first argument is less than (i.e. is ordered before) the second.
//! The signature of the comparison function should be equivalent to the following:
//! \code
//! bool comp(const T &a, const T &b);
//! \endcode
//! 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).
//! Complexity `O(N·log(N))`.
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
//! Для сравнения элементов используется функция сравнения `comp`.
//! Функция сравнения, возвращает `true` если первый аргумент меньше второго.
//! Сигнатура функции сравнения должна быть эквивалентна следующей:
//! \code
//! bool comp(const T &a, const T &b);
//! \endcode
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
//! Функция обязана возвращать `false` для одинаковых элементов,
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
//! Сложность сортировки `O(N·log(N))`.
//! \~\code
//! PIVector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
//! v.sort([](const int & a, const int & b){return a > b;});
//! piCout << v; // {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
//! \endcode
//! \~\sa \a sort()
inline PIVector<T> & sort(std::function<bool(const T &a, const T &b)> comp) {
std::sort(begin(), end(), comp);
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
//! PIVector<int> v{1, 3, 7, 5};
//! v.reverse();
//! piCout << v; // {5, 7, 3, 1}
//! \endcode
//! \~\sa \a reversed()
inline PIVector<T> & reverse() {
size_t s2 = piv_size/2;
for (size_t i = 0; i < s2; ++i) {
piSwap<T>(piv_data[i], piv_data[piv_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 PIVector<T> reversed() const {
PIVector<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 PIVector<T> & enlarge(llong add_size, const T & e = T()) {
llong ns = size_s() + add_size;
if (ns <= 0) clear(); if (ns <= 0) clear();
else resize(size_t(ns), e); else resize(size_t(ns));
return *this; return *this;
} }
//! \~english Remove no more than one element equal `e`. /*! \brief Remove no more than one element equal "v" and return reference to vector
//! \~russian Удаляет первый элемент, который равен элементу `e`. * \details Example: \snippet picontainers.cpp PIVector::removeOne
//! \~\details * \sa \a remove(), \a removeAll()
//! \~\code */
//! PIVector<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 PIVector<T> & removeOne(const T & e) { inline PIVector<T> & removeOne(const T & e) {
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
if (piv_data[i] == e) { if (piv_data[i] == e) {
@@ -1537,18 +541,8 @@ public:
} }
return *this; return *this;
} }
//! \~english Remove all elements equal `e`.
//! \~russian Удаляет все элементы, равные элементу `e`.
//! \~\details
//! \~\code
//! PIVector<int> v{3, 2, 5, 2, 7};
//! v.removeAll(2);
//! piCout << v; // {3, 5, 7}
//! \endcode
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIVector<T> & removeAll(const T & e) { inline PIVector<T> & removeAll(const T & e) {
for (ssize_t i = 0; i < size_s(); ++i) { for (ssize_t i = 0; i < ssize_t(piv_size); ++i) {
if (piv_data[i] == e) { if (piv_data[i] == e) {
remove(i); remove(i);
--i; --i;
@@ -1556,20 +550,8 @@ 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
//! PIVector<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 PIVector<T> & removeWhere(std::function<bool(const T & e)> test) { inline PIVector<T> & removeWhere(std::function<bool(const T & e)> test) {
for (ssize_t i = 0; i < size_s(); ++i) { for (ssize_t i = 0; i < ssize_t(piv_size); ++i) {
if (test(piv_data[i])) { if (test(piv_data[i])) {
remove(i); remove(i);
--i; --i;
@@ -1578,30 +560,6 @@ 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
//! PIVector<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 PIVector<T> & push_back(const T & e) { inline PIVector<T> & push_back(const T & e) {
alloc(piv_size + 1); alloc(piv_size + 1);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
@@ -1609,12 +567,6 @@ public:
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 PIVector<T> & push_back(T && e) { inline PIVector<T> & push_back(T && e) {
alloc(piv_size + 1); alloc(piv_size + 1);
PIINTROSPECTION_CONTAINER_USED(T, 1); PIINTROSPECTION_CONTAINER_USED(T, 1);
@@ -1622,465 +574,80 @@ public:
return *this; return *this;
} }
//! \~english Appends the given elements to the end of the array. inline PIVector<T> & append(const T & e) {return push_back(e);}
//! \~russian Добавляет элементы в конец массива. inline PIVector<T> & append(T && e) {return push_back(std::move(e));}
//! \~\details inline PIVector<T> & append(const PIVector<T> & v) {
//! \~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 PIVector<T> & push_back(std::initializer_list<T> init_list) {
size_t ps = piv_size;
alloc(piv_size + init_list.size());
newT(piv_data + 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 PIVector<T> & push_back(const PIVector<T> & v) {
#ifndef NDEBUG
if (&v == this) {
printf("error with PIVector<%s>::push_back\n", __PIP_TYPENAME__(T));
}
#endif
assert(&v != this); assert(&v != this);
size_t ps = piv_size; size_t ps = piv_size;
alloc(piv_size + v.piv_size); alloc(piv_size + v.piv_size);
newT(piv_data + ps, v.piv_data, v.piv_size); newT(piv_data + ps, v.piv_data, v.piv_size);
return *this; return *this;
} }
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~\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
//! PIVector<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 PIVector<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 PIVector<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 PIVector<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
//! PIVector<int> v{1, 2, 3};
//! v.append(PIVector<int>{4, 5});
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIVector<T> & append(const PIVector<T> & v) {return push_back(v);}
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! v << 4 << 5;
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\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);}
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! v << 4 << 5;
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\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));}
inline PIVector<T> & operator <<(const PIVector<T> & v) {return append(v);}
//! \~english Appends the given array `v` to the end of the array. inline PIVector<T> & push_front(const T & e) {insert(0, e); return *this;}
//! \~russian Добавляет массив `v` в конец массива. inline PIVector<T> & push_front(T && e) {insert(0, std::move(e)); return *this;}
//! \~\details
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! v << PIVector<int>{4, 5};
//! piCout << v; // {1, 2, 3, 4, 5}
//! \endcode
//! \~\sa \a append()
inline PIVector<T> & operator <<(const PIVector<T> & v) {return push_back(v);}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english Adding an element to the beginning takes longer than to the end.
//! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated.
//! \~russian Добавление элемента в начало выполняется дольше, чем в конец.
//! Это время прямопропорционально размеру массива.
//! При добавлении элемента все итераторы и указатели становятся нерабочими.
//! \~\code
//! PIVector<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 PIVector<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 PIVector<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
//! PIVector<int> v{1, 2, 3};
//! v.push_front(PIVector<int>{4, 5});
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a push_front()
inline PIVector<T> & push_front(const PIVector<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 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.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english Adding an element to the beginning takes longer than to the end.
//! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated.
//! \~russian Добавление элемента в начало выполняется дольше, чем в конец.
//! Это время прямопропорционально размеру массива.
//! При добавлении элемента все итераторы и указатели становятся нерабочими.
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! v.prepend(4);
//! v.prepend(5);
//! piCout << v; // {5, 4, 1, 2, 3}
//! \endcode
//! \~\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);}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\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));}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! v.prepend(PIVector<int>{4, 5});
//! piCout << v; // {4, 5, 1, 2, 3}
//! \endcode
//! \~\sa \a prepend()
inline PIVector<T> & prepend(const PIVector<T> & v) {return push_front(v);}
//! \~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.
//! \~russian Удаляет один элемент с конца массива.
//! \~\details
//! \~english Deleting an element from the end is very fast
//! and does not depend on the size of the array.
//! \~russian Удаление элемента с конца выполняется очень быстро
//! и не зависит от размера массива.
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! v.pop_back();
//! piCout << v; // {1, 2}
//! \endcode
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
inline PIVector<T> & pop_back() { inline PIVector<T> & pop_back() {
if (piv_size == 0) return *this; if (piv_size == 0) return *this;
resize(piv_size - 1); resize(piv_size - 1);
return *this; 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
//! PIVector<int> v{1, 2, 3};
//! v.pop_front();
//! piCout << v; // {2, 3}
//! \endcode
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
inline PIVector<T> & pop_front() { inline PIVector<T> & pop_front() {
if (piv_size == 0) return *this; if (piv_size == 0) return *this;
remove(0); remove(0);
return *this; return *this;
} }
//! \~english Remove one element from the end of the array and return it. inline T take_back() {T e(back()); pop_back(); return e;}
//! \~russian Удаляет один элемент с начала массива и возвращает его. inline T take_front() {T e(front()); pop_front(); return e;}
//! \~\details
//! \~\code
//! PIVector<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
//! PIVector<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
//! PIVector<double> v{1.1, 2.5, 3.8};
//! PIVector<int> v2 = v.toType<int>();
//! piCout << v2; // {1, 2, 3}
//! \endcode
//! \~\sa \a map()
template <typename ST> template <typename ST>
inline PIVector<ST> toType() const { PIVector<ST> toType() const {
PIVector<ST> ret; ret.reserve(piv_size); PIVector<ST> ret(piv_size);
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
ret << ST(piv_data[i]); ret[i] = ST(piv_data[i]);
} }
return ret; return ret;
} }
//! \~english Returns a new array with all elements const PIVector<T> & forEach(std::function<void(const T & e)> f) const {
//! 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 {
PIVector<T> ret;
for (size_t i = 0; i < piv_size; ++i) {
if (test(piv_data[i])) ret << piv_data[i];
}
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 {
for (size_t i = 0; i < piv_size; ++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) {
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]);
} }
return *this; return *this;
} }
PIVector<T> copyForEach(std::function<T(const T & e)> f) const {
PIVector<T> ret; ret.reserve(piv_size);
for (size_t i = 0; i < piv_size; ++i) {
ret << f(piv_data[i]);
}
return ret;
}
PIVector<T> & forEachInplace(std::function<T(const T & e)> f) {
for (size_t i = 0; i < piv_size; ++i) {
piv_data[i] = f(piv_data[i]);
}
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 { 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);
for (size_t i = 0; i < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
ret << f(piv_data[i]); ret << f(piv_data[i]);
} }
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 { PIVector<ST> toType(std::function<ST(const T & e)> f) const {return map(f);}
template <typename ST>
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 < piv_size; ++i) { for (size_t i = 0; i < piv_size; ++i) {
ret = f(piv_data[i], ret); ret = f(piv_data[i], ret);
@@ -2088,41 +655,17 @@ public:
return ret; return ret;
} }
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array. inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = byRow) const {
//! \~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};
//! 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
if (rows*cols != piv_size) {
printf("error with PIVector<%s>::reshape\n", __PIP_TYPENAME__(T));
}
#endif
assert(rows*cols == piv_size);
PIVector<PIVector<T>> ret; PIVector<PIVector<T>> ret;
if (isEmpty()) return ret; if (isEmpty()) return ret;
assert(rows*cols == piv_size);
ret.resize(rows); ret.resize(rows);
if (order == ReshapeByRow) { if (order == byRow) {
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 == ReshapeByColumn) { if (order == byColumn) {
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++) {
@@ -2133,35 +676,21 @@ 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> flatten(ReshapeOrder order = ReshapeByRow) const { inline PIVector<C> reshape(ReshapeOrder order = byRow) 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 == ReshapeByRow) { if (order == byRow) {
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 == ReshapeByColumn) { if (order == byColumn) {
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];
@@ -2172,32 +701,6 @@ 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) {
@@ -2205,9 +708,8 @@ 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 = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1; ssize_t t = 0, 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<
@@ -2280,11 +782,6 @@ private:
if (as == piv_rsize) return; if (as == piv_rsize) return;
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-piv_rsize)) PIINTROSPECTION_CONTAINER_ALLOC(T, (as-piv_rsize))
T * p_d = (T*)(realloc((void*)(piv_data), as*sizeof(T))); T * p_d = (T*)(realloc((void*)(piv_data), as*sizeof(T)));
#ifndef NDEBUG
if (!p_d) {
printf("error with PIVector<%s>::alloc\n", __PIP_TYPENAME__(T));
}
#endif
assert(p_d); assert(p_d);
piv_data = p_d; piv_data = p_d;
piv_rsize = as; piv_rsize = as;
@@ -2295,9 +792,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 PIVector<T> & v) { inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {
s << "{"; s << "{";
@@ -2310,9 +806,6 @@ inline std::ostream & operator <<(std::ostream & s, const PIVector<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 PIVector<T> & v) { inline PICout operator <<(PICout s, const PIVector<T> & v) {
s.space(); s.space();
@@ -2329,7 +822,7 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
return s; return s;
} }
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

@@ -275,12 +275,17 @@ public:
mat.clear(); mat.clear();
} }
void forEach(std::function<void(const T &)> f) const { const PIVector2D<T> & forEach(std::function<void(const T &)> f) const {
mat.forEach(f); mat.forEach(f);
return *this;
} }
PIVector2D<T> copyForEach(std::function<T(const T &)> f) const {
PIVector2D<T> & forEach(std::function<void(T &)> f) { PIVector2D<T> ret(*this);
mat.forEach(f); ret.mat = mat.copyForEach(f);
return ret;
}
PIVector2D<T> & forEachInplace(std::function<T(const T &)> f) {
mat.forEachInplace(f);
return *this; return *this;
} }

View File

@@ -38,7 +38,7 @@
#include "piplatform.h" #include "piplatform.h"
#include "pip_export.h" #include "pip_export.h"
#include "pip_defs.h" #include "pip_defs.h"
#include <string.h> #include "string.h"
//! \~english //! \~english
//! Meta-information section for any entity. //! Meta-information section for any entity.
@@ -246,10 +246,9 @@
extern char ** environ; extern char ** environ;
#endif #endif
#ifndef NO_UNUSED #ifdef NDEBUG
# define NO_UNUSED(x) (void)x # undef NDEBUG
#endif #endif
#ifndef assert #ifndef assert
# define assert(x) # define assert(x)
# define assertm(exp, msg) # define assertm(exp, msg)
@@ -257,12 +256,6 @@
# define assertm(exp, msg) assert(((void)msg, exp)) # define assertm(exp, msg) assert(((void)msg, exp))
#endif #endif
#ifdef MICRO_PIP
# define __PIP_TYPENAME__(T) "?"
#else
# define __PIP_TYPENAME__(T) typeid(T).name()
#endif
#ifdef CC_GCC #ifdef CC_GCC
# undef DEPRECATED # undef DEPRECATED
# define DEPRECATED __attribute__((deprecated)) # define DEPRECATED __attribute__((deprecated))
@@ -391,12 +384,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,7 +21,15 @@
#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.

View File

@@ -32,14 +32,16 @@
#include "pivector2d.h" #include "pivector2d.h"
#include <stdio.h> #include <stdio.h>
#ifdef MICRO_PIP
# define _TYPENAME_(T) "?"
#else
# define _TYPENAME_(T) typeid(T).name()
#endif
class PIString; 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:
@@ -272,8 +274,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 //! \~english Store operator, see \ref PIByteArray_sec1 for details
//! \~russian Оператор сохранения //! \~russian Оператор сохранения, подробнее в \ref PIByteArray_sec1
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) {
@@ -392,7 +394,7 @@ inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >=
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0> template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) { inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
if (s.size() < sizeof(v)) { if (s.size() < sizeof(v)) {
printf("error with %s\n", __PIP_TYPENAME__(T)); printf("error with %s\n", _TYPENAME_(T));
assert(s.size() >= sizeof(v)); assert(s.size() >= sizeof(v));
} }
memcpy((void*)(&v), s.data(), sizeof(v)); memcpy((void*)(&v), s.data(), sizeof(v));
@@ -406,8 +408,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 //! \~english Restore operator, see \ref PIByteArray_sec1 for details
//! \~russian Оператор извлечения //! \~russian Оператор извлечения, подробнее в \ref PIByteArray_sec1
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);
@@ -428,7 +430,7 @@ template<typename T,
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
if (s.size_s() < 4) { if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIVector<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; int sz; s >> sz;
@@ -444,7 +446,7 @@ template<typename T,
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
if (s.size_s() < 4) { if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIVector<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; int sz; s >> sz;
@@ -461,7 +463,7 @@ template<typename T,
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
if (s.size_s() < 4) { if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIDeque<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; int sz; s >> sz;
@@ -477,7 +479,7 @@ template<typename T,
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
if (s.size_s() < 4) { if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIDeque<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; int sz; s >> sz;
@@ -494,7 +496,7 @@ template<typename T,
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
if (s.size_s() < 8) { if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIVecto2Dr<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 8); assert(s.size_s() >= 8);
} }
int r, c; s >> r >> c; int r, c; s >> r >> c;
@@ -511,7 +513,7 @@ template<typename T,
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0> typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
if (s.size_s() < 8) { if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIVecto2Dr<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 8); assert(s.size_s() >= 8);
} }
int r,c; int r,c;
@@ -579,7 +581,7 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
if (s.size_s() < 4) { if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIVector<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; int sz; s >> sz;
@@ -594,7 +596,7 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
if (s.size_s() < 4) { if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIDeque<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 4); assert(s.size_s() >= 4);
} }
int sz; s >> sz; int sz; s >> sz;
@@ -609,7 +611,7 @@ inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0> template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
if (s.size_s() < 8) { if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T)); printf("error with PIVecto2Dr<%s>\n", _TYPENAME_(T));
assert(s.size_s() >= 8); assert(s.size_s() >= 8);
} }
int r,c; int r,c;
@@ -630,9 +632,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;
} }
@@ -644,20 +646,20 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
template <typename Key, typename T> template <typename Key, typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) { inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
if (s.size_s() < 4) { if (s.size_s() < 4) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T)); printf("error with PIMap<%s, %s>\n", _TYPENAME_(Key), _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;
} }
@@ -709,4 +711,7 @@ template <typename T> T piDeserialize(const PIByteArray & data) {
} }
#undef _TYPENAME_
#endif // PIBYTEARRAY_H #endif // PIBYTEARRAY_H

View File

@@ -18,7 +18,7 @@
*/ */
#include "piincludes_p.h" #include "piincludes_p.h"
#include "pistring.h" #include "pibytearray.h"
#ifdef PIP_ICU #ifdef PIP_ICU
# define U_NOEXCEPT # define U_NOEXCEPT
# include "unicode/ucnv.h" # include "unicode/ucnv.h"
@@ -35,8 +35,21 @@ 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.
@@ -46,6 +59,7 @@ 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) {
@@ -72,12 +86,10 @@ 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
mbstate_t state; wchar_t wc(0);
memset(&state, 0, sizeof(state)); mbtowc(0, 0, 0); // reset mbtowc
wchar_t wc; ret = mbtowc(&wc, c, size);
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
@@ -375,9 +387,15 @@ PICout operator <<(PICout s, const PIChar & v) {
} else } else
#endif #endif
#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,10 +32,6 @@ 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;
@@ -65,10 +61,6 @@ 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,8 +19,13 @@
#include "pichunkstream.h" #include "pichunkstream.h"
//! \addtogroup Core
//! \{
//! \class PIChunkStream pichunkstream.h //! \class PIChunkStream pichunkstream.h
//! \details //! \brief
//! \~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
@@ -84,6 +89,7 @@
//! \~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,10 +29,6 @@
#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,8 +21,13 @@
#include "pisysteminfo.h" #include "pisysteminfo.h"
//! \addtogroup Core
//! \{
//! \class PICLI picli.h //! \class PICLI picli.h
//! \details //! \~\brief
//! \~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
@@ -38,33 +43,15 @@
//! а также получить их значения при помощи \a argumentValue(). //! а также получить их значения при помощи \a argumentValue().
//! //!
//! \~english \section PICLI_sec1 Example //! \~english \section PICLI_sec1 Example
//! \~russian \section PICLI_sec1 Пример //! \~russian \section PICLI_sec0 Пример
//! \~\code //! \~\snippet picli.cpp main
//! int main(int argc, char ** argv) {
//! PICLI cli(argc, argv);
//! cli.addArgument("console");
//! cli.addArgument("debug");
//! cli.addArgument("Value", "v", "value", true);
//! if (cli.hasArgument("console"))
//! piCout << "console active";
//! if (cli.hasArgument("debug"))
//! piCout << "debug active";
//! piCout << "Value =" << cli.argumentValue("Value");
//! return 0;
//! }
//!
//! These executions are similar:
//! a.out -cd -v 10
//! a.out --value 10 -dc
//! a.out -c -v 10 -d
//! a.out --console -d -v 10
//! a.out --debug -c --value 10
//! \endcode
//! //!
//! /}
PICLI::PICLI(int argc, char * argv[]) { PICLI::PICLI(int argc, char * argv[]) {
needParse = debug_ = true; setName("CLI");
needParse = true;
_prefix_short = "-"; _prefix_short = "-";
_prefix_full = "--"; _prefix_full = "--";
_count_opt = 0; _count_opt = 0;

View File

@@ -26,15 +26,11 @@
#ifndef PICLI_H #ifndef PICLI_H
#define PICLI_H #define PICLI_H
#include "pistringlist.h" #include "piobject.h"
#include "piset.h"
//! \ingroup Core class PIP_EXPORT PICLI: public PIObject
//! \~\brief
//! \~english Command-Line parser.
//! \~russian Парсер командной строки.
class PIP_EXPORT PICLI
{ {
PIOBJECT_SUBCLASS(PICLI, PIObject)
public: public:
//! \~english Constructor //! \~english Constructor
@@ -98,11 +94,6 @@ 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;}
@@ -121,7 +112,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, debug_; bool needParse;
}; };

View File

@@ -20,7 +20,13 @@
#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 Краткий обзор
@@ -35,6 +41,7 @@
//! объектов в глобальные группы. Затем можно получить их список в любом месте программы. //! объектов в глобальные группы. Затем можно получить их список в любом месте программы.
//! \~\snippet picollection.cpp main //! \~\snippet picollection.cpp main
//! //!
//! \}
PIStringList PICollection::groups() { PIStringList PICollection::groups() {

View File

@@ -1,8 +1,8 @@
/*! \file picollection.h /*! \file picollection.h
* \ingroup Core * \ingroup Core
* \~\brief * \~\brief
* \~english Unique classes collection * \~english Custom elements collection
* \~russian Коллекция уникальных классов * \~russian
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -100,10 +100,6 @@
#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

@@ -1,164 +0,0 @@
/*
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

@@ -1,262 +0,0 @@
/*! \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,37 +16,31 @@
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 Core /** \defgroup Core
//! \~\brief * \~\brief
//! \~english Basic functionality. * \~english This module contains basic functionality.
//! \~russian Базовая функциональность. * \~russian Модуль обеспечивает базовую функциональность.
//! *
//! \~\details * \~\details
//! \~english \section cmake_module_Core Building with CMake * Scope | Use
//! \~russian \section cmake_module_Core Сборка с использованием CMake * ----- | -------
//! * C++ | #include <picoremodule.h>
//! \~\code * CMake | PIP
//! find_package(PIP REQUIRED) *
//! target_link_libraries([target] PIP) * \~english
//! \endcode * These files provides platform abstraction, useful macros, methods and classes
//! *
//! \~english \par Common * \~russian
//! \~russian \par Общее * Эти файлы обеспечивают абстракцию операционной системы, полезные макросы, методы и классы
//! *
//! \~english * \~\authors
//! These files provides platform abstraction, useful macros, methods and classes * \~english
//! * Ivan Pelipenko peri4ko@yandex.ru;
//! \~russian * Andrey Bychkov work.a.b@yandex.ru;
//! Эти файлы обеспечивают абстракцию операционной системы, полезные макросы, методы и классы * \~russian
//! * Иван Пелипенко peri4ko@yandex.ru;
//! \~\authors * Андрей Бычков work.a.b@yandex.ru;
//! \~english */
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PICOREMODULE_H #ifndef PICOREMODULE_H
#define PICOREMODULE_H #define PICOREMODULE_H

View File

@@ -22,10 +22,6 @@
#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>
@@ -34,8 +30,13 @@
#endif #endif
//! \addtogroup Core
//! \{
//! \~\class PICout picout.h //! \~\class PICout picout.h
//! \~\details //! \~\brief
//! \~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
@@ -74,6 +75,7 @@
//! \~russian \section PICout_ex1 Создание своего оператора вывода //! \~russian \section PICout_ex1 Создание своего оператора вывода
//! \~\snippet picout.cpp own //! \~\snippet picout.cpp own
//! //!
//! \}
//! \addtogroup Core //! \addtogroup Core
@@ -83,8 +85,8 @@
//! \~english Class for emit notifications of PICout //! \~english Class for emit notifications of PICout
//! \~russian Класс для посылки событий от PICout //! \~russian Класс для посылки событий от PICout
//! //!
//! \~english \section PICoutNotifier_sec0 Synopsis //! \~english \section PICout_sec0 Synopsis
//! \~russian \section PICoutNotifier_sec0 Краткий обзор //! \~russian \section PICout_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
@@ -153,12 +155,15 @@ WORD PICout::__Private__::dattr = 0;
DWORD PICout::__Private__::smode = 0; DWORD PICout::__Private__::smode = 0;
#endif #endif
PICout::PICout(int controls): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(controls) { PICout::PICout(PIFlags<PICoutControl> controls): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(controls) {
init();
}
PICout::PICout(PICoutControl control): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(control) {
init(); init();
} }
PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) { PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) {
buffer_ = nullptr;
if (act_) if (act_)
init(); init();
} }
@@ -318,7 +323,7 @@ PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v)
} }
#define PICOUTTOTARGET(v) { \ #define PICOUTTOTARGET(v) { \
if (buffer_) {\ if (buffer_) {\
(*buffer_) << (v);\ (*buffer_) << (v);\
} else {\ } else {\
@@ -326,45 +331,46 @@ PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v)
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\ if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
}\ }\
} }
#define PICOUTTOTARGETS(v) { \
#define PINUMERICCOUT(v) { \ if (buffer_) {\
if (!act_) return *this; \ (*buffer_) << (v);\
space(); \ } else {\
if (cnb_ == 10) PICOUTTOTARGET(v) \ if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v).dataConsole();\
else write(PIString::fromNumber(v, cnb_)); \ if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
return *this; \ }\
} }
#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGETS(PIString::fromNumber(v, cnb_))
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 char * v) {if (!act_) 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;}
PICout PICout::operator <<(const char v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;} PICout PICout::operator <<(const char v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const uchar v) {PINUMERICCOUT(ushort(v))} PICout PICout::operator <<(const uchar v) {if (!act_) return *this; space(); if (cnb_ == 10) PICOUTTOTARGET(ushort(v)) else PICOUTTOTARGETS(PIString::fromNumber(v, cnb_)) return *this;}
PICout PICout::operator <<(const short int v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const short int v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const ushort v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const ushort v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const int v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const int v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const uint v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const uint v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const long v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const long v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const ulong v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const ulong v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const llong v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const llong v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const ullong v) {PINUMERICCOUT(v)} PICout PICout::operator <<(const ullong v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const float v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;} PICout PICout::operator <<(const float 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 double v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) 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 void * v) {if (!act_) return *this; space(); PICOUTTOTARGET("0x") PICOUTTOTARGETS(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;
@@ -373,9 +379,9 @@ PICout PICout::operator <<(const PIObject * v) {
else { else {
PICOUTTOTARGET(v->className()) PICOUTTOTARGET(v->className())
PICOUTTOTARGET("*(0x") PICOUTTOTARGET("*(0x")
write(PIString::fromNumber(ullong(v), 16)); PICOUTTOTARGETS(PIString::fromNumber(ullong(v), 16))
PICOUTTOTARGET(", \"") PICOUTTOTARGET(", \"")
write(v->name()); PICOUTTOTARGET(v->name())
PICOUTTOTARGET("\")") PICOUTTOTARGET("\")")
} }
return *this; return *this;
@@ -520,47 +526,6 @@ 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) {
if (!act_ || !str) return *this;
if (buffer_) {
buffer_->append(PIString(str, len));
} else {
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout.write(str, len);
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(PIString(str, len));
}
return *this;
}
PICout & PICout::write(const PIString & s) {
if (!act_) return *this;
if (buffer_) {
buffer_->append(s);
} else {
if (PICout::isOutputDeviceActive(PICout::StdOut))
stdoutPIString(s);
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s);
}
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) {
@@ -571,7 +536,7 @@ void PICout::init() {
} }
attr_ = __Private__::dattr; attr_ = __Private__::dattr;
#endif #endif
buffer_ = nullptr; buffer_ = 0;
id_ = 0; id_ = 0;
if ((co_ & NoLock) != NoLock) if ((co_ & NoLock) != NoLock)
PICout::__mutex__().lock(); PICout::__mutex__().lock();

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,16 +125,13 @@ namespace PICoutManipulators {
//! \ingroup Core
//! \~\brief
//! \~english Universal output to console class.
//! \~russian Универсальный вывод в консоль.
class PIP_EXPORT PICout { class PIP_EXPORT PICout {
public: public:
//! \~english Default constructor with default features (AddSpaces and AddNewLine) //! \~english Default constructor with default features (AddSpaces and AddNewLine)
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine) //! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine)
PICout(int controls = PICoutManipulators::DefaultControls); PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls);
PICout(PICoutManipulators::PICoutControl control = PICoutManipulators::DefaultControls);
//! \~english Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing //! \~english Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine), но если не \"active\" то будет неактивным //! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine), но если не \"active\" то будет неактивным
@@ -287,22 +284,6 @@ public:
//! \~russian Условно добавляет новую строку //! \~russian Условно добавляет новую строку
PICout & newLine(); PICout & newLine();
//! \~english Write raw data
//! \~russian Пишет сырые символы
PICout & write(const char * str);
//! \~english Write raw data
//! \~russian Пишет сырые символы
PICout & write(const char * str, int len);
//! \~english Write raw \a PIString
//! \~russian Пишет сырой \a PIString
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" то очищает его
static bool setBufferActive(bool on, bool clear = false); static bool setBufferActive(bool on, bool clear = false);

View File

@@ -35,12 +35,20 @@
//! \addtogroup Core //! \addtogroup Core
//! \{ //! \{
//! \class PISystemTime pitime.h
//! \brief
//! \~english System time with nanosecond precision
//! \~russian Системное время с точностью до наносекунд
//! //!
//! \~\class PITime pidatetime.h //! \~english \section PISystemTime_sec0 Synopsis
//! \~russian \section PISystemTime_sec0 Краткий обзор
//! \~english
//! //!
//! \~\class PIDate pidatetime.h //! \~russian
//! //!
//! \~\class PIDateTime pidatetime.h //! \~english \section PISystemTime_sec1 Example
//! \~russian \section PISystemTime_sec1 Пример
//! \~\snippet pitimer.cpp system_time
//! //!
//! \} //! \}

View File

@@ -30,72 +30,23 @@
#include "pisystemtime.h" #include "pisystemtime.h"
//! \ingroup Core struct PIP_EXPORT PITime {
//! \~\brief
//! \~english Calendar time.
//! \~russian Календарное время.
class PIP_EXPORT PITime {
public:
//! \~english Construct %PITime from hours, minutes, seconds and milliseconds
//! \~russian Создает %PITime из часов, минут, секунд и миллисекунд
PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;} PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;}
//! \~english Returns string representation
//! \~russian Возвращает строковое представление
PIString toString(const PIString & format = "h:mm:ss") const;
//! \~english Returns time as %PISystemTime
//! \~russian Возвращает время как %PISystemTime
PISystemTime toSystemTime() const;
//! \~english Returns current time
//! \~russian Возвращает текущее время
static PITime current();
//! \~english Construct %PITime from %PISystemTime
//! \~russian Создает %PITime из %PISystemTime
static PITime fromSystemTime(const PISystemTime & st);
//! \~english Hour, 0-23
//! \~russian Час, 0-23
int hours; int hours;
//! \~english Minutes, 0-59
//! \~russian Минуты, 0-59
int minutes; int minutes;
//! \~english Seconds, 0-59
//! \~russian Секунды, 0-59
int seconds; int seconds;
//! \~english Milliseconds, 0-999
//! \~russian Миллисекунды, 0-999
int milliseconds; int milliseconds;
PIString toString(const PIString & format = "h:mm:ss") const;
PISystemTime toSystemTime() const;
static PITime current();
static PITime fromSystemTime(const PISystemTime & st);
}; };
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1); PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1); PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1); PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);} inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);} inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);} inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);}
//! \relatesalso PICout //! \relatesalso PICout
@@ -106,60 +57,20 @@ PIP_EXPORT PICout operator <<(PICout s, const PITime & v);
//! \ingroup Core struct PIP_EXPORT PIDate {
//! \~\brief
//! \~english Calendar date.
//! \~russian Календарная дата.
class PIP_EXPORT PIDate {
public:
//! \~english Construct %PIDate from year, month and day
//! \~russian Создает %PIDate из года, месяца и дня
PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;} PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;}
//! \~english Returns string representation
//! \~russian Возвращает строковое представление
PIString toString(const PIString & format = "d.MM.yyyy") const;
//! \~english Returns current date
//! \~russian Возвращает текущую дату
static PIDate current();
//! \~english Year
//! \~russian Год
int year; int year;
//! \~english Month, 1-12
//! \~russian Месяц, 1-12
int month; int month;
//! \~english Day, 1-31
//! \~russian День, 1-31
int day; int day;
PIString toString(const PIString & format = "d.MM.yyyy") const;
static PIDate current();
}; };
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1); PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1); PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1); PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);} inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);} inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);} inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);}
//! \relatesalso PICout //! \relatesalso PICout
@@ -170,155 +81,43 @@ PIP_EXPORT PICout operator <<(PICout s, const PIDate & v);
//! \ingroup Core struct PIP_EXPORT PIDateTime {
//! \~\brief
//! \~english Calendar date and time.
//! \~russian Календарное дата и время.
class PIP_EXPORT PIDateTime {
public:
//! \~english Construct null %PIDateTime
//! \~russian Создает нулевой %PIDateTime
PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;} PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;}
//! \~english Construct %PIDateTime from %PITime and null %PIDate
//! \~russian Создает %PIDateTime из %PITime и нулевого %PIDate
PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;} PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
//! \~english Construct %PIDateTime from %PIDate and null %PITime
//! \~russian Создает %PIDateTime из %PIDate и нулевого %PITime
PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;} PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;}
//! \~english Construct %PIDateTime from %PIDate and %PITime
//! \~russian Создает %PIDateTime из %PIDate и %PITime
PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;} PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
//! \~english Returns normalized %PIDateTime
//! \~russian Возвращает нормализованный %PIDateTime
PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());}
//! \~english Normalize all fields
//! \~russian Нормализует все поля
void normalize() {*this = normalized();}
//! \~english Returns string representation
//! \~russian Возвращает строковое представление
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const;
//! \~english Returns seconds since 1 Jan 1970
//! \~russian Возвращает секунды от 1 Янв 1970
time_t toSecondSinceEpoch() const;
//! \~english Returns time as %PISystemTime
//! \~russian Возвращает время как %PISystemTime
PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);}
//! \~english Returns date part
//! \~russian Возвращает дату
PIDate date() const {return PIDate(year, month, day);}
//! \~english Returns time part
//! \~russian Возвращает время
PITime time() const {return PITime(hours, minutes, seconds, milliseconds);}
//! \~english Set date part
//! \~russian Устанавливает дату
void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;}
//! \~english Set time part
//! \~russian Устанавливает время
void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;}
//! \~english Sum operator
//! \~russian Оператор сложения
void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();}
//! \~english Subtract operator
//! \~russian Оператор вычитания
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
//! \~english Construct %PIDateTime from seconds since 1 Jan 1970
//! \~russian Создает %PIDateTime из секунд от 1 Янв 1970
static PIDateTime fromSecondSinceEpoch(const time_t sec);
//! \~english Construct %PIDateTime from %PISystemTime
//! \~russian Создает %PIDateTime из %PISystemTime
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
//! \~english Returns current date and time
//! \~russian Возвращает текущую дату и время
static PIDateTime current();
//! \~english Year
//! \~russian Год
int year; int year;
//! \~english Month, 1-12
//! \~russian Месяц, 1-12
int month; int month;
//! \~english Day, 1-31
//! \~russian День, 1-31
int day; int day;
//! \~english Hour, 0-23
//! \~russian Час, 0-23
int hours; int hours;
//! \~english Minutes, 0-59
//! \~russian Минуты, 0-59
int minutes; int minutes;
//! \~english Seconds, 0-59
//! \~russian Секунды, 0-59
int seconds; int seconds;
//! \~english Milliseconds, 0-999
//! \~russian Миллисекунды, 0-999
int milliseconds; int milliseconds;
PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());}
void normalize() {*this = normalized();}
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const;
time_t toSecondSinceEpoch() const;
PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);}
PIDate date() const {return PIDate(year, month, day);}
PITime time() const {return PITime(hours, minutes, seconds, milliseconds);}
void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;}
void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;}
void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();}
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
static PIDateTime fromSecondSinceEpoch(const time_t sec);
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
static PIDateTime current();
}; };
//! \~english Sum operator
//! \~russian Оператор сложения
inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();} inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();}
//! \~english Subtract operator
//! \~russian Оператор вычитания
inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();} inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();}
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1); PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1); PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1); PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);} inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);} inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);} inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const PIDateTime & v) {s << v.year << v.month << v.day << v.hours << v.minutes << v.seconds << v.milliseconds; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIDateTime & v) {s << v.year << v.month << v.day << v.hours << v.minutes << v.seconds << v.milliseconds; return s;}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, PIDateTime & v) {s >> v.year >> v.month >> v.day >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIDateTime & v) {s >> v.year >> v.month >> v.day >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;}
//! \relatesalso PICout //! \relatesalso PICout

View File

@@ -64,16 +64,10 @@ void errorClear() {
PIString errorString() { PIString errorString() {
#ifdef WINDOWS #ifdef WINDOWS
char * msg = nullptr; char * msg;
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);
PIString ret = PIStringAscii("code ") + PIString::fromNumber(err) + PIStringAscii(" - "); return "code " + PIString::fromNumber(err) + " - " + PIString(msg);
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));
@@ -86,6 +80,11 @@ PIString PIPVersion() {
} }
void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) {
qsort(base, num, size, compar);
}
void randomize() { void randomize() {
srand(PISystemTime::current(true).nanoseconds); srand(PISystemTime::current(true).nanoseconds);
} }
@@ -94,3 +93,237 @@ 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

@@ -64,6 +64,8 @@ PIP_EXPORT PIString errorString();
//! Сброс последней ошибки //! Сброс последней ошибки
PIP_EXPORT void errorClear(); PIP_EXPORT void errorClear();
PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
PIP_EXPORT void randomize(); PIP_EXPORT void randomize();
PIP_EXPORT int randomi(); PIP_EXPORT int randomi();

View File

@@ -31,7 +31,6 @@
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
# include "esp_system.h" # include "esp_system.h"
#endif #endif
#include <codecvt>
#ifdef WINDOWS #ifdef WINDOWS
# include <winsock2.h> # include <winsock2.h>
extern FILETIME __pi_ftjan1970; extern FILETIME __pi_ftjan1970;
@@ -152,16 +151,12 @@ PIInit::PIInit() {
} }
# endif //WINDOWS # endif //WINDOWS
# ifdef HAS_LOCALE # ifdef HAS_LOCALE
//std::cout << "has locale" << std::endl; //cout << "has locale" << 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, "C"), 0); currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 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");
@@ -213,9 +208,8 @@ PIInit::PIInit() {
#endif #endif
char cbuff[1024]; char cbuff[1024];
memset(cbuff, 0, 1024); memset(cbuff, 0, 1024);
if (gethostname(cbuff, 1023) == 0) { if (gethostname(cbuff, 1023) == 0)
sinfo->hostname = cbuff; sinfo->hostname = cbuff;
}
#ifdef WINDOWS #ifdef WINDOWS
SYSTEM_INFO sysinfo; SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo); GetSystemInfo(&sysinfo);

View File

@@ -26,7 +26,13 @@
#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 События и Обработчики событий
@@ -92,88 +98,34 @@
//! 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
//! \~\details //! \~\brief
//! //! \~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 {
PIString ret; return types.join(",");
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 = PIStringAscii(type_ret) + " " + PIString ret = type_ret + " " + scope + "::" + func_name +"(";
PIStringAscii(scope) + "::" + for (int i = 0; i < types.size_s(); ++i) {
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 += PIStringAscii(types[i]) + " " + PIStringAscii(names[i]); ret += types[i] + " " + 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);
@@ -196,6 +148,15 @@ 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) {
@@ -235,13 +196,8 @@ 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());
const PIVector<const char *> & scope(__meta_data()[classNameID()].scope_list); return __meta_data()[classNameID()].scope_list;
for (const char * c: scope)
ret << PIStringAscii(c);
return ret;
} }
@@ -256,11 +212,10 @@ 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_id == search_id) if (eh.value().func_name == name)
return true; return true;
} }
return false; return false;
@@ -268,11 +223,10 @@ 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_id == search_id) if (eh.value().func_name == name)
return eh.value().arguments(); return eh.value().arguments();
} }
return PIString(); return PIString();
@@ -280,11 +234,10 @@ 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_id == search_id) if (eh.value().func_name == name)
return eh.value().fullFormat(); return eh.value().fullFormat();
} }
return PIString(); return PIString();
@@ -297,11 +250,10 @@ 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_id == search_id) if (eh.value().func_name == name)
ret << eh.value(); ret << eh.value();
} }
return ret; return ret;
@@ -361,9 +313,10 @@ 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.canConnectTo(fd, args)) { if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) {
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();
} }
} }
} }
@@ -575,7 +528,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.argumentsCount(); int j = m.names.size_s();
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;
@@ -617,46 +570,30 @@ void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector<PIVar
} }
PIString PIObject::simplifyType(const char * a, bool readable) { PIString PIObject::simplifyType(const char * a) {
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'; //piCout << i << iw << white;
//piCout << i << iw << white; if (white < 0) {
if (white < 0) { if (iw) {
if (iw) { white = i;
white = i; continue;
continue; }
} } else {
} else { if (!iw) {
if (!iw) { ret.replace(white, i - white, " ");
ret.replace(white, i - white, " "); i = white;
i = white; white = -1;
white = -1; //piCout << i;
//piCout << i;
}
} }
} }
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("&"))
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');
} }
ret.replaceAll(" &", "&");
ret.replaceAll(" *", "*");
if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim();
return ret; return ret;
} }
@@ -674,12 +611,9 @@ 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());
const char * o_name = "name"; piForeachC (PropertyHash p, properties_)
auto it = properties_.makeIterator(); if (p.first != PIString("name").hash())
while (it.next()) { PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << p.second.first << ": " << p.second.second;
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 {";
@@ -694,18 +628,17 @@ 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());
for (const Connection & c : connections) { piForeachC (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) if (!ef.func_name.isEmpty())
src = PIStringAscii(ef.func_name) + "(" + ef.arguments() + ")"; src = ef.func_name + "(" + ef.arguments() + ")";
if (dst) { if (dst) {
__MetaFunc hf = dst->methodEH(c.slot); __MetaFunc hf = dst->methodEH(c.slot);
PIString hf_fn; if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]";
if (!hf.func_name) hf_fn = "[BROKEN]"; else hf.func_name += "(" + hf.arguments() + ")";
else hf_fn = PIStringAscii(hf.func_name) + "(" + hf.arguments() + ")"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name;
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]";
} }
@@ -717,7 +650,7 @@ void PIObject::dump(const PIString & line_prefix) const {
#ifndef MICRO_PIP #ifndef MICRO_PIP
void dumpApplication(bool with_objects) { void dumpApplication() {
PIMutexLocker _ml(PIObject::mutexObjects()); PIMutexLocker _ml(PIObject::mutexObjects());
//printf("dump application ...\n"); //printf("dump application ...\n");
PIDateTime cd = PIDateTime::current(); PIDateTime cd = PIDateTime::current();
@@ -735,24 +668,22 @@ void dumpApplication(bool with_objects) {
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();
if (with_objects) { piForeachC (PIObject * o, PIObject::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 with_objects) { bool dumpApplicationToFile(const PIString & path) {
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(with_objects); dumpApplication();
f << PICout::buffer(); f << PICout::buffer();
f.close(); f.close();
PICout::setBufferActive(ba, true); PICout::setBufferActive(ba, true);
@@ -762,7 +693,7 @@ bool dumpApplicationToFile(const PIString & path, bool with_objects) {
#endif #endif
void PIObject::__MetaData::addScope(const char * s, uint shash) { void PIObject::__MetaData::addScope(const PIString & 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,16 +34,13 @@
#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(bool); friend void dumpApplication();
friend class PIIntrospection; friend class PIIntrospection;
#endif #endif
typedef PIObject __PIObject__; typedef PIObject __PIObject__;
@@ -57,10 +54,6 @@ 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(),
@@ -106,7 +99,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
@@ -121,7 +114,7 @@ public:
//! \~english Returns object name //! \~english Returns object name
//! \~russian Возвращает имя объекта //! \~russian Возвращает имя объекта
PIString name() const {return property("name").toString();} PIString name() const {return property(PIStringAscii("name")).toString();}
//! \~english Returns object class name //! \~english Returns object class name
//! \~russian Возвращает имя класса объекта //! \~russian Возвращает имя класса объекта
@@ -129,7 +122,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 char * __classNameCC() {return "PIObject";} static const PIString __classNameS() {return PIStringAscii("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
@@ -137,30 +130,42 @@ public:
virtual const char * parentClassName() const {return "";} virtual const char * parentClassName() const {return "";}
//! \~english Return if \a piCoutObj of this object is active //! \~english Return if debug of this object is active
//! \~russian Возвращает включен ли вывод \a piCoutObj для этого объекта //! \~russian Возвращает включен ли вывод на консоль для этого объекта
bool debug() const {return property("debug").toBool();} bool debug() const {return property(PIStringAscii("debug")).toBool();}
//! \~english Set object name //! \~english Set object name
//! \~russian Устанавливает имя объекта //! \~russian Устанавливает имя объекта
void setName(const PIString & name) {setProperty("name", name);} void setName(const PIString & name) {setProperty(PIStringAscii("name"), name);}
void setName(const char * name) {setName(PIStringAscii(name));}
//! \~english Set object \a piCoutObj active
//! \~russian Включает или отключает вывод \a piCoutObj для этого объекта //! \~english Set object debug active
void setDebug(bool debug) {setProperty("debug", debug);} //! \~russian Включает или отключает вывод на консоль для этого объекта
void setDebug(bool debug) {setProperty(PIStringAscii("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 char * name) const {return properties_.value(piHashData((const uchar *)name, strlen(name)));} PIVariant property(const PIString & name) const {return properties_.value(name.hash(), Property(PIString(), PIVariant())).second;}
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 char * name, const PIVariant & value) {properties_[piHashData((const uchar *)name, strlen(name))] = value; propertyChanged(name);} void setProperty(const PIString & name, const PIVariant & value) {properties_[name.hash()] = Property(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 char * name) const {return properties_.contains(piHashData((const uchar *)name, strlen(name)));} bool isPropertyExists(const PIString & name) const {return properties_.contains(name.hash());}
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_;}
@@ -432,8 +437,7 @@ public:
template<typename T> template<typename T>
bool isTypeOf() const { bool isTypeOf() const {
if (!isPIObject()) return false; if (!isPIObject()) return false;
PIMutexLocker ml(__meta_mutex()); return scopeList().contains(T::__classNameS());
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"
@@ -455,32 +459,26 @@ 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, bool readable = true); static PIString simplifyType(const char * a);
struct PIP_EXPORT __MetaFunc { struct PIP_EXPORT __MetaFunc {
__MetaFunc(); __MetaFunc(): addr(0), addrV(0) {;}
bool isNull() const {return addr == nullptr;} bool isNull() const {return addr == 0;}
int argumentsCount() const;
PIString arguments() const; PIString arguments() const;
PIString fullFormat() const; PIString fullFormat() const;
void __setFuncName(const char * n); void * addr;
void __addArgument(const char * t, const char * n); void * addrV;
bool canConnectTo(const __MetaFunc & dst, int & args_count) const; PIString func_name;
void * addr = nullptr; PIString type_ret;
void * addrV = nullptr; PIString scope;
uint func_name_id = 0; PIStringList types;
const char * func_name = nullptr; PIStringList names;
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 << "PIObject"; scope_id << PIStringAscii("PIObject").hash();} __MetaData() {scope_list << PIStringAscii("PIObject"); scope_id << PIStringAscii("PIObject").hash();}
void addScope(const char * s, uint shash); void addScope(const PIString & s, uint shash);
PIVector<const char *> scope_list; PIStringList 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;
@@ -516,7 +514,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 char * name) {} virtual void propertyChanged(const PIString & name) {}
EVENT1(deleted, PIObject *, o) EVENT1(deleted, PIObject *, o)
@@ -565,6 +563,9 @@ 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;
@@ -584,7 +585,7 @@ private:
PIVector<Connection> connections; PIVector<Connection> connections;
PIMap<uint, PIVariant> properties_; PIMap<uint, PIPair<PIString, 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;
@@ -595,8 +596,8 @@ private:
}; };
#ifndef MICRO_PIP #ifndef MICRO_PIP
PIP_EXPORT void dumpApplication(bool with_objects = true); PIP_EXPORT void dumpApplication();
PIP_EXPORT bool dumpApplicationToFile(const PIString & path, bool with_objects = true); PIP_EXPORT bool dumpApplicationToFile(const PIString & path);
#endif #endif
#endif // PIOBJECT_H #endif // PIOBJECT_H

View File

@@ -385,14 +385,13 @@
# 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 char * __classNameCC() {return #name;} \ static const PIString __classNameS() {static PIString ret = PIStringAscii(#name); return ret;} \
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;} \
@@ -412,7 +411,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(__classNameCC(), id); \ eh.addScope(__classNameS(), id); \
} \ } \
}; \ }; \
__BaseInitializer__ __base_init__; __BaseInitializer__ __base_init__;
@@ -432,7 +431,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(__classNameCC(), id); \ eh.addScope(__classNameS(), id); \
} \ } \
}; \ }; \
__ParentInitializer__ __parent_init__; \ __ParentInitializer__ __parent_init__; \
@@ -444,61 +443,92 @@
#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent) #define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)
#define __EH_INIT_BASE__(ret, name) \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameCC(); \
f.__setFuncName(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = #ret;
#define EH_INIT0(ret, name) \ #define EH_INIT0(ret, name) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
void * fpV = fp; \ void * fpV = fp; \
__EH_INIT_BASE__(ret, name) \ if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__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); \
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##__; \
__EH_INIT_BASE__(ret, name) \ if (eh.eh_set[fp]) return; \
f.__addArgument(#a0, #n0); \ eh.eh_set << fp; \
__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##__; \
__EH_INIT_BASE__(ret, name) \ if (eh.eh_set[fp]) return; \
f.__addArgument(#a0, #n0); \ eh.eh_set << fp; \
f.__addArgument(#a1, #n1); \ __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) << 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##__; \
__EH_INIT_BASE__(ret, name) \ if (eh.eh_set[fp]) return; \
f.__addArgument(#a0, #n0); \ eh.eh_set << fp; \
f.__addArgument(#a1, #n1); \ __MetaFunc & f(eh.eh_func[fp]); \
f.__addArgument(#a2, #n2); \ 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) << 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##__; \
__EH_INIT_BASE__(ret, name) \ if (eh.eh_set[fp]) return; \
f.__addArgument(#a0, #n0); \ eh.eh_set << fp; \
f.__addArgument(#a1, #n1); \ __MetaFunc & f(eh.eh_func[fp]); \
f.__addArgument(#a2, #n2); \ f.scope = __classNameS(); \
f.__addArgument(#a3, #n3); \ 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) << PIObject::simplifyType(#a3); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2) << PIStringAscii(#n3); \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END

View File

@@ -20,7 +20,13 @@
#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 Краткий обзор
@@ -39,12 +45,35 @@
//! \~russian Пример: //! \~russian Пример:
//! \~\code{.cpp} //! \~\code{.cpp}
//! \endcode //! \endcode
//! //! \}
//! \addtogroup Core
//! \{
//! \~\class PIPropertyStorage::Property pipropertystorage.h //! \~\class PIPropertyStorage::Property pipropertystorage.h
//! \~\details //! \~\brief
//! \~english PIPropertyStorage element
//! \~russian Элемент PIPropertyStorage
//! //!
//! \~\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,10 +29,6 @@
#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:
@@ -40,10 +36,6 @@ 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"
@@ -265,6 +257,8 @@ 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,39 +27,99 @@
#ifdef WINDOWS #ifdef WINDOWS
# include <stringapiset.h> # include <stringapiset.h>
#endif #endif
#include <string> #include <wchar.h>
#include <locale> #ifdef ANDROID
#include <codecvt> # if __ANDROID_API__ < 21
# define wctomb(s, wc) wcrtomb(s, wc, NULL)
# define mbtowc(pwc, s, n) mbrtowc(pwc, s, n, NULL)
# endif
#endif
//! \class PIString pistring.h /*! \class PIString
//! \~\details * \brief String class
//! \~english \section PIString_sec0 Synopsis * \details PIP use this class for use string information.
//! \~russian \section PIString_sec0 Краткий обзор *
//! * \section PIString_sec0 Synopsis
//! \~english * This class based on \a PIVector to store information.
//! String is a sequence of \a PIChar. Real memory size of string is symbols count * 2. * String is a sequence of \a PIChar and can contain multibyte
//! String can be constucted from many types of data and can be converted * symbols. Therefore real memory size of string is symbols count * 4.
//! to many types. There are many operators and handly functions to use * String can be constucted from many types of data and can be converted
//! string as you wish. * to many types. There are man operators and handly functions to use
//! * string as you wish.
//! \~russian *
//! Строка состоит из последовательности \a PIChar. Реальный объем памяти, * \section PIString_sec1 To/from data convertions
//! занимаемый строкой, равен количеству символов * 2. Строка может быть * Most common constructor is \a PIString(const char * str), where "str"
//! создана из множества типов и преобразована в несколько типов. * is null-terminated string, e.g. \c "string". This is 7 chars with last char = 0.
//! Имеет множество методов для манипуляций. * Also you can constructs \a PIString from single \a PIChar, \a PIByteArray,
//! * other \a PIString or sequency of the same characters with custom length.\n \n
* This class has implicit conversions to <tt>const char * </tt> and
* \c std::string. Also there are functions to make same convertions:
* * \a data() - to <tt>const char * </tt>,
* * \a stdString() - to \c std::string,
* * \a toByteArray() - to \a PIByteArray.
*
* \section PIString_sec2 Numeric operations
* You can get symbolic representation of any numeric value with function
* \a setNumber(any integer value, int base = 10, bool * ok = 0). Default
* arguments are set for decimal base system, but you can choose any system
* from 2 to 40. There are the same static functions \a fromNumber(), that
* returns \a PIString. \n
* Also there is function \a setReadableSize() which is set human-readable
* size in bytes, Kb, Mb, Gb or Pb. Static analog is \a readableSize().
*
*/
/*! \fn int versionCompare(const PIString & v0, const PIString & v1, int components = 6)
* \relatesalso PIString
* \brief Compare two version strings in free notation and returns 0, -1 or 1
* \details This function parse version to number codes and labels. Then it
* compare no more than "components" codes. If there is no difference, compare
* labels. Each label has corresponding integer value, so
* "prealpha" < "alpha" < "prebeta" < "beta" < "rcN" < "" < "rN".
* Example:
* \code
* piCout << versionCompare("1.0.0_rc2-999", "1.0.1_rc2-999"); // -1
* piCout << versionCompare("1.0.0", "0.9.2"); // 1
* piCout << versionCompare("1.0.0_r1", "1.0.0"); // 1
* piCout << versionCompare("1.0.0_r1", "1.0.0", 3); // 0
* piCout << versionCompare("1.0.0_r1", "1.0.0", 3); // 0
* piCout << versionCompare(".2-alpha", "0.2_alpha"); // 0
* piCout << versionCompare("1_prebeta", "1.0_alpha"); // 1
* \endcode
* \return
* * 0 - equal
* * 1 - v0 > v1
* * -1 - v0 < v1
*
*
* \fn PIString versionNormalize(const PIString & v)
* \relatesalso PIString
* \brief Converts version string in free notation to classic view
* \details Parse version as described in \a versionCompare() and
* returns classic view of codes and labels: major.minor.revision[-build][_label].
* Example:
* \code
* piCout << versionNormalize(""); // 0.0.0
* piCout << versionNormalize("1"); // 1.0.0
* piCout << versionNormalize("1.2"); // 1.2.0
* piCout << versionNormalize("1.2.3"); // 1.2.3
* piCout << versionNormalize("1.2+rc1.99"); // 1.2.99_rc1
* piCout << versionNormalize("1.2-alpha"); // 1.2.0_alpha
* piCout << versionNormalize("1..4_rc2-999"); // 1.0.4-999_rc2
* \endcode
*
*/
const char PIString::toBaseN[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'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 char PIString::fromBaseN[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, const int 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,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
@@ -78,7 +138,11 @@ const float PIString::ElideCenter = .5f;
const float PIString::ElideRight = 1.f; const float PIString::ElideRight = 1.f;
#define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); snprintf(ch, 256, f, v); return PIStringAscii(ch); #ifndef CC_VC
# 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);}
@@ -86,10 +150,16 @@ 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 = snprintf(&(f[2]), 4, "%d", precision); int wr = sprintf(&(f[2]), "%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);
@@ -100,7 +170,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();
} }
@@ -122,7 +192,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();
} }
@@ -153,7 +223,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;
} }
@@ -161,7 +231,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;
char cs; int 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;
@@ -184,87 +254,116 @@ 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) {
// piCout << "appendFromChars"; if (s <= 0) return;
if (s == 0) return; int sz;
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) {
d.enlarge(s); UChar * ucs = new UChar[s];
memset(ucs, 0, s * sizeof(UChar));
e = (UErrorCode)0; e = (UErrorCode)0;
int sz = ucnv_toUChars(cc, (UChar*)(d.data(old_sz)), s, c, s, &e); sz = ucnv_toUChars(cc, ucs, s, c, s, &e);
d.resize(old_sz+sz); //printf("appendFromChars %d -> %d\n", s, 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
int sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0); sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0);
if (sz <= 0) return; if (sz <= 0) return;
d.enlarge(sz); int old_sz = size_s();
MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, (LPWSTR)d.data(old_sz), sz); enlarge(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
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> ucs2conv; wchar_t wc;
std::u16string ucs2 = ucs2conv.from_bytes(c, c+s); mbtowc(0,0,0); // reset mbtowc
d.enlarge(ucs2.size()); //qDebug() << "FromChars ...";
ucs2.copy((char16_t *)d.data(old_sz), ucs2.size()); while (s>0) {
//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 (!s) return ret; if (l > 0) ret.appendFromChars(s, l, __sysoemname__);
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 (!s) return ret; if (l > 0) ret.appendFromChars(s, l, __syslocname__);
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 (!s) return ret; if (l > 0) ret.appendFromChars(s, l, __utf8name__);
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.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __utf8name__); if (ba.isEmpty()) return ret;
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) {
return fromAscii(s, strlen(s)); PIString ret;
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.resize(len); ret.reserve(len);
for (int l = 0; l < len; ++l) { for (int l = 0; l < len; ++l) {
ret[l] = s[l]; ret.push_back(PIChar(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 (s[0] > '\0') ret.appendFromChars(s, -1 if (l > 0) ret.appendFromChars(s, l
#ifdef PIP_ICU #ifdef PIP_ICU
, c , c
#else #else
@@ -277,19 +376,6 @@ PIString PIString::fromCodepage(const char * s, const char * c) {
} }
//! \~\details
//! \~english
//! Example:
//! \~russian
//! Пример:
//! \~\code
//! piCout << PIString::readableSize(512); // 512 B
//! piCout << PIString::readableSize(5120); // 5.0 kB
//! piCout << PIString::readableSize(512000); // 500.0 kB
//! piCout << PIString::readableSize(5120000); // 4.8 MB
//! piCout << PIString::readableSize(512000000); // 488.2 MB
//! piCout << PIString::readableSize(51200000000); // 47.6 GB
//! \endcode
PIString PIString::readableSize(llong bytes) { PIString PIString::readableSize(llong bytes) {
PIString s; PIString s;
s.setReadableSize(bytes); s.setReadableSize(bytes);
@@ -298,56 +384,72 @@ PIString PIString::readableSize(llong bytes) {
void PIString::buildData(const char * cp) const { void PIString::buildData(const char * cp) const {
deleteData(); data_.clear();
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) {
const size_t len = MB_CUR_MAX*size()+1; char uc[8];
data_ = (char *)malloc(len); data_.reserve(size_s());
int sz = ucnv_fromUChars(cc, data_, len, (const UChar*)(d.data()), d.size_s(), &e); for (int i = 0; i < size_s(); ++i) {
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_[sz] = '\0'; data_.push_back('\0');
return; return;
} }
#else #else
# ifdef WINDOWS # ifdef WINDOWS
int sz = WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)d.data(), d.size_s(), 0, 0, NULL, NULL); sz = WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque<PIChar>::data(), PIDeque<PIChar>::size_s(), 0, 0, NULL, NULL);
//printf("WideCharToMultiByte %d %d\n", (uint)(uintptr_t)cp, sz);
if (sz <= 0) { if (sz <= 0) {
data_ = (char *)malloc(1); //printf("WideCharToMultiByte erro %d\n", GetLastError());
data_[0] = '\0'; data_.push_back(uchar('\0'));
return; return;
} }
data_ = (char *)malloc(sz+1); data_.resize(sz);
WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)d.data(), d.size_s(), (LPSTR)data_, sz, NULL, NULL); WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque<PIChar>::data(), PIDeque<PIChar>::size_s(), (LPSTR)data_.data(), data_.size_s(), NULL, NULL);
data_[sz] = '\0'; data_.push_back(uchar('\0'));
return; return;
# else # else
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> ucs2conv; wchar_t wc;
std::string u8str = ucs2conv.to_bytes((char16_t*)d.data(), (char16_t*)d.data() + d.size()); char tc[8];
data_ = (char *)malloc(u8str.size()+1); wctomb(0, 0);
strcpy(data_, u8str.c_str()); for (int i = 0; i < size_s(); ++i) {
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 < d.size_s(); ++i) { for (int i = 0; i < length(); ++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 = d.size_s() - 1; i >= 0; --i) { for (int i = length() - 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;
@@ -356,20 +458,42 @@ void PIString::trimsubstr(int &st, int &fn) const {
} }
const char * PIString::dataConsole() const {
buildData(__sysoemname__ );
return (const char *)(data_.data());
}
const char * PIString::dataUTF8() const {
buildData(__utf8name__);
return (const char *)(data_.data());
}
const char * PIString::dataAscii() const {
data_.clear();
for (int i = 0; i < size_s(); ++i) {
data_.push_back(uchar(at(i).ch));
}
data_.push_back(uchar('\0'));
return (const char *)data_.data();
}
uint PIString::hash() const { uint PIString::hash() const {
return piHashData((const uchar*)d.data(), d.size() * sizeof(PIChar)); return piHashData((const uchar*)PIDeque<PIChar>::data(), size() * sizeof(PIChar));
} }
PIByteArray PIString::toUTF8() const { PIByteArray PIString::toUTF8() const {
if (isEmpty()) return PIByteArray(); if (isEmpty()) return data_.resized(0);
buildData(__utf8name__); buildData(__utf8name__);
return PIByteArray(data_, strlen(data_)); return data_.resized(data_.size_s() - 1);
} }
PIByteArray PIString::toCharset(const char * c) const { PIByteArray PIString::toCharset(const char * c) const {
if (isEmpty()) return PIByteArray(); if (isEmpty()) return data_.resized(0);
buildData( buildData(
#ifdef PIP_ICU #ifdef PIP_ICU
c c
@@ -379,67 +503,63 @@ PIByteArray PIString::toCharset(const char * c) const {
# endif # endif
#endif #endif
); );
return PIByteArray(data_, strlen(data_)); return data_.resized(data_.size_s() - 1);
} }
PIString & PIString::operator +=(const char * str) { PIString & PIString::operator +=(const char * str) {
if (!str) return *this; if (!str) return *this;
appendFromChars(str, -1, __syslocname__); int l = 0;
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]) {
d.push_back(PIChar(str[i])); push_back(PIChar(str[i]));
} }
return *this; return *this;
} }
PIString & PIString::operator +=(const PIString & str) { PIString & PIString::operator +=(const PIString & str) {
d.append(str.d); *((PIDeque<PIChar>*)this) << *((PIDeque<PIChar>*)&str);
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 {
return d == str.d; uint l = str.size();
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 {
return d != str.d; uint l = str.size();
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 {
size_t l = str.size(); uint l = str.size();
if (size() < l) return true; if (size() < l) return true;
if (size() > l) return false; if (size() > l) return false;
for (size_t i = 0; i < l; ++i) { for (uint i = 0; i < l; ++i) {
if (at(i) == str.at(i)) continue; if (at(i) == str[i]) continue;
if (at(i) < str.at(i)) return true; if (at(i) < str[i]) return true;
else return false; else return false;
} }
return false; return false;
@@ -447,33 +567,18 @@ bool PIString::operator <(const PIString & str) const {
bool PIString::operator >(const PIString & str) const { bool PIString::operator >(const PIString & str) const {
size_t l = str.size(); uint l = str.size();
if (size() < l) return false; if (size() < l) return false;
if (size() > l) return true; if (size() > l) return true;
for (size_t i = 0; i < l; ++i) { for (uint i = 0; i < l; ++i) {
if (at(i) == str.at(i)) continue; if (at(i) == str[i]) continue;
if (at(i) < str.at(i)) return false; if (at(i) < str[i]) return false;
else return true; else return true;
} }
return false; return false;
} }
//! \~\details
//! \~english
//! If "len" < 0 then returns substring from symbol "start" to end.
//! \~russian
//! Если "len" < 0 тогда возвращается подстрока от символа "start" и до конца.
//! \~\code
//! PIString s("0123456789");
//! piCout << s.mid(-2, -1); // s = "0123456789"
//! piCout << s.mid(-2, 4); // s = "01"
//! piCout << s.mid(3, -1); // s = "3456789"
//! piCout << s.mid(3, 4); // s = "3456"
//! piCout << s.mid(7, 1); // s = "7"
//! piCout << s.mid(7, 4); // s = "789"
//! \endcode
//! \~\sa \a left(), \a right()
PIString PIString::mid(const int start, const int len) const { PIString PIString::mid(const int start, const int len) const {
//PIString str; //PIString str;
int s = start, l = len; int s = start, l = len;
@@ -483,26 +588,15 @@ PIString PIString::mid(const int start, const int len) const {
s = 0; s = 0;
} }
if (l < 0) { if (l < 0) {
return PIString(d.data(s), size_s() - s); return PIString(&(at(s)), size_s() - s);
} else { } else {
if (l > length() - s) l = length() - s; if (l > length() - s) l = length() - s;
return PIString(d.data(s), l); return PIString(&(at(s)), l);
} }
return PIString(); return PIString();
} }
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! s.cutMid(1, 3);
//! piCout << s; // s = "0456789"
//! s.cutMid(-1, 3);
//! piCout << s; // s = "56789"
//! s.cutMid(3, -1);
//! piCout << s; // s = "567"
//! \endcode
//! \~\sa \a cutLeft(), \a cutRight()
PIString & PIString::cutMid(const int start, const int len) { PIString & PIString::cutMid(const int start, const int len) {
int s = start, l = len; int s = start, l = len;
if (l == 0) return *this; if (l == 0) return *this;
@@ -511,25 +605,15 @@ PIString & PIString::cutMid(const int start, const int len) {
s = 0; s = 0;
} }
if (l < 0) { if (l < 0) {
d.remove(s, size() - s); remove(s, size() - s);
} else { } else {
if (l > length() - s) l = length() - s; if (l > length() - s) l = length() - s;
d.remove(s, l); remove(s, l);
} }
return *this; return *this;
} }
//! \~\details
//! \~english Remove spaces, tabulations, line feeds and null symbols:
//! \~russian Удаляет пробелы, табуляцию, переводы строк и нулевые символы:
//! \~ ' ', '\\n', '\\r', '\\t', '\\0'
//! \~\code
//! PIString s(" \t string \n");
//! s.trim();
//! piCout << s; // s = "string"
//! \endcode
//! \~\sa \a trimmed()
PIString & PIString::trim() { PIString & PIString::trim() {
int st = -1, fn = 0; int st = -1, fn = 0;
trimsubstr(st, fn); trimsubstr(st, fn);
@@ -551,39 +635,18 @@ PIString PIString::trimmed() const {
} }
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! s.replace(2, 3, "_cut_");
//! piCout << s; // s = "01_cut_56789"
//! s.replace(0, 1, "one_");
//! piCout << s; // s = "one_1_cut_56789"
//! \endcode
//! \~\sa \a replaced(), \a replaceAll()
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(d.data(from), with.d.data(), count * sizeof(PIChar)); memcpy(PIDeque<PIChar>::data(from), static_cast<PIDeque<PIChar>>(with).data(), count * sizeof(PIChar));
} else { } else {
d.remove(from, count); remove(from, count);
d.insert(from, with.d); PIDeque<PIChar>::insert(from, with);
} }
return *this; return *this;
} }
//! \~\details
//! \~english If "ok" is not null, it set to "true" if something was replaced
//! \~russian Если "ok" не null, то устанавливает в "true" если замена произведена
//! \~\code
//! PIString s("pip string");
//! bool ok;
//! s.replace("string", "conf", &ok);
//! piCout << s << ok; // s = "pip conf", true
//! s.replace("PIP", "PlInPr", &ok);
//! piCout << s << ok; // s = "pip conf", false
//! \endcode
//! \~\sa \a replaced(), \a replaceAll()
PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) { PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) {
if (what.isEmpty()) { if (what.isEmpty()) {
if (ok != 0) *ok = false; if (ok != 0) *ok = false;
@@ -596,13 +659,6 @@ PIString & PIString::replace(const PIString & what, const PIString & with, bool
} }
//! \~\details
//! \~\code
//! PIString s("substrings");
//! s.replaceAll("s", "_");
//! piCout << s; // s = "_ub_tring_"
//! \endcode
//! \~\sa \a replace(), \a replaced(), \a replacedAll()
PIString & PIString::replaceAll(const PIString & what, const PIString & with) { PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
if (what.isEmpty() || what == with) return *this; if (what.isEmpty() || what == with) return *this;
if (with.isEmpty()) { if (with.isEmpty()) {
@@ -618,22 +674,15 @@ PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
} }
} }
if (!match) continue; if (!match) continue;
if (dl > 0) d.insert(i, PIDeque<PIChar>((size_t)dl)); if (dl > 0) PIDeque<PIChar>::insert(i, PIDeque<PIChar>((size_t)dl));
if (dl < 0) d.remove(i, -dl); if (dl < 0) PIDeque<PIChar>::remove(i, -dl);
memcpy(d.data(i), with.d.data(), with.size() * sizeof(PIChar)); memcpy(PIDeque<PIChar>::data(i), &(with.at(0)), with.length() * sizeof(PIChar));
} }
} }
return *this; return *this;
} }
//! \~\details
//! \~\code
//! PIString s("substrings");
//! s.replaceAll("s", '_');
//! piCout << s; // s = "_ub_tring_"
//! \endcode
//! \~\sa \a replace(), \a replaced(), \a replacedAll()
PIString & PIString::replaceAll(const PIString & what, const char with) { PIString & PIString::replaceAll(const PIString & what, const char with) {
if (what.isEmpty()) return *this; if (what.isEmpty()) return *this;
int l = what.length(), dl = what.length() - 1; int l = what.length(), dl = what.length() - 1;
@@ -646,24 +695,17 @@ PIString & PIString::replaceAll(const PIString & what, const char with) {
} }
} }
if (!match) continue; if (!match) continue;
if (dl > 0) d.remove(i, dl); if (dl > 0) PIDeque<PIChar>::remove(i, dl);
d[i] = PIChar(with); (*this)[i] = PIChar(with);
} }
return *this; return *this;
} }
//! \~\details
//! \~\code
//! PIString s("substrings");
//! s.replaceAll('s', '_');
//! piCout << s; // s = "_ub_tring_"
//! \endcode
//! \~\sa \a replace(), \a replaced(), \a replacedAll()
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) d[i] = with; if (at(i) == what) (*this)[i] = with;
} }
return *this; return *this;
} }
@@ -675,13 +717,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 (d.at(j + i) != str.at(j)) { if (at(j + i) != str[j]) {
match = false; match = false;
break; break;
} }
} }
if (!match) continue; if (!match) continue;
d.remove(i, l); PIDeque<PIChar>::remove(i, l);
i -= l; i -= l;
} }
return *this; return *this;
@@ -689,7 +731,7 @@ PIString & PIString::removeAll(const PIString & str) {
PIString & PIString::insert(int index, const PIString & str) { PIString & PIString::insert(int index, const PIString & str) {
d.insert(index, str.d); PIDeque<PIChar>::insert(index, *((const PIDeque<PIChar>*)&str));
return *this; return *this;
} }
@@ -704,8 +746,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);
d.remove(ls, length() - ns); remove(ls, length() - ns);
d.insert(ls, s_dotdot.d); insert(ls, s_dotdot);
return *this; return *this;
} }
@@ -725,15 +767,6 @@ PIStringList PIString::split(const PIString & delim) const {
} }
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.find('-'); // -1
//! piCout << s.find('3'); // 3
//! piCout << s.find('3', 4); // 9
//! piCout << s.find('3', 10); // -1
//! \endcode
//! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::find(const char c, const int start) const { int PIString::find(const char c, const int start) const {
for (int i = start; i < length(); ++i) { for (int i = start; i < length(); ++i) {
if (at(i) == c) return i; if (at(i) == c) return i;
@@ -742,15 +775,6 @@ int PIString::find(const char c, const int start) const {
} }
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.find("-"); // -1
//! piCout << s.find("34"); // 3
//! piCout << s.find("3", 4); // 9
//! piCout << s.find("3", 10); // -1
//! \endcode
//! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::find(const PIString & str, const int start) const { int PIString::find(const PIString & str, const int start) const {
int l = str.length(); int l = str.length();
for (int i = start; i < length() - l + 1; ++i) { for (int i = start; i < length() - l + 1; ++i) {
@@ -760,30 +784,6 @@ int PIString::find(const PIString & str, const int start) const {
} }
//! \~\details
//! \~\code
//! piCout << PIString("1.str").findAny(".,:"); // 1
//! piCout << PIString("1,str").findAny(".,:"); // 1
//! piCout << PIString("1:str").findAny(".,:"); // 1
//! \endcode
//! \~\sa \a find(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::findAny(const PIString & str, const int start) const {
for (int i = start; i < length(); ++i) {
if (str.contains(at(i))) return i;
}
return -1;
}
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.findLast('-'); // -1
//! piCout << s.findLast('3'); // 9
//! piCout << s.findLast('3', 4); // 9
//! piCout << s.findLast('3', 10); // -1
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::findLast(const char c, const int start) const { int PIString::findLast(const char c, const int start) const {
for (int i = length() - 1; i >= start; --i) { for (int i = length() - 1; i >= start; --i) {
if (at(i) == c) return i; if (at(i) == c) return i;
@@ -791,24 +791,7 @@ 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
//! \~\code
//! PIString s("012345012345");
//! piCout << s.findLast("-"); // -1
//! piCout << s.findLast("34"); // 9
//! piCout << s.findLast("3", 4); // 9
//! piCout << s.findLast("3", 10); // -1
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::findLast(const PIString & str, const int start) const { int PIString::findLast(const PIString & str, const int start) const {
int l = str.length(); int l = str.length();
for (int i = length() - l; i >= start; --i) { for (int i = length() - l; i >= start; --i) {
@@ -818,44 +801,20 @@ int PIString::findLast(const PIString & str, const int start) const {
} }
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str,0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str:0").findAnyLast(".,:"); // 4
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::findAnyLast(const PIString & str, const int start) const {
for (int i = length() - 1; i >= start; --i) {
if (str.contains(at(i))) return i;
}
return -1;
}
//! \~\details
//! \~\code
//! PIString s("this is <PIP>");
//! piCout << s.findWord("this"); // 0
//! piCout << s.findWord("is"); // 5
//! piCout << s.findWord("PIP", 4); // -1
//! piCout << s.findWord("<PIP>", 4); // 8
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findAnyLast(), \a findCWord(), \a findRange()
int PIString::findWord(const PIString & word, const int start) const { int PIString::findWord(const PIString & word, const int start) const {
int f = start - 1, tl = length(), wl = word.length(); int f = start - 1, tl = length(), wl = word.length();
while ((f = find(word, f + 1)) >= 0) { while ((f = find(word, f + 1)) >= 0) {
bool ok = true; bool ok = true;
PIChar c; PIChar c;
if (f > 0) { if (f > 0) {
c = at(f - 1); c = (*this)[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 = at(f + wl); c = (*this)[f + wl];
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) { if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
ok = false; ok = false;
continue; continue;
@@ -867,29 +826,20 @@ int PIString::findWord(const PIString & word, const int start) const {
} }
//! \~\details
//! \~\code
//! PIString s("this::is <PIP>");
//! piCout << s.findCWord("this"); // 0
//! piCout << s.findCWord("is"); // 6
//! piCout << s.findCWord("PIP", 4); // 10
//! piCout << s.findCWord("<PIP>", 4); // 9
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findRange()
int PIString::findCWord(const PIString & word, const int start) const { int PIString::findCWord(const PIString & word, const int start) const {
int f = start - 1, tl = length(), wl = word.length(); int f = start - 1, tl = length(), wl = word.length();
while ((f = find(word, f + 1)) >= 0) { while ((f = find(word, f + 1)) >= 0) {
bool ok = true; bool ok = true;
PIChar c; PIChar c;
if (f > 0) { if (f > 0) {
c = at(f - 1); c = (*this)[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 = at(f + wl); c = (*this)[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;
@@ -901,15 +851,6 @@ int PIString::findCWord(const PIString & word, const int start) const {
} }
//! \~\details
//! \~\code
//! PIString s(" {figures{inside}}");
//! int len = -1;
//! piCout << s.findRange('{', '}', '\\', 0, &len) << len << s.mid(2, len); // 2 15 figures{inside}
//! s = "\"text\\\"shielded\" next";
//! piCout << s.findRange('"', '"', '\\', 0, &len) << len << s.mid(1, len); // 1 14 text\"shielded
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord()
int PIString::findRange(const PIChar start, const PIChar end, const PIChar shield, const int start_index, int * len) const { int PIString::findRange(const PIChar start, const PIChar end, const PIChar shield, const int start_index, int * len) const {
if (len) *len = 0; if (len) *len = 0;
bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end); bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end);
@@ -950,6 +891,22 @@ int PIString::findRange(const PIChar start, const PIChar end, const PIChar shiel
} }
int PIString::findAny(const PIString & str, const int start) const {
for (int i = start; i < length(); ++i) {
if (str.contains(at(i))) return i;
}
return -1;
}
int PIString::findAnyLast(const PIString & str, const int start) const {
for (int i = length() - 1; i >= start; --i) {
if (str.contains(at(i))) return i;
}
return -1;
}
int PIString::entries(const PIChar c) const { int PIString::entries(const PIChar c) const {
int sz = size_s(), ret = 0; int sz = size_s(), ret = 0;
for (int i = 0; i < sz; ++i) { for (int i = 0; i < sz; ++i) {
@@ -971,17 +928,6 @@ bool PIString::endsWith(const PIString & str) const {
} }
//! \~\details
//! \~\code
//! piCout << PIString("true").toBool(); // true
//! piCout << PIString("Yes").toBool(); // true
//! piCout << PIString(" TRUE ").toBool(); // true
//! piCout << PIString(" 1 ").toBool(); // true
//! piCout << PIString("0").toBool(); // false
//! piCout << PIString("0.1").toBool(); // true
//! piCout << PIString("-1").toBool(); // false
//! piCout << PIString("").toBool(); // false
//! \endcode
bool PIString::toBool() const { bool PIString::toBool() const {
static const PIString s_true = PIStringAscii("true"); static const PIString s_true = PIStringAscii("true");
static const PIString s_yes = PIStringAscii("yes" ); static const PIString s_yes = PIStringAscii("yes" );
@@ -995,15 +941,6 @@ bool PIString::toBool() const {
} }
//! \~\details
//! \~\code
//! PIString s("\t ! word");
//! piCout << s.takeSymbol(); // "!"
//! piCout << s.takeSymbol(); // "w"
//! piCout << s.takeSymbol(); // "o"
//! piCout << s; // "rd"
//! \endcode
//! \~\sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange()
PIString PIString::takeSymbol() { PIString PIString::takeSymbol() {
PIString ret; PIString ret;
int sz = size_s(), ss = -1; int sz = size_s(), ss = -1;
@@ -1020,15 +957,6 @@ PIString PIString::takeSymbol() {
} }
//! \~\details
//! \~\code
//! PIString s("some words\nnew line ");
//! piCout << s.takeWord(); // "some"
//! piCout << s.takeWord(); // "words"
//! piCout << s.takeWord(); // "new"
//! piCout << s; // " line "
//! \endcode
//! \~\sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange()
PIString PIString::takeWord() { PIString PIString::takeWord() {
int sz = size_s(), ws = -1, we = -1; int sz = size_s(), ws = -1, we = -1;
for (int i = 0; i < sz; ++i) { for (int i = 0; i < sz; ++i) {
@@ -1049,10 +977,6 @@ PIString PIString::takeWord() {
} }
//! \~\details
//! \~\code
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange()
PIString PIString::takeCWord() { PIString PIString::takeCWord() {
PIString ret; PIString ret;
int sz = size_s(), ws = -1, we = -1; int sz = size_s(), ws = -1, we = -1;
@@ -1085,15 +1009,6 @@ PIString PIString::takeCWord() {
} }
//! \~\details
//! \~\code
//! PIString s("some words\nnew line \n\nend");
//! piCout << s.takeLine(); // "some words"
//! piCout << s.takeLine(); // "new line "
//! piCout << s.takeLine(); // ""
//! piCout << s; // "end"
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange()
PIString PIString::takeLine() { PIString PIString::takeLine() {
int sz = size_s(), le = -1; int sz = size_s(), le = -1;
for (int i = 0; i < sz; ++i) { for (int i = 0; i < sz; ++i) {
@@ -1114,16 +1029,6 @@ PIString PIString::takeLine() {
} }
//! \~\details
//! \~\code
//! PIString s(" 0xFF -99 1.2E+5f 1000L");
//! piCout << s.takeNumber(); // "0xFF"
//! piCout << s.takeNumber(); // "-99"
//! piCout << s.takeNumber(); // "1.2E+5f"
//! piCout << s.takeNumber(); // "1000L"
//! piCout << s; // ""
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange()
PIString PIString::takeNumber() { PIString PIString::takeNumber() {
PIString ret; PIString ret;
int sz = size_s(), ls = -1, le = -1, phase = 0; int sz = size_s(), ls = -1, le = -1, phase = 0;
@@ -1218,18 +1123,6 @@ PIString PIString::takeNumber() {
} }
//! \~\details
//! \~english "shield" symbol prevent analysis of the next symbol
//! \~russian Символ "shield" экранирует следующий символ
//! \~\code
//! PIString s(" {figures{inside}}");
//! piCout << s.takeRange('{', '}'); // "figures{inside}"
//! piCout << s; // ""
//! s = "\"text\\\"shielded\" next";
//! piCout << s.takeRange('"', '"'); // "text\"shielded"
//! piCout << s; // " next"
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber()
PIString PIString::takeRange(const PIChar start, const PIChar end, const PIChar shield) { PIString PIString::takeRange(const PIChar start, const PIChar end, const PIChar shield) {
PIString ret; PIString ret;
bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end); bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end);
@@ -1277,12 +1170,6 @@ PIString PIString::takeRange(const PIChar start, const PIChar end, const PIChar
} }
//! \~\details
//! \~\code
//! PIString s("a(b(c)d)e");
//! piCout << s.inBrackets('(', ')'); // "b(c)d"
//! piCout << s; // s = "a(b(c)d)e"
//! \endcode
PIString PIString::inBrackets(const PIChar start, const PIChar end) const { PIString PIString::inBrackets(const PIChar start, const PIChar end) const {
int slen = length(); int slen = length();
int st = -1, bcnt = 0; int st = -1, bcnt = 0;
@@ -1302,88 +1189,11 @@ PIString PIString::inBrackets(const PIChar start, const PIChar end) const {
} }
//! \~\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'.
//! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\code
//! piCout << PIString("0123456789").data(); // 0123456789
//! piCout << PIString("№1").data(); // №1
//! \endcode
//! \~\sa \a dataConsole(), \a dataUTF8()
const char * PIString::data() const {
if (isEmpty()) return "";
buildData(__syslocname__);
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 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()
const char * PIString::dataAscii() const {
if (isEmpty()) return "";
deleteData();
data_ = (char*)malloc(size()+1);
for (int i = 0; i < size_s(); ++i) {
data_[i] = uchar(at(i).ch);
}
data_[size()] = '\0';
return data_;
}
PIString PIString::toUpperCase() const { 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.d[i] = str.d[i].toUpper(); str[i] = str[i].toUpper();
} }
return str; return str;
} }
@@ -1393,7 +1203,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.d[i] = str.d[i].toLower(); str[i] = str[i].toLower();
} }
return str; return str;
} }
@@ -1433,26 +1243,6 @@ ldouble PIString::toLDouble() const {
} }
//! \~\details
//! \~english
//! Example:
//! \~russian
//! Пример:
//! \~\code
//! PIString s;
//! s.setReadableSize(512);
//! piCout << s; // 512 B
//! s.setReadableSize(5120);
//! piCout << s; // 5.0 kB
//! s.setReadableSize(512000);
//! piCout << s; // 500.0 kB
//! s.setReadableSize(5120000);
//! piCout << s; // 4.8 MB
//! s.setReadableSize(512000000);
//! piCout << s; // 488.2 MB
//! s.setReadableSize(51200000000);
//! piCout << s; // 47.6 GB
//! \endcode
PIString & PIString::setReadableSize(llong bytes) { PIString & PIString::setReadableSize(llong bytes) {
clear(); clear();
if (bytes < 1024) { if (bytes < 1024) {
@@ -1561,38 +1351,6 @@ int versionLabelValue(PIString s) {
} }
//! \relatesalso PIString
//! \~\details
//! \~english
//! This function parse version to number codes and labels. Then it
//! compare no more than "components" codes. If there is no difference, compare
//! labels. Each label has corresponding integer value, so
//! "prealpha" < "alpha" < "prebeta" < "beta" < "rc[N]" < "" < "r[N]".
//! Example:
//! \~russian
//! Этот метод разбирает версии на числовые части и метку. Затем сравнивает
//! не более чем "components" частей. Если различий нет, то сравниваются
//! метки. Каждой метке соответствует своё значение так, что
//! "prealpha" < "alpha" < "prebeta" < "beta" < "rc[N]" < "" < "r[N]".
//! Пример:
//! \~\code
//! piCout << versionCompare("1.0.0_rc2-999", "1.0.1_rc2-999"); // -1, <
//! piCout << versionCompare("1.0.0", "0.9.2"); // 1, >
//! piCout << versionCompare("1.0.0_r1", "1.0.0"); // 1, >
//! piCout << versionCompare("1.0.0_r1", "1.0.0", 3); // 0, =
//! piCout << versionCompare("1.0.0_r2", "1.0.0", 3); // 0, =
//! piCout << versionCompare(".2-alpha", "0.2_alpha"); // 0, =
//! piCout << versionCompare("1_prebeta", "1.0_alpha"); // 1, >
//! \endcode
//! \~\return
//! \~english
//! * 0 - equal
//! * 1 - v0 > v1
//! * -1 - v0 < v1
//! \~russian
//! * 0 - равны
//! * 1 - v0 > v1
//! * -1 - v0 < v1
int versionCompare(const PIString & v0, const PIString & v1, int components) { int versionCompare(const PIString & v0, const PIString & v1, int components) {
PIStringList strs[2]; PIVector<int> codes[2]; PIStringList strs[2]; PIVector<int> codes[2];
parseVersion(v0.toLowerCase(), codes[0], strs[0]); parseVersion(v0.toLowerCase(), codes[0], strs[0]);
@@ -1621,25 +1379,6 @@ int versionCompare(const PIString & v0, const PIString & v1, int components) {
} }
//! \relatesalso PIString
//! \~\details
//! \~english
//! Parse version as described in \a versionCompare() and returns
//! classic view of codes and labels: major.minor.revision[-build][_label].
//! Example:
//! \~russian
//! Разбирает версию по описанию \a versionCompare() и возвращает
//! классическое представление версии и метки: major.minor.revision[-build][_label].
//! Пример:
//! \~\code
//! piCout << versionNormalize(""); // 0.0.0
//! piCout << versionNormalize("1"); // 1.0.0
//! piCout << versionNormalize("1.2"); // 1.2.0
//! piCout << versionNormalize("1.2.3"); // 1.2.3
//! piCout << versionNormalize("1.2+rc1.99"); // 1.2.99_rc1
//! piCout << versionNormalize("1.2-alpha"); // 1.2.0_alpha
//! piCout << versionNormalize("1..4_rc2-999"); // 1.0.4-999_rc2
//! \endcode
PIString versionNormalize(const PIString & v) { PIString versionNormalize(const PIString & v) {
PIStringList strs; PIVector<int> codes; PIStringList strs; PIVector<int> codes;
parseVersion(v.toLowerCase(), codes, strs); parseVersion(v.toLowerCase(), codes, strs);
@@ -1662,7 +1401,10 @@ 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.write(v); s.setControl(0, true);
s << v.data();
s.restoreControl();
s.quote(); s.quote();
return s; return s;
} }

View File

@@ -27,1533 +27,712 @@
#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;
//! \ingroup Core class PIP_EXPORT PIString: public PIDeque<PIChar>
//! \~\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:
typedef PIDeque<PIChar>::iterator iterator; //! Contructs an empty string
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 Contructs an empty string.
//! \~russian Создает пустую строку.
PIString() {}
//! \~english Value for elide at left.
//! \~russian Значение для пропуска слева.
static const float ElideLeft ; static const float ElideLeft ;
//! \~english Value for elide at center.
//! \~russian Значение для пропуска в середине.
static const float ElideCenter; static const float ElideCenter;
//! \~english Value for elide at right.
//! \~russian Значение для пропуска справа.
static const float ElideRight ; static const float ElideRight ;
PIString & operator +=(const PIChar & c) {d.push_back(c); return *this;} PIString & operator +=(const PIChar c) {push_back(c); return *this;}
PIString & operator +=(const char c) {d.push_back(PIChar(c)); return *this;} PIString & operator +=(const char c) {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. PIString(const PIString & o): PIDeque<PIChar>(o) {}
//! \~russian Создает копию строки.
PIString(const PIString & o) {d = o.d;}
//! \~english Move constructor. PIString(PIString && o): PIDeque<PIChar>(std::move(o)) {}
//! \~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 character "c".
//! \~russian Создает строку из одного символа "c".
PIString(const char c) {*this += PIChar(c);}
//! \~english Contructs string from C-string "str" (system codepage). //! Contructs string with single symbol "c"
//! \~russian Создает строку из C-строки "str" (кодировка системы). PIString(const PIChar c): PIDeque<PIChar>() {*this += c;}
//! \~\details PIString(const char c): PIDeque<PIChar>() {*this += PIChar(c);}
//! \~english
//! "str" should be null-terminated\n
//! \~russian
//! "str" должна заканчиваться нулевым байтом\n
//! \~\code
//! PIString s("string");
//! \endcode
PIString(const char * str) {*this += str;}
//! \~english Contructs string from \c wchar_t C-string "str". /*! \brief Contructs string from c-string "str"
//! \~russian Создает строку из \c wchar_t C-строки "str". * \details "str" should be null-terminated\n
//! \~\details * Example: \snippet pistring.cpp PIString(char * ) */
//! \~english PIString(const char * str): PIDeque<PIChar>() {*this += str;}
//! "str" should be null-terminated
//! \~russian
//! "str" должна заканчиваться нулевым \c wchar_t
//! \~\code
//! PIString s(L"string");
//! \endcode
PIString(const wchar_t * str) {*this += str;}
//! \~english Contructs string from byte array "ba" (as UTF-8).
//! \~russian Создает строку из байтового массива "ba" (как UTF-8).
PIString(const PIByteArray & ba) {*this += ba;}
//! \~english Contructs string from "len" characters of buffer "str".
//! \~russian Создает строку из "len" символов массива "str".
PIString(const PIChar * str, const int len): d(str, size_t(len)) {}
//! \~english Contructs string from "len" characters of buffer "str" (system codepage).
//! \~russian Создает строку из "len" символов массива "str" (кодировка системы).
//! \~\details
//! \~\code
//! PIString s("string", 3); // s = "str"
//! \endcode
PIString(const char * str, const int len) {appendFromChars(str, len);}
//! \~english Contructs string as sequence of characters "c" of buffer with length "len".
//! \~russian Создает строку как последовательность длиной "len" символа "c".
//! \~\details
//! \~\code
//! PIString s(5, 'p'); // s = "ppppp"
//! \endcode
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 characters "c" of buffer with length "len".
//! \~russian Создает строку как последовательность длиной "len" символа "c".
//! \~\details
//! \~\code
//! PIString s(5, "№"); // s = "№№№№№"
//! \endcode
PIString(const int len, const PIChar c) {for (int i = 0; i < len; ++i) d.push_back(c);}
PIString(const PIConstChars & c) {*this += c;}
~PIString(); /*! \brief Contructs string from \c wchar_t c-string "str"
* \details "str" should be null-terminated\n
* Example: \snippet pistring.cpp PIString(wchar_t * ) */
PIString(const wchar_t * str): PIDeque<PIChar>() {*this += str;}
//! \~english Assign operator. //! Contructs string from byte array "ba"
//! \~russian Оператор присваивания. PIString(const PIByteArray & ba): PIDeque<PIChar>() {*this += ba;}
PIString & operator =(const PIString & o) {if (this == &o) return *this; d = o.d; return *this;}
//! \~english Assign move operator. //! \brief Contructs string from "len" characters of buffer "str"
//! \~russian Оператор перемещающего присваивания. PIString(const PIChar * str, const int len): PIDeque<PIChar>(str, size_t(len)) {}
PIString & operator =(PIString && o) {d.swap(o.d); piSwap(data_, o.data_); return *this;}
//! \~english Assign operator. /*! \brief Contructs string from "len" characters of buffer "str"
//! \~russian Оператор присваивания. * \details Example: \snippet pistring.cpp PIString(char * , int) */
PIString & operator =(const PIConstChars & o) {d.clear(); *this += o; return *this;} PIString(const char * str, const int len): PIDeque<PIChar>() {appendFromChars(str, len);}
//! \~english Assign operator. /*! \brief Contructs string as sequence of characters "c" of buffer with length "len"
//! \~russian Оператор присваивания. * \details Example: \snippet pistring.cpp PIString(int, char) */
PIString & operator =(const char * o) {d.clear(); *this += o; return *this;} PIString(const int len, const char c): PIDeque<PIChar>() {for (int i = 0; i < len; ++i) push_back(c);}
//! \~english Compare operator. /*! \brief Contructs string as sequence of symbols "c" of buffer with length "len"
//! \~russian Оператор сравнения. * \details Example: \snippet pistring.cpp PIString(int, PIChar) */
PIString(const int len, const PIChar c): PIDeque<PIChar>() {for (int i = 0; i < len; ++i) push_back(c);}
~PIString() {}
PIString & operator =(const PIString & o) {if (this == &o) return *this; clear(); *this += o; return *this;}
PIString & operator =(PIString && o) {swap(o); return *this;}
//! Compare operator
bool operator ==(const PIString & str) const; bool operator ==(const PIString & str) const;
//! \~english Compare operator. //! Compare operator
//! \~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. //! Compare operator
//! \~russian Оператор сравнения.
bool operator ==(const char * str) const {return *this == PIString(str);} bool operator ==(const char * str) const {return *this == PIString(str);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator !=(const PIString & str) const; bool operator !=(const PIString & str) const;
//! \~english Compare operator. //! Compare operator
//! \~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. //! Compare operator
//! \~russian Оператор сравнения.
bool operator !=(const char * str) const {return *this != PIString(str);} bool operator !=(const char * str) const {return *this != PIString(str);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator <(const PIString & str) const; bool operator <(const PIString & str) const;
//! \~english Compare operator. //! Compare operator
//! \~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. //! Compare operator
//! \~russian Оператор сравнения.
bool operator <(const char * str) const {return *this < PIString(str);} bool operator <(const char * str) const {return *this < PIString(str);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator >(const PIString & str) const; bool operator >(const PIString & str) const;
//! \~english Compare operator. //! Compare operator
//! \~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. //! Compare operator
//! \~russian Оператор сравнения.
bool operator >(const char * str) const {return *this > PIString(str);} bool operator >(const char * str) const {return *this > PIString(str);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator <=(const PIString & str) const {return !(*this > str);} bool operator <=(const PIString & str) const {return !(*this > str);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator <=(const PIChar c) const {return !(*this > c);} bool operator <=(const PIChar c) const {return !(*this > c);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator <=(const char * str) const {return *this <= PIString(str);} bool operator <=(const char * str) const {return *this <= PIString(str);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator >=(const PIString & str) const {return !(*this < str);} bool operator >=(const PIString & str) const {return !(*this < str);}
//! \~english Compare operator. //! Compare operator
//! \~russian Оператор сравнения.
bool operator >=(const PIChar c) const {return !(*this < c);} bool operator >=(const PIChar c) const {return !(*this < c);}
//! \~english Compare operator. //! Compare operator
//! \~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. /*! \brief Append string "str" at the end of string
//! \~russian Добавляет в конец строку "str". * \details Example: \snippet pistring.cpp PIString::<<(PIString) */
//! \~\details
//! \~\code
//! PIString s("this"), s1(" is"), s2(" string");
//! s << s1 << s2; // s = "this is string"
//! \endcode
PIString & operator <<(const PIString & str) {*this += str; return *this;} PIString & operator <<(const PIString & str) {*this += str; return *this;}
//! \~english Append character "c" at the end of string. /*! \brief Append symbol "c" at the end of string
//! \~russian Добавляет в конец символ "c". * \details Example: \snippet pistring.cpp PIString::<<(PIChar) */
//! \~\details PIString & operator <<(const PIChar c) {*this += c; return *this;}
//! \~\code
//! PIString s("stri");
//! s << PIChar('n') << PIChar('g'); // s = "string"
//! \endcode
PIString & operator <<(const PIChar c) {d.append(c); return *this;}
//! \~english Append character `c` at the end of string. /*! \brief Append symbol "c" at the end of string
//! \~russian Добавляет в конец символ `c`. * \details Example: \snippet pistring.cpp PIString::<<(PIChar) */
//! \~\details PIString & operator <<(const char c) {*this += PIChar(c); return *this;}
//! \~\code
//! PIString s("stri");
//! s << 'n' << 'g'; // s = "string"
//! \endcode
PIString & operator <<(const char c) {d.append(PIChar(c)); return *this;}
//! \~english Append С-string "str" at the end of string. /*! \brief Append c-string "str" at the end of string
//! \~russian Добавляет в конец C-строку "str". * \details Example: \snippet pistring.cpp PIString::<<(char * ) */
//! \~\details
//! \~\code
//! PIString s("this");
//! s << " is" << " string"; // s = "this is string"
//! \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. /*! \brief Append \c wchar_t c-string "str" at the end of string
//! \~russian Добавляет в конец \c wchar_t C-строку "str". * \details Example: \snippet pistring.cpp PIString::<<(wchar_t * ) */
//! \~\details
//! \~\code
//! PIString s;
//! s << L"№ -" << " number"; // s = "№ - number"
//! \endcode
PIString & operator <<(const wchar_t * str) {*this += str; return *this;} PIString & operator <<(const wchar_t * str) {*this += str; return *this;}
PIString & operator <<(const PIConstChars & str) {*this += str; return *this;} /*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
//! \~english Append string representation of "num" at the end of string.
//! \~russian Добавляет в конец строковое представление "num".
//! \~\details
//! \~\code
//! PIString s("ten - ");
//! s << 10; // s = "ten - 10"
//! \endcode
PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const 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. /*! \brief Append string representation of "num" at the end of string
//! \~russian Добавляет в конец строковое представление "num". * \details Example: \snippet pistring.cpp PIString::<<(int) */
//! \~\details
//! \~\code
//! PIString s("ten - ");
//! s << 10; // s = "ten - 10"
//! \endcode
PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const 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. /*! \brief Append string representation of "num" at the end of string
//! \~russian Добавляет в конец строковое представление "num". * \details Example: \snippet pistring.cpp PIString::<<(int) */
//! \~\details
//! \~\code
//! PIString s("1/10 - ");
//! s << 0.1; // s = "1/10 - 0.1"
//! \endcode
PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;} PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;}
//! \~english Append string representation of "num" at the end of string. /*! \brief Append string representation of "num" at the end of string
//! \~russian Добавляет в конец строковое представление "num". * \details Example: \snippet pistring.cpp PIString::<<(int) */
//! \~\details
//! \~\code
//! PIString s("1/10 - ");
//! s << 0.1; // s = "1/10 - 0.1"
//! \endcode
PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;} 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 Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
//! \~\details
//! \~\return \ref stl_iterators
//! \~\sa \a begin(), \a rbegin(), \a rend()
inline iterator end() {return d.end();}
inline const_iterator begin() const {return d.begin();}
inline const_iterator end() const {return d.end();}
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
//! \~\details
//! \~english It corresponds to the last element of the non-reversed array.
//! \~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. //! \brief Insert string "str" at the begin of string
//! \~russian Вставляет "str" в начало строки. PIString & prepend(const PIString & str) {insert(0, str); return *this;}
PIString & prepend(const PIString & str) {d.prepend(str.d); return *this;}
//! \brief Insert string "str" at the end of string
//! \~english Insert character `c` at the begin of string. PIString & append(const PIString & str) {*this += str; return *this;}
//! \~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 character at index "start" and maximum length "len". /*! \brief Return part of string from symbol at index "start" and maximum length "len"
//! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len". * \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid
* \sa \a left(), \a right() */
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(). /*! \brief Return sub-string of string from symbol at index "start" and maximum length "len" */
//! \~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". /*! \brief Return part of string from left and maximum length "len"
//! \~russian Возвращает подстроку от начала и максимальной длиной "len". * \details Example: \snippet pistring.cpp PIString::left
//! \~\details * \sa \a mid(), \a right() */
//! \~\code
//! PIString s("0123456789");
//! piCout << s.left(-1); // s = ""
//! piCout << s.left(1); // s = "0"
//! piCout << s.left(5); // s = "01234"
//! piCout << s.left(15); // s = "0123456789"
//! \endcode
//! \~\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". /*! \brief Return part of string from right and maximum length "len"
//! \~russian Возвращает подстроку максимальной длиной "len" и до конца. * \details Example: \snippet pistring.cpp PIString::right
//! \~\details * \sa \a mid(), \a left() */
//! \~\code
//! PIString s("0123456789");
//! piCout << s.right(-1); // s = ""
//! piCout << s.right(1); // s = "9"
//! piCout << s.right(5); // s = "56789"
//! piCout << s.right(15); // s = "0123456789"
//! \endcode
//! \~\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 character as index "start" and maximum length "len" and return this string. /*! \brief Remove part of string from symbol as index "start" and maximum length "len"
//! \~russian Удаляет часть строки от символа "start" и максимальной длины "len", возвращает эту строку. * and return this string
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::cutMid
* \sa \a cutLeft(), \a cutRight() */
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. /*! \brief Remove part of string from left and maximum length "len" and return this string
//! \~russian Удаляет часть строки от начала и максимальной длины "len", возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::cutLeft
//! \~\details * \sa \a cutMid(), \a cutRight() */
//! \~\code
//! PIString s("0123456789");
//! s.cutLeft(1);
//! piCout << s; // s = "123456789"
//! s.cutLeft(3);
//! piCout << s; // s = "456789"
//! s.cutLeft(30);
//! piCout << s; // s = ""
//! \endcode
//! \~\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. /*! \brief Remove part of string from right and maximum length "len" and return this string
//! \~russian Удаляет часть строки максимальной длины "len" от конца, возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::cutRight
//! \~\details * \sa \a cutMid(), \a cutLeft() */
//! \~\code
//! PIString s("0123456789");
//! s.cutRight(1);
//! piCout << s; // s = "012345678"
//! s.cutRight(3);
//! piCout << s; // s = "012345"
//! s.cutRight(30);
//! piCout << s; // s = ""
//! \endcode
//! \~\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. /*! \brief Remove spaces at the start and at the end of string and return this string
//! \~russian Удаляет пробельные символы с начала и конца строки и возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::trim
* \sa \a trimmed() */
PIString & trim(); PIString & trim();
//! \~english Returns copy of this string without spaces at the start and at the end. /*! \brief Return copy of this string without spaces at the start and at the end
//! \~russian Возвращает копию этой строки без пробельных символов с начала и конца. * \details Example: \snippet pistring.cpp PIString::trimmed
//! \~\details * \sa \a trim() */
//! \~\code
//! PIString s(" \t string \n");
//! piCout << s.trimmed(); // s = "string"
//! piCout << s; // s = " string "
//! \endcode
//! \~\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. /*! \brief Replace part of string from index "from" and maximum length "len"
//! \~russian Заменяет часть строки от символа "from" и максимальной длины "len" строкой "with", возвращает эту строку. * with string "with" and return this string
* \details Example: \snippet pistring.cpp PIString::replace_0
* \sa \a replaced(), \a replaceAll() */
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". /*! \brief Replace part copy of this string from index "from" and maximum length "len"
//! \~russian Заменяет часть копии этой строки от символа "from" и максимальной длины "len" строкой "with". * with string "with" and return copied string
//! \~\details * \details Example: \snippet pistring.cpp PIString::replaced_0
//! \~\code * \sa \a replace(), \a replaceAll() */
//! PIString s("0123456789");
//! piCout << s.replaced(2, 3, "_cut_"); // s = "01_cut_56789"
//! piCout << s.replaced(0, 1, "one_"); // s = "one_123456789"
//! \endcode
//! \~\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. /*! \brief Replace first founded substring "what" with string "with" and return this string
//! \~russian Заменяет первую найденную подстроку "what" строкой "with", возвращает эту строку. * \details If "ok" is not null, it set to "true" if something was replaced\n
* Example: \snippet pistring.cpp PIString::replace_1
* \sa \a replaced(), \a replaceAll() */
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". /*! \brief Replace first founded substring "what" with string "with" and return copied string
//! \~russian Заменяет в копии строки первую найденную подстроку "what" строкой "with". * \details If "ok" is not null, it set to "true" if something was replaced\n
//! \~\details * Example: \snippet pistring.cpp PIString::replaced_1
//! \~english If "ok" is not null, it set to "true" if something was replaced. * \sa \a replaced(), \a replaceAll() */
//! \~russian Если "ok" не null, то устанавливает в "true" если замена произведена.
//! \~\code
//! PIString s("pip string");
//! bool ok;
//! piCout << s.replace("string", "conf", &ok); // s = "pip conf", true
//! piCout << s.replace("PIP", "PlInPr", &ok); // s = "pip string", false
//! \endcode
//! \~\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. /*! \brief Replace all founded substrings "what" with strings "with" and return this string
//! \~russian Заменяет все найденные подстроки "what" строками "with", возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::replaceAll
* \sa \a replace(), \a replaced() */
PIString & replaceAll(const PIString & what, const PIString & with); PIString & replaceAll(const PIString & what, const PIString & with);
//! \~english Replace all founded substrings "what" with characters "with" and return this string. /*! \brief Replace all founded substrings "what" with symbol "with" and return this string
//! \~russian Заменяет все найденные подстроки "what" символами "with", возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::replaceAll
* \sa \a replace(), \a replaced() */
PIString & replaceAll(const PIString & what, const char with); PIString & replaceAll(const PIString & what, const char with);
//! \~english Replace all founded characters "what" with characters "with" and return this string. /*! \brief Replace all founded symbols "what" with symbol "with" and return this string
//! \~russian Заменяет все найденные символы "what" символами "with", возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::replaceAll
* \sa \a replace(), \a replaced() */
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.
//! \~russian Заменяет в копии строки все найденные подстроки "what" строками "with".
//! \~\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 characters "with" in string copy.
//! \~russian Заменяет в копии строки все найденные подстроки "what" символами "with".
//! \~\sa \a replaceAll()
PIString replacedAll(const PIString & what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;}
//! \~english Replace all founded characters "what" with characters "with" in string copy.
//! \~russian Заменяет в копии строки все найденные символы "what" символами "with".
//! \~\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.
//! \~russian Удаляет все найденные подстроки "what", возвращает эту строку.
PIString & removeAll(const PIString & str); PIString & removeAll(const PIString & str);
//! \~english Remove all founded characters "what" and return this string. PIString & removeAll(char c) {PIDeque<PIChar>::removeAll(PIChar(c)); return *this;}
//! \~russian Удаляет все найденные символы "what", возвращает эту строку.
PIString & removeAll(char c) {d.removeAll(PIChar(c)); return *this;}
//! \~english Repeat content of string "times" times and return this string. /*! \brief Repeat content of string "times" times and return this string
//! \~russian Повторяет содержимое строки "times" раз и возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::repeat */
//! \~\details
//! \~\code
//! PIString s(" :-) ");
//! s.repeat(3);
//! piCout << s; // :-) :-) :-)
//! \endcode
//! \~\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. /*! \brief Returns repeated "times" times string
//! \~russian Возвращает повторённую "times" раз строку. * \details Example: \snippet pistring.cpp PIString::repeated */
//! \~\details
//! \~\code
//! PIString s(" :-) ");
//! piCout << s.repeated(3); // :-) :-) :-)
//! piCout << s; // :-)
//! \endcode
//! \~\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 character "c" after index "index" and return this string. /*! \brief Insert symbol "c" after index "index" and return this string
//! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::insert_0 */
//! \~\details PIString & insert(const int index, const PIChar c) {PIDeque<PIChar>::insert(index, c); return *this;}
//! \~\code
//! PIString s("pp");
//! s.insert(1, "i");
//! piCout << s; // s = "pip"
//! \endcode
PIString & insert(const int index, const PIChar c) {d.insert(index, c); return *this;}
//! \~english Insert character "c" after index "index" and return this string. /*! \brief Insert symbol "c" after index "index" and return this string
//! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::insert_1 */
//! \~\details
//! \~\code
//! PIString s("pp");
//! s.insert(1, 'i');
//! piCout << s; // s = "pip"
//! \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. /*! \brief Insert string "str" after index "index" and return this string
//! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::insert_2 */
//! \~\details
//! \~\code
//! PIString s("stg");
//! s.insert(2, "rin");
//! piCout << s; // s = "string"
//! \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. /*! \brief Insert string "str" after index "index" and return this string
//! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::insert_2 */
//! \~\details
//! \~\code
//! PIString s("stg");
//! s.insert(2, "rin");
//! piCout << s; // s = "string"
//! \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 characters "c" at the end, and return this string. /*! \brief Enlarge string to length "len" by addition sequence of symbols
//! \~russian Увеличивает длину строки до "len" добавлением символов "c" в конец и возвращает эту строку. * "c" at the end of string, and return this string
//! \~\details * \details Example: \snippet pistring.cpp PIString::expandRightTo
//! \~\code * \sa \a expandLeftTo() */
//! PIString s("str"); PIString & expandRightTo(const int len, const PIChar c) {if (len > length()) resize(len, c); return *this;}
//! s.expandRightTo(2, "_");
//! piCout << s; // s = "str"
//! s.expandRightTo(6, "_");
//! piCout << s; // s = "str___"
//! \endcode
//! \~\sa \a expandLeftTo(), \a expandedRightTo(), \a expandedLeftTo()
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 characters "c" at the begin, and return this string. /*! \brief Enlarge string to length "len" by addition sequence of symbols
//! \~russian Увеличивает длину строки до "len" добавлением символов "c" в начало и возвращает эту строку. * "c" at the beginning of string, and return this string
//! \~\details * \details Example: \snippet pistring.cpp PIString::expandLeftTo
//! \~\code * \sa \a expandRightTo() */
//! PIString s("str"); PIString & expandLeftTo(const int len, const PIChar c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;}
//! s.expandLeftTo(2, "_");
//! piCout << s; // s = "str"
//! s.expandLeftTo(6, "_");
//! piCout << s; // s = "___str"
//! \endcode
//! \~\sa \a expandRightTo(), \a expandedRightTo(), \a expandedLeftTo()
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 characters "c" at the end. /*! \brief Enlarge and returns copy of this string to length "len"
//! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в конец. * by addition sequence of symbols "c" at the end of string
//! \~\details * \sa \a expandRightTo() */
//! \~\code
//! PIString s("str");
//! piCouy << s.expandedRightTo(5, "_"); // s = "str__"
//! piCout << s; // s = "str"
//! \endcode
//! \~\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 characters "c" at the begin. /*! \brief Enlarge and returns copy of this string to length "len"
//! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в начало. * by addition sequence of symbols "c" at the beginning of string
//! \~\details * \sa \a expandLeftTo() */
//! \~\code
//! PIString s("str");
//! piCouy << s.expandedLeftTo(5, "_"); // s = "__str"
//! piCout << s; // s = "str"
//! \endcode
//! \~\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" characters at the beginning and end, and return this string. /*! \brief Add "c" symbols at the beginning and end of the string, and return this string
//! \~russian Добавляет символ "c" в начало и конец и возвращает эту строку. * \sa \a quoted() */
//! \~\details PIString & quote(PIChar c = PIChar('"')) {insert(0, c); *this += c; return *this;}
//! \~\code
//! PIString s("str");
//! s.quote();
//! piCout << s; // s = ""str""
//! \endcode
//! \~\sa \a quoted()
PIString & quote(PIChar c = PIChar('"')) {d.prepend(c); d.append(c); return *this;}
//! \~english Returns quoted copy of this string. /*! \brief Return quoted copy of this string
//! \~russian Возвращает копию строки с добавленным в начало и конец символом "c". * \sa \a quote() */
//! \~\details
//! \~\code
//! PIString s("str");
//! piCout << s.quoted(); // s = ""str""
//! piCout << s; // s = "str"
//! \endcode
//! \~\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. /*! \brief Reverse string and return this string
//! \~russian Разворачивает и возвращает эту строку. * \details Example: \snippet pistring.cpp PIString::reverse
//! \~\details * \sa \a reversed() */
//! \~\code PIString & reverse() {PIString str(*this); clear(); piForeachCR (PIChar c, str) push_back(c); return *this;}
//! PIString s("0123456789");
//! s.reverse();
//! piCout << s; // s = "9876543210"
//! \endcode
//! \~\sa \a reversed()
PIString & reverse() {d.reverse(); return *this;}
//! \~english Reverse copy of this string. /*! \brief Reverse copy of this string and return it
//! \~russian Разворачивает копию этой строки. * \details Example: \snippet pistring.cpp PIString::reversed
//! \~\details * \sa \a reverse() */
//! \~\code PIString reversed() const {PIString str(*this); str.reverse(); return str;}
//! PIString s("0123456789");
//! piCout << s.reversed(); // s = "9876543210"
//! piCout << s; // s = "0123456789"
//! \endcode
//! \~\sa \a reverse()
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. /*! \brief Elide string to maximum size \"size\" and return this string
//! \~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". /*! \brief Elide copy of this string to maximum size \"size\" and return it
//! \~russian Уменьшает копию этой строки до размера "size", вставляя ".." в положение "pos". * \details Example: \snippet pistring.cpp PIString::elided
//! \~\details * \sa \a elide() */
//! \~\code
//! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideLeft); // ..ABCDEF
//! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideCenter); // 123..DEF
//! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideRight); // 123456..
//! piCout << PIString("123456789ABCDEF").elided(8, 0.25); // 12..CDEF
//! \endcode
//! \~\sa \a elide()
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 character at index "start" and maximum length "len" and return it. /*! \brief Take a part of string from symbol at index "start" and maximum length "len" and return it
//! \~russian Извлекает часть строки от символа "start" максимальной длины "len" и возвращает её. * \sa \a takeLeft, \a takeRight() */
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.takeMid(1, 3); // "123"
//! piCout << s; // s = "0456789"
//! \endcode
//! \~\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. /*! \brief Take a part from the begin of string with maximum length "len" and return it
//! \~russian Извлекает часть строки от начала максимальной длины "len" и возвращает её. * \sa \a takeMid(), \a takeRight() */
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.takeLeft(3); // "012"
//! piCout << s; // s = "3456789"
//! \endcode
//! \~\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. /*! \brief Take a part from the end of string with maximum length "len" and return it
//! \~russian Извлекает часть строки с конца максимальной длины "len" и возвращает её. * \sa \a takeMid(), \a takeLeft() */
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.takeRight(3); // "789"
//! piCout << s; // s = "0123456"
//! \endcode
//! \~\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 character from the begin of this string and return it. /*! \brief Take a symbol from the begin of this string and return it
//! \~russian Извлекает символ с начала строки и возвращает его как строку. * \details Example: \snippet pistring.cpp PIString::takeSymbol
* \sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
PIString takeSymbol(); PIString takeSymbol();
//! \~english Take a word from the begin of this string and return it. /*! \brief Take a word from the begin of this string and return it
//! \~russian Извлекает слово с начала строки и возвращает его. * \details Example: \snippet pistring.cpp PIString::takeWord
* \sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
PIString takeWord(); PIString takeWord();
//! \~english Take a word with letters, numbers and '_' characters from the begin of this string and return it. /*! \brief Take a word with letters, numbers and '_' symbols from the
//! \~russian Извлекает слово из букв, цифр и симолов '_' с начала строки и возвращает его. * begin of this string and return it
* \details Example: \snippet pistring.cpp PIString::takeCWord
* \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
PIString takeCWord(); PIString takeCWord();
//! \~english Take a line from the begin of this string and return it. /*! \brief Take a line from the begin of this string and return it
//! \~russian Извлекает строку текста (до новой строки) с начала строки и возвращает её. * \details Example: \snippet pistring.cpp PIString::takeLine
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange() */
PIString takeLine(); PIString takeLine();
//! \~english Take a number with C-format from the begin of this string and return it. /*! \brief Take a number with C-format from the begin of this string and return it
//! \~russian Извлекает число в C-формате с начала строки и возвращает его как строку. * \details Example: \snippet pistring.cpp PIString::takeNumber
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange() */
PIString takeNumber(); PIString takeNumber();
//! \~english Take a range between "start" and "end" characters from the begin of this string and return it. /*! \brief Take a range between "start" and "end" symbols from the begin of this
//! \~russian Извлекает диапазон между символами "start" и "end" с начала строки и возвращает его. * string and return it.
* \details "Shield" symbol prevent analysis of the next symbol.
* Example: \snippet pistring.cpp PIString::takeRange
* \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber() */
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" characters from the beginning. /*! \brief Return a string in brackets "start" and "end" symbols from the begin of this
//! \~russian Возвращает строку между символами "start" и "end" с начала строки. * string and return it.
* \details Example: string = "a(b(c)d)e"; inBrackets('(', ')') = "b(c)d"; */
PIString inBrackets(const PIChar start, const PIChar end) const; PIString inBrackets(const PIChar start, const PIChar end) const;
//! \~english Returns \c char * representation of this string in system codepage. /*! \brief Return real bytes count of this string
//! \~russian Возвращает \c char * представление строки в системной кодировке. * \details It`s equivalent length of char sequence
const char * data() const; * returned by function \a data() - 1, without terminating null-char \n
* Example: \snippet pistring.cpp PIString::lengthAscii
* \sa \a data() */
int lengthAscii() const {buildData(__syslocname__); return data_.size_s() - 1;}
//! \~english Returns \c char * representation of this string in terminal codepage. /*! \brief Return \c char * representation of this string in system codepage
//! \~russian Возвращает \c char * представление строки в кодировке консоли. * \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n
* Example: \snippet pistring.cpp PIString::data
* \sa \a dataConsole(), \a dataUTF8() */
const char * data() const {buildData(__syslocname__); return (const char *)(data_.data());}
/*! \brief Return \c char * representation of this string in terminal codepage
* \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n
* \sa \a data(), \a dataUTF8() */
const char * dataConsole() const; const char * dataConsole() const;
//! \~english Returns \c char * representation of this string in UTF-8. /*! \brief Return \c char * representation of this string in UTF-8
//! \~russian Возвращает \c char * представление строки в кодировке UTF-8. * \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n
* \sa \a data(), \a dataConsole() */
const char * dataUTF8() const; const char * dataUTF8() const;
//! \~english Returns \c char * representation of this string in ASCII. /*! \brief Return \c char * representation of this string in ASCII
//! \~russian Возвращает \c char * представление строки в кодировке ASCII. * \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n */
const char * dataAscii() const; const char * dataAscii() const;
//! \~english Returns hash of string //! Returns hash
//! \~russian Возвращает хэш строки
uint hash() const; uint hash() const;
//! \~english Same as \a toUTF8(). //! \brief Return \a PIByteArray contains \a data() of this string without terminating null-char
//! \~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. //! \brief Return \a PIByteArray contains UTF-8 \a data() of this string without terminating null-char
//! \~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. //! \brief Return \a PIByteArray contains custom charset representation of this string without terminating null-char
//! \~russian Возвращает \a PIByteArray содержащий строку в указанной кодировке без завершающего нулевого байта.
PIByteArray toCharset(const char * c) const; PIByteArray toCharset(const char * c) const;
//! \~english Split string with delimiter "delim" to \a PIStringList. /*! \brief Split string with delimiter "delim" to \a PIStringList and return it
//! \~russian Разделяет строку в \a PIStringList через разделитель "delim". * \details Example: \snippet pistring.cpp PIString::split */
//! \~\details
//! \~\code
//! PIString s("1 2 3");
//! piCout << s.split(" "); // {"1", "2", "3"}
//! \endcode
PIStringList split(const PIString & delim) const; PIStringList split(const PIString & delim) const;
//! \~english Convert each character in copied string to upper case. //! \brief Convert each symbol in copyed string to upper case and return it
//! \~russian Преобразует каждый символ в скопированной строке в верхний регистр.
PIString toUpperCase() const; PIString toUpperCase() const;
//! \~english Convert each character in copied string to lower case. //! \brief Convert each symbol in copyed string to lower case and return it
//! \~russian Преобразует каждый символ в скопированной строке в нижний регистр.
PIString toLowerCase() const; PIString toLowerCase() const;
// TODO: doxygen
PIString toNativeDecimalPoints() const; PIString toNativeDecimalPoints() const;
//! \~english Returns if string contains character "c". //! \brief Returns if string contains "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". //! \brief Returns if string contains "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". //! \brief Returns if string contains "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 character "c" from character at index "start" and return first occur position. //! \brief Search symbol "c" from symbol at index "start" and return first occur position
//! \~russian Ищет символ "c" от символа "start" и возвращает первое вхождение. //! \details Example: \snippet pistring.cpp PIString::find
int find(const char c, const int start = 0) const; int find(const char c, const int start = 0) const;
//! \~english Search character "c" from character at index "start" and return first occur position.
//! \~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. //! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение. //! \details Example: \snippet pistring.cpp PIString::find
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 character at index "start" and return first occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение.
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.find("-"); // -1
//! piCout << s.find("34"); // 3
//! piCout << s.find("3", 4); // 9
//! piCout << s.find("3", 10); // -1
//! \endcode
//! \~\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);}
//! \~english Search any character of "str" from character at index "start" and return first occur position.
//! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение.
int findAny(const PIString & str, const int start = 0) const;
//! \~english Search any character of "str" from character at index "start" and return first occur position.
//! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение.
//! \~\details
//! \~\code
//! piCout << PIString("1.str").findAny(".,:"); // 1
//! piCout << PIString("1,str").findAny(".,:"); // 1
//! piCout << PIString("1:str").findAny(".,:"); // 1
//! \endcode
//! \~\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);}
//! \~english Search character "c" from character at index "start" and return last occur position. //! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \~russian Ищет символ "c" от символа "start" и возвращает последнее вхождение. //! \details Example: \snippet pistring.cpp PIString::find
int find(const char * str, const int start = 0) const {return find(PIString(str), start);}
//! \brief Search symbol "c" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const char c, const int start = 0) const; int findLast(const char c, const int start = 0) const;
//! \~english Search character "c" from character at index "start" and return last occur position. //! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \~russian Ищет символ "c" от символа "start" и возвращает последнее вхождение. //! \details Example: \snippet pistring.cpp PIString::findLast
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 character at index "start" and return last occur position. //! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \~russian Ищет подстроку "str" от символа "start" и возвращает последнее вхождение. //! \details Example: \snippet pistring.cpp PIString::findLast
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.findLast("-"); // -1
//! piCout << s.findLast("34"); // 9
//! piCout << s.findLast("3", 4); // 9
//! piCout << s.findLast("3", 10); // -1
//! \endcode
//! \~\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 character of "str" from character at index "start" and return last occur position. //! \brief Search word "word" from symbol at index "start" and return first occur position.
//! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение. //! \details Example: \snippet pistring.cpp PIString::findWord
int findAnyLast(const PIString & str, const int start = 0) const;
//! \~english Search any character of "str" from character at index "start" and return last occur position.
//! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение.
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str,0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str:0").findAnyLast(".,:"); // 4
//! \endcode
//! \~\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);}
//! \~english Search word "word" from character at index "start" and return first occur position.
//! \~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 character at index "start" and return first occur position. //! \brief Search C-style word "word" from symbol at index "start" and return first occur position.
//! \~russian Ищет C-слово "word" от симола "start" и возвращает первое вхождение. //! \details Example: \snippet pistring.cpp PIString::findCWord
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" characters at index "start_index" and return first occur position. //! \brief Search range between "start" and "end" symbols at index "start_index" and return first occur position.
//! \~russian Ищет начало диапазона между символами "start" и "end" от симола "start" и возвращает первое вхождение. //! \details Example: \snippet pistring.cpp PIString::findRange
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 character "c". //! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
//! \~russian Возвращает число вхождений символа "c". //! \details Example: \snippet pistring.cpp PIString::findAny
//! \~\details int findAny(const PIString & str, const int start = 0) const;
//! \~\code
//! piCout << PIString(".str.0").entries("."); // 2 //! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
//! piCout << PIString(".str.0").entries("0"); // 1 //! \details Example: \snippet pistring.cpp PIString::findAny
//! \endcode int findAny(const char * str, const int start = 0) const {return findAny(PIString(str), start);}
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
int findAnyLast(const PIString & str, const int start = 0) const;
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);}
//! \brief Returns number of occurrences of symbol "c"
int entries(const PIChar c) const; int entries(const PIChar c) const;
//! \~english Returns number of occurrences of character "c". //! \brief Returns number of occurrences of symbol "c"
//! \~russian Возвращает число вхождений символа "c".
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").entries('.'); // 2
//! piCout << PIString(".str.0").entries('0'); // 1
//! \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". //! \brief Return if string starts with "str"
//! \~russian Возвращает начинается ли строка со "str".
bool startsWith(const PIString & str) const; bool startsWith(const PIString & str) const;
//! \~english Returns if string ends with "str". //! \brief Return if string ends with "str"
//! \~russian Возвращает оканчивается ли строка на "str".
bool endsWith(const PIString & str) const; bool endsWith(const PIString & str) const;
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
int length() const {return d.size_s();}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
size_t size() const {return d.size();}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
ssize_t size_s() const {return d.size_s();}
//! \~english Returns \c true if string is empty, i.e. length = 0. //! \brief Return symbols length of string
//! \~russian Возвращает \c true если строка пустая, т.е. длина = 0. int length() const {return size();}
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();}
//! \~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. //! \brief Return \c true if string is empty, i.e. length = 0
//! \~russian Возвращает \c true если строка равна "true", "yes", "on" или числу > 0. bool isEmpty() const {return (size() == 0 || *this == "");}
//! \brief Return \c true if string equal "true", "yes", "on" or positive not null numeric value
bool toBool() const; bool toBool() const;
//! \~english Returns \c char numeric value of string. //! \brief Return \c char numeric value of string
//! \~russian Возвращает \c char числовое значение строки.
char toChar() const; char toChar() const;
//! \~english Returns \c short numeric value of string in base "base". //! \brief Return \c short numeric value of string in base "base"
//! \~russian Возвращает \c short числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toShort(); // 123
//! piCout << PIString("123").toShort(16); // 291
//! piCout << PIString("0x123").toShort(); // 291
//! piCout << PIString("1001").toShort(2); // 9
//! \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". //! \brief Return \c ushort numeric value of string in base "base"
//! \~russian Возвращает \c ushort числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toUShort(); // 123
//! piCout << PIString("123").toUShort(16); // 291
//! piCout << PIString("0x123").toUShort(); // 291
//! piCout << PIString("1001").toUShort(2); // 9
//! \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". //! \brief Return \c int numeric value of string in base "base"
//! \~russian Возвращает \c int числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toInt(); // 123
//! piCout << PIString("123").toInt(16); // 291
//! piCout << PIString("0x123").toInt(); // 291
//! piCout << PIString("1001").toInt(2); // 9
//! \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". //! \brief Return \c uint numeric value of string in base "base"
//! \~russian Возвращает \c uint числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toUInt(); // 123
//! piCout << PIString("123").toUInt(16); // 291
//! piCout << PIString("0x123").toUInt(); // 291
//! piCout << PIString("1001").toUInt(2); // 9
//! \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". //! \brief Return \c long numeric value of string in base "base"
//! \~russian Возвращает \c long числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toLong(); // 123
//! piCout << PIString("123").toLong(16); // 291
//! piCout << PIString("0x123").toLong(); // 291
//! piCout << PIString("1001").toLong(2); // 9
//! \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". //! \brief Return \c ulong numeric value of string in base "base"
//! \~russian Возвращает \c ulong числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toULong(); // 123
//! piCout << PIString("123").toULong(16); // 291
//! piCout << PIString("0x123").toULong(); // 291
//! piCout << PIString("1001").toULong(2); // 9
//! \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". //! \brief Return \c llong numeric value of string in base "base"
//! \~russian Возвращает \c llong числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toLLong(); // 123
//! piCout << PIString("123").toLLong(16); // 291
//! piCout << PIString("0x123").toLLong(); // 291
//! piCout << PIString("1001").toLLong(2); // 9
//! \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". //! \brief Return \c ullong numeric value of string in base "base"
//! \~russian Возвращает \c ullong числовое значение строки по основанию "base". //! \details Example: \snippet pistring.cpp PIString::toNumber
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toULLong(); // 123
//! piCout << PIString("123").toULLong(16); // 291
//! piCout << PIString("0x123").toULLong(); // 291
//! piCout << PIString("1001").toULLong(2); // 9
//! \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. //! \brief Return \c float numeric value of string
//! \~russian Возвращает \c float числовое значение строки. //! \details Example: \snippet pistring.cpp PIString::toFloat
//! \~\details
//! \~\code
//! piCout << PIString("123").toFloat(); // 123
//! piCout << PIString("1.2E+2").toFloat(); // 120
//! piCout << PIString("0.01").toFloat(); // 0.01
//! \endcode
float toFloat() const; float toFloat() const;
//! \~english Returns \c double numeric value of string. //! \brief Return \c double numeric value of string
//! \~russian Возвращает \c double числовое значение строки. //! \details Example: \snippet pistring.cpp PIString::toFloat
//! \~\details
//! \~\code
//! piCout << PIString("123").toDouble(); // 123
//! piCout << PIString("1.2E+2").toDouble(); // 120
//! piCout << PIString("0.01").toDouble(); // 0.01
//! \endcode
double toDouble() const; double toDouble() const;
//! \~english Returns \c ldouble numeric value of string. //! \brief Return \c ldouble numeric value of string
//! \~russian Возвращает \c ldouble числовое значение строки. //! \details Example: \snippet pistring.cpp PIString::toFloat
//! \~\details
//! \~\code
//! piCout << PIString("123").toLDouble(); // 123
//! piCout << PIString("1.2E+2").toLDouble(); // 120
//! piCout << PIString("0.01").toLDouble(); // 0.01
//! \endcode
ldouble toLDouble() const; ldouble toLDouble() const;
//! \~english Set string content to text representation of "value" in base "base" and return this string. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value" in base "base"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setNumber
//! \~\details PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
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. //! \brief Set string content to numeric representation of "value"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setFloat
//! \~\details PIString & setNumber(const float value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(12.3);
//! piCout << s; // 12.30000000
//! s.setNumber(12.3, 'f', 3);
//! piCout << s; // 12.300
//! s.setNumber(12.123456, 'f', 3);
//! piCout << s; // 12.123
//! s.setNumber(123456789., 'g', 2);
//! piCout << s; // 1.2e+08
//! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789
//! \endcode
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. //! \brief Set string content to numeric representation of "value"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setFloat
//! \~\details PIString & setNumber(const double & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(12.3);
//! piCout << s; // 12.30000000
//! s.setNumber(12.3, 'f', 3);
//! piCout << s; // 12.300
//! s.setNumber(12.123456, 'f', 3);
//! piCout << s; // 12.123
//! s.setNumber(123456789., 'g', 2);
//! piCout << s; // 1.2e+08
//! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789
//! \endcode
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. //! \brief Set string content to numeric representation of "value"
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку. //! \details Example: \snippet pistring.cpp PIString::setFloat
//! \~\details PIString & setNumber(const ldouble & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
//! \~\code
//! PIString s;
//! s.setNumber(12.3);
//! piCout << s; // 12.30000000
//! s.setNumber(12.3, 'f', 3);
//! piCout << s; // 12.300
//! s.setNumber(12.123456, 'f', 3);
//! piCout << s; // 12.123
//! s.setNumber(123456789., 'g', 2);
//! piCout << s; // 1.2e+08
//! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789
//! \endcode
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. //! \brief Set string content to human readable size in B/kB/MB/GB/TB
//! \~russian Устанавливает содержимое в строку с читаемым размером B/kB/MB/GB/TB/PB. //! \details Example: \snippet pistring.cpp PIString::setReadableSize
//! \~\sa PIString::readableSize()
PIString & setReadableSize(llong bytes); PIString & setReadableSize(llong bytes);
//! \~english Returns string contains numeric representation of "value" in base "base". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value" in base "base"
//! \~russian Возвращает строковое представление числа "value" по основанию "base". //! \details Example: \snippet pistring.cpp PIString::fromNumber
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \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". //! \brief Return string contains numeric representation of "value"
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision". //! \details Example: \snippet pistring.cpp PIString::fromFloat
//! \~\details static PIString fromNumber(const float value, char format = 'f', int precision = 8) {return ftos(value, format, precision);}
//! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000
//! piCout << PIString::fromNumber(12.3, 'f', 3); // 12.300
//! piCout << PIString::fromNumber(12.123456, 'f', 3); // 12.123
//! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08
//! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789
//! \endcode
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". //! \brief Return string contains numeric representation of "value"
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision". //! \details Example: \snippet pistring.cpp PIString::fromFloat
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000
//! piCout << PIString::fromNumber(12.3, 'f', 3); // 12.300
//! piCout << PIString::fromNumber(12.123456, 'f', 3); // 12.123
//! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08
//! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789
//! \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". //! \brief Return string contains numeric representation of "value"
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision". //! \details Example: \snippet pistring.cpp PIString::fromFloat
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000
//! piCout << PIString::fromNumber(12.3, 'f', 3); // 12.300
//! piCout << PIString::fromNumber(12.123456, 'f', 3); // 12.123
//! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08
//! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789
//! \endcode
static PIString fromNumber(const ldouble & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);} static PIString fromNumber(const ldouble & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
//! \~english Returns "true" or "false" //! \brief Return "true" or "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. //! \brief Return string constructed from terminal codepage
//! \~russian Возвращает строку созданную из кодировки консоли.
static PIString fromConsole(const char * s); static PIString fromConsole(const char * s);
//! \~english Returns string constructed from system codepage. //! \brief Return string constructed from system codepage
//! \~russian Возвращает строку созданную из кодировки системы.
static PIString fromSystem(const char * s); static PIString fromSystem(const char * s);
//! \~english Returns string constructed from UTF-8. //! \brief Return string constructed from UTF-8
//! \~russian Возвращает строку созданную из UTF-8.
static PIString fromUTF8(const char * s); static PIString fromUTF8(const char * s);
//! \~english Returns string constructed from UTF-8. //! \brief Return string constructed from UTF-8
//! \~russian Возвращает строку созданную из UTF-8. static PIString fromUTF8(const PIByteArray &ba);
static PIString fromUTF8(const PIByteArray & utf);
//! \~english Returns string constructed from ASCII. //! \brief Return string constructed from ASCII
//! \~russian Возвращает строку созданную из ASCII.
static PIString fromAscii(const char * s); static PIString fromAscii(const char * s);
//! \~english Returns string constructed from "len" chars ASCII. //! \brief Return string constructed from "len" chars 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. //! \brief Return string constructed from "c" codepage
//! \~russian Возвращает строку созданную из кодировки "cp". static PIString fromCodepage(const char * s, const char * c);
static PIString fromCodepage(const char * s, const char * cp);
//! \~english Returns string contains human readable size in B/kB/MB/GB/TB/PB. //! \brief Return string contains human readable size in B/kB/MB/GB/TB
//! \~russian Возвращает строку с читаемым размером B/kB/MB/GB/TB/PB. //! \details Example: \snippet pistring.cpp PIString::readableSize
//! \~\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 char fromBaseN[]; static const int 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);
@@ -1561,72 +740,52 @@ 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 \brief Output operator to PICout
//! \~english Output operator to \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
//! \~english Store operator.
//! \~russian Оператор сохранения.
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.d; return s;}
//! \relatesalso PIByteArray //! \relatesalso PIByteArray \brief Output operator to PIByteArray
//! \~english Restore operator. inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << *(PIDeque<PIChar>*)&v; return s;}
//! \~russian Оператор извлечения.
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {v.d.clear(); s >> v.d; return s;} //! \relatesalso PIByteArray \brief Input operator from PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {v.clear(); s >> *(PIDeque<PIChar>*)&v; return s;}
//! \~english Returns concatenated string. //! \brief Return concatenated string
//! \~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. //! \brief Return concatenated string
//! \~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. //! \brief Return concatenated string
//! \~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. //! \relatesalso PIString \brief Return concatenated string
//! \~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. //! \brief Return concatenated string
//! \~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
//! \~english Compare two version strings in free notation and returns 0, -1 or 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
//! \~english Converts version string in free notation to classic view.
//! \~russian Преобразует строку с версией в произвольной форме к классическому виду.
PIString PIP_EXPORT versionNormalize(const PIString & v); PIString PIP_EXPORT versionNormalize(const PIString & v);
template<> inline uint piHash(const PIString & s) {return s.hash();}
template<> inline void piSwap(PIString & f, PIString & s) { template<> inline uint piHash(const PIString & s) {return s.hash();}
f.swap(s); template<> inline void piSwap(PIString & f, PIString & s) {f.swap(s);}
}
#endif // PISTRING_H #endif // PISTRING_H

View File

@@ -20,19 +20,22 @@
#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
//! \~english Example: //! \~english Example:
//! \~russian Пример: //! \~russian Пример:
//! \~\code //! \~\snippet pistring.cpp PIStringList::join
//! PIStringList sl("1", "2");
//! sl << "3";
//! piCout << sl.join(" < "); // 1 < 2 < 3
//! \endcode
PIString PIStringList::join(const PIString & delim) const { PIString PIStringList::join(const PIString & delim) const {
PIString s; PIString s;
for (uint i = 0; i < size(); ++i) { for (uint i = 0; i < size(); ++i) {
@@ -47,12 +50,7 @@ PIString PIStringList::join(const PIString & delim) const {
//! \details //! \details
//! \~english Example: //! \~english Example:
//! \~russian Пример: //! \~russian Пример:
//! \~\code //! \~\snippet pistring.cpp PIStringList::removeStrings
//! PIStringList sl("1", "2");
//! sl << "1" << "2" << "3";
//! piCout << sl; // {"1", "2", "1", "2", "3"}
//! piCout << sl.removeStrings("1"); // {"2", "2", "3"}
//! \endcode
PIStringList & PIStringList::removeStrings(const PIString & value) { PIStringList & PIStringList::removeStrings(const PIString & value) {
for (uint i = 0; i < size(); ++i) { for (uint i = 0; i < size(); ++i) {
if (at(i) == value) { if (at(i) == value) {
@@ -67,12 +65,7 @@ PIStringList & PIStringList::removeStrings(const PIString & value) {
//! \details //! \details
//! \~english Example: //! \~english Example:
//! \~russian Пример: //! \~russian Пример:
//! \~\code //! \~\snippet pistring.cpp PIStringList::removeDuplicates
//! PIStringList sl("1", "2");
//! sl << "1" << "2" << "3";
//! piCout << sl; // {"1", "2", "1", "2", "3"}
//! piCout << sl.removeDuplicates(); // {"1", "2", "3"}
//! \endcode
PIStringList& PIStringList::removeDuplicates() { PIStringList& PIStringList::removeDuplicates() {
PIStringList l; PIStringList l;
PIString s; PIString s;
@@ -98,11 +91,7 @@ PIStringList& PIStringList::removeDuplicates() {
//! \details //! \details
//! \~english Example: //! \~english Example:
//! \~russian Пример: //! \~russian Пример:
//! \~\code //! \~\snippet pistring.cpp PIStringList::trim
//! PIStringList sl(" 1 ", "\t2", " 3\n");
//! piCout << sl; // {" 1 ", " 2", " 3\n"}
//! piCout << sl.trim(); // {"1", "2", "3"}
//! \endcode
PIStringList & PIStringList::trim() { PIStringList & PIStringList::trim() {
for (uint i = 0; i < size(); ++i) for (uint i = 0; i < size(); ++i)
(*this)[i].trim(); (*this)[i].trim();

View File

@@ -29,10 +29,6 @@
#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,8 +45,13 @@
#endif #endif
//! \addtogroup Core
//! \{
//! \class PISystemTime pisystemtime.h //! \class PISystemTime pisystemtime.h
//! \details //! \brief
//! \~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
@@ -67,10 +72,16 @@
//! \~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
//! \details //! \brief
//! \~english Time measurements
//! \~russian Измерение времени
//!
//! \~english \section PITimeMeasurer_sec0 Usage //! \~english \section PITimeMeasurer_sec0 Usage
//! \~russian \section PITimeMeasurer_sec0 Использование //! \~russian \section PITimeMeasurer_sec0 Использование
//! \~english //! \~english
@@ -85,6 +96,7 @@
//! Эти методы возвращают нано, микро, милли и секунды с приставками //! Эти методы возвращают нано, микро, милли и секунды с приставками
//! "n", "u", "m" и "s". //! "n", "u", "m" и "s".
//! //!
//! \}

View File

@@ -30,10 +30,6 @@
#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:
@@ -191,10 +187,6 @@ 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,6 +21,7 @@
/** \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,7 +27,6 @@
#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"
@@ -201,9 +200,6 @@ 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);
@@ -248,104 +244,104 @@ public:
pivCustom /** Custom */ = 0xFF pivCustom /** Custom */ = 0xFF
}; };
//! Construct \a pivInvalid %PIVariant //! Empty constructor, \a type() will be set to \a Invalid
PIVariant(); PIVariant();
PIVariant(const PIVariant & v); PIVariant(const PIVariant & v);
PIVariant(PIVariant && v); PIVariant(PIVariant && v);
//! Constructs %PIVariant from string //! Constructs variant from string
PIVariant(const char * v) {initType(PIString(v));} PIVariant(const char * v) {initType(PIString(v));}
//! Constructs %PIVariant from boolean //! Constructs variant from boolean
PIVariant(const bool v) {initType(v);} PIVariant(const bool v) {initType(v);}
//! Constructs %PIVariant from char //! Constructs variant from char
PIVariant(const char v) {initType(v);} PIVariant(const char v) {initType(v);}
//! Constructs %PIVariant from integer //! Constructs variant from integer
PIVariant(const uchar v) {initType(v);} PIVariant(const uchar v) {initType(v);}
//! Constructs %PIVariant from integer //! Constructs variant from integer
PIVariant(const short v) {initType(v);} PIVariant(const short v) {initType(v);}
//! Constructs %PIVariant from integer //! Constructs variant from integer
PIVariant(const ushort v) {initType(v);} PIVariant(const ushort v) {initType(v);}
//! Constructs %PIVariant from integer //! Constructs variant from integer
PIVariant(const int & v) {initType(v);} PIVariant(const int & v) {initType(v);}
//! Constructs %PIVariant from integer //! Constructs variant from integer
PIVariant(const uint & v) {initType(v);} PIVariant(const uint & v) {initType(v);}
//! Constructs %PIVariant from integer //! Constructs variant from integer
PIVariant(const llong & v) {initType(v);} PIVariant(const llong & v) {initType(v);}
//! Constructs %PIVariant from integer //! Constructs variant from integer
PIVariant(const ullong & v) {initType(v);} PIVariant(const ullong & v) {initType(v);}
//! Constructs %PIVariant from float //! Constructs variant from float
PIVariant(const float & v) {initType(v);} PIVariant(const float & v) {initType(v);}
//! Constructs %PIVariant from double //! Constructs variant from double
PIVariant(const double & v) {initType(v);} PIVariant(const double & v) {initType(v);}
//! Constructs %PIVariant from long double //! Constructs variant from long double
PIVariant(const ldouble & v) {initType(v);} PIVariant(const ldouble & v) {initType(v);}
//! Constructs %PIVariant from bit array //! Constructs variant from bit array
PIVariant(const PIBitArray & v) {initType(v);} PIVariant(const PIBitArray & v) {initType(v);}
//! Constructs %PIVariant from byte array //! Constructs variant from byte array
PIVariant(const PIByteArray & v) {initType(v);} PIVariant(const PIByteArray & v) {initType(v);}
//! Constructs %PIVariant from string //! Constructs variant from string
PIVariant(const PIString & v) {initType(v);} PIVariant(const PIString & v) {initType(v);}
//! Constructs %PIVariant from strings list //! Constructs variant from strings list
PIVariant(const PIStringList & v) {initType(v);} PIVariant(const PIStringList & v) {initType(v);}
//! Constructs %PIVariant from time //! Constructs variant from time
PIVariant(const PITime & v) {initType(v);} PIVariant(const PITime & v) {initType(v);}
//! Constructs %PIVariant from date //! Constructs variant from date
PIVariant(const PIDate & v) {initType(v);} PIVariant(const PIDate & v) {initType(v);}
//! Constructs %PIVariant from date and time //! Constructs variant from date and time
PIVariant(const PIDateTime & v) {initType(v);} PIVariant(const PIDateTime & v) {initType(v);}
//! Constructs %PIVariant from system time //! Constructs variant from system time
PIVariant(const PISystemTime & v) {initType(v);} PIVariant(const PISystemTime & v) {initType(v);}
//! Constructs %PIVariant from enum //! Constructs variant from enum
PIVariant(const PIVariantTypes::Enum & v) {initType(v);} PIVariant(const PIVariantTypes::Enum & v) {initType(v);}
//! Constructs %PIVariant from file //! Constructs variant from file
PIVariant(const PIVariantTypes::File & v) {initType(v);} PIVariant(const PIVariantTypes::File & v) {initType(v);}
//! Constructs %PIVariant from dir //! Constructs variant from dir
PIVariant(const PIVariantTypes::Dir & v) {initType(v);} PIVariant(const PIVariantTypes::Dir & v) {initType(v);}
//! Constructs %PIVariant from color //! Constructs variant from color
PIVariant(const PIVariantTypes::Color & v) {initType(v);} PIVariant(const PIVariantTypes::Color & v) {initType(v);}
//! Constructs %PIVariant from IODevice //! Constructs variant from IODevice
PIVariant(const PIVariantTypes::IODevice & v) {initType(v);} PIVariant(const PIVariantTypes::IODevice & v) {initType(v);}
//! Constructs %PIVariant from point //! Constructs variant from point
PIVariant(const PIPointd & v) {initType(v);} PIVariant(const PIPointd & v) {initType(v);}
//! Constructs %PIVariant from rect //! Constructs variant from rect
PIVariant(const PIRectd & v) {initType(v);} PIVariant(const PIRectd & v) {initType(v);}
//! Constructs %PIVariant from line //! Constructs variant from line
PIVariant(const PILined & v) {initType(v);} PIVariant(const PILined & v) {initType(v);}
//! Constructs %PIVariant from MathVector //! Constructs variant from MathVector
PIVariant(const PIMathVectord & v) {initType(v);} PIVariant(const PIMathVectord & v) {initType(v);}
//! Constructs %PIVariant from MathMatrix //! Constructs variant from MathMatrix
PIVariant(const PIMathMatrixd & v) {initType(v);} PIVariant(const PIMathMatrixd & v) {initType(v);}
@@ -805,10 +801,7 @@ 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(); s << "PIVariant(" << v.typeName() << ", " << v.toString() << ")";
if (v.isValid())
s << ", " << v.toString();
s << ")";
s.restoreControl(); return s; s.restoreControl(); return s;
} }

View File

@@ -1,9 +1,6 @@
/*! \file piauth.h /*! \file piauth.h
* \ingroup Crypt * \brief PIP Authentication API
* \~\brief */
* \~english Authentication API
* \~russian API аутентификации
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PIP Authentication API PIP Authentication API

View File

@@ -1,9 +1,6 @@
/*! \file picrypt.h /*! \file picrypt.h
* \ingroup Crypt * \brief Cryptographic class using lib Sodium
* \~\brief */
* \~english Cryptographic using libsodium
* \~russian Шифрование с помощью libsodium
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Cryptographic class using lib Sodium Cryptographic class using lib Sodium

View File

@@ -16,37 +16,6 @@
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 Crypt
//! \~\brief
//! \~english Cryptographic support
//! \~russian Поддержка шифрования
//!
//! \~\details
//! \~english \section cmake_module_Crypt Building with CMake
//! \~russian \section cmake_module_Crypt Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP::Crypt)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! These files provides basic and symmetric cryptographic support via [libsodium](https://doc.libsodium.org/).
//!
//! \~russian
//! Эти файлы обеспечивают базовое и симметричное шифрование с помощью [libsodium](https://doc.libsodium.org/).
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PICRYPTMODULE_H #ifndef PICRYPTMODULE_H
#define PICRYPTMODULE_H #define PICRYPTMODULE_H

View File

@@ -1,9 +1,6 @@
/*! \file piellipsoidmodel.h /*! \file piellipsoidmodel.h
* \ingroup Geo * \brief Contains geo ellipsoid models
* \~\brief */
* \~english Geographical ellipsoid Earth models
* \~russian Географическая эллипсоидная модель Земли
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Contains geo ellipsoid models Contains geo ellipsoid models

View File

@@ -16,39 +16,6 @@
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 Geo
//! \~\brief
//! \~english Geographical position and Earth models
//! \~russian Географическая позиция и модели Земли
//!
//! \~\details
//! \~english \section cmake_module_Geo Building with CMake
//! \~russian \section cmake_module_Geo Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! These files provides geographical position, several Earth models and converting
//! from one model to another.
//!
//! \~russian
//! Эти файлы обеспечивают географическую позицию, несколько моделей Земли и
//! преобразования из одной модели в другую.
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PIGEOMODULE_H #ifndef PIGEOMODULE_H
#define PIGEOMODULE_H #define PIGEOMODULE_H

View File

@@ -1,9 +1,6 @@
/*! \file pigeoposition.h /*! \file pigeoposition.h
* \ingroup Geo * \brief Class for geo position storage and conversions
* \~\brief */
* \~english Class for geo position storage and conversions
* \~russian Класс для хранения географической позиции и преобразований
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for geo position storage and conversions Class for geo position storage and conversions

View File

@@ -16,37 +16,6 @@
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 Introspection
//! \~\brief
//! \~english Internal PIP introspection
//! \~russian Внутренняя интроспекция PIP
//!
//! \~\details
//! \~english \section cmake_module_Introspection Building with CMake
//! \~russian \section cmake_module_Introspection Сборка с использованием CMake
//!
//! \~\code
//! find_package(PIP REQUIRED)
//! target_link_libraries([target] PIP)
//! \endcode
//!
//! \~english \par Common
//! \~russian \par Общее
//!
//! \~english
//! These files provides gathering and sending internal PIP statistics.
//!
//! \~russian
//! Эти файлы обеспечивают сбор и отправку внутренних статистик PIP.
//!
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//!
#ifndef PIINTROSPECTION_BASE_H #ifndef PIINTROSPECTION_BASE_H
#define PIINTROSPECTION_BASE_H #define PIINTROSPECTION_BASE_H

View File

@@ -17,49 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#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();
@@ -71,33 +35,33 @@ PIIntrospectionContainersInterface::~PIIntrospectionContainersInterface() {
} }
void PIIntrospectionContainersInterface::containerNew(const PIIntrospectionContainersType & ti, uint isz) { void PIIntrospectionContainersInterface::containerNew(const char * tn, uint isz) {
p->containerNew(ti, isz); p->containerNew(tn, isz);
} }
void PIIntrospectionContainersInterface::containerDelete(const PIIntrospectionContainersType & ti) { void PIIntrospectionContainersInterface::containerDelete(const char * tn) {
p->containerDelete(ti); p->containerDelete(tn);
} }
void PIIntrospectionContainersInterface::containerAlloc(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainersInterface::containerAlloc(const char * tn, ullong cnt) {
p->containerAlloc(ti, cnt); p->containerAlloc(tn, cnt);
} }
void PIIntrospectionContainersInterface::containerFree(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainersInterface::containerFree(const char * tn, ullong cnt) {
p->containerFree(ti, cnt); p->containerFree(tn, cnt);
} }
void PIIntrospectionContainersInterface::containerUsed(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainersInterface::containerUsed(const char * tn, ullong cnt) {
p->containerUsed(ti, cnt); p->containerUsed(tn, cnt);
} }
void PIIntrospectionContainersInterface::containerUnused(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainersInterface::containerUnused(const char * tn, ullong cnt) {
p->containerUnused(ti, cnt); p->containerUnused(tn, cnt);
} }
#endif #endif

View File

@@ -20,48 +20,27 @@
#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;
template<typename T> #define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance())//(PIIntrospectionContainersInterface::instance())
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;
}
};
#define PIINTROSPECTION_CONTAINERS (PIIntrospectionContainersInterface::instance()) #ifdef CC_GCC
# include <typeinfo>
# define _PIIS_TYPENAME_(t) typeid(t).name()
#else
# define _PIIS_TYPENAME_(t) ""
#endif
# define PIINTROSPECTION_CONTAINER_NEW(t, isz) PIINTROSPECTION_CONTAINERS->containerNew (PIIntrospectionContainersTypeInfo<t>::get(), isz); # define PIINTROSPECTION_CONTAINER_NEW(t, isz) PIINTROSPECTION_CONTAINERS->containerNew (_PIIS_TYPENAME_(t), isz);
# define PIINTROSPECTION_CONTAINER_DELETE(t) PIINTROSPECTION_CONTAINERS->containerDelete(PIIntrospectionContainersTypeInfo<t>::get()); # define PIINTROSPECTION_CONTAINER_DELETE(t) PIINTROSPECTION_CONTAINERS->containerDelete(_PIIS_TYPENAME_(t));
# define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt) PIINTROSPECTION_CONTAINERS->containerAlloc (PIIntrospectionContainersTypeInfo<t>::get(), cnt); # define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt) PIINTROSPECTION_CONTAINERS->containerAlloc (_PIIS_TYPENAME_(t), cnt);
# define PIINTROSPECTION_CONTAINER_FREE(t, cnt) PIINTROSPECTION_CONTAINERS->containerFree (PIIntrospectionContainersTypeInfo<t>::get(), cnt); # define PIINTROSPECTION_CONTAINER_FREE(t, cnt) PIINTROSPECTION_CONTAINERS->containerFree (_PIIS_TYPENAME_(t), cnt);
# define PIINTROSPECTION_CONTAINER_USED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUsed (PIIntrospectionContainersTypeInfo<t>::get(), cnt); # define PIINTROSPECTION_CONTAINER_USED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUsed (_PIIS_TYPENAME_(t), cnt);
# define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUnused(PIIntrospectionContainersTypeInfo<t>::get(), cnt); # define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) PIINTROSPECTION_CONTAINERS->containerUnused(_PIIS_TYPENAME_(t), cnt);
class PIP_EXPORT PIIntrospectionContainersInterface { class PIP_EXPORT PIIntrospectionContainersInterface {
@@ -70,12 +49,12 @@ class PIP_EXPORT PIIntrospectionContainersInterface {
public: public:
__PIINTROSPECTION_SINGLETON_H__(Containers) __PIINTROSPECTION_SINGLETON_H__(Containers)
void containerNew (const PIIntrospectionContainersType & ti, uint isz); void containerNew (const char * tn, uint isz);
void containerDelete(const PIIntrospectionContainersType & ti); void containerDelete(const char * tn);
void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt); void containerAlloc (const char * tn, ullong cnt);
void containerFree (const PIIntrospectionContainersType & ti, ullong cnt); void containerFree (const char * tn, ullong cnt);
void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt); void containerUsed (const char * tn, ullong cnt);
void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt); void containerUnused(const char * tn, ullong cnt);
PIIntrospectionContainers * p; PIIntrospectionContainers * p;
private: private:

View File

@@ -18,23 +18,44 @@
*/ */
#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::_Type::_Type() {
id = count = item_size = 0u;
allocated = used = 0U;
}
PIIntrospectionContainers::PIIntrospectionContainers() { PIIntrospectionContainers::PIIntrospectionContainers() {
//printf("PIIntrospectionContainers %p\n", this); //printf("PIIntrospectionContainers %p\n", this);
} }
void PIIntrospectionContainers::containerNew(const PIIntrospectionContainersType & ti, uint isz) { void PIIntrospectionContainers::containerNew(const char * tn, uint isz) {
PISpinlockLocker _ml(mutex); uint id = typeID(tn);
PIMutexLocker _ml(mutex);
//printf("containerNew lock\n"); //printf("containerNew lock\n");
PIIntrospectionContainersType & t(types[ti.id]); std::string & n(typenames[id]);
_Type & d(data[ti.id]); _Type & d(data[id]);
if (!t.inited) { if (n.empty()) {
t = ti; n = tn;
d.id = ti.id; d.id = id;
d.item_size = isz; d.item_size = isz;
} }
d.count++; d.count++;
@@ -42,41 +63,49 @@ void PIIntrospectionContainers::containerNew(const PIIntrospectionContainersType
} }
void PIIntrospectionContainers::containerDelete(const PIIntrospectionContainersType & ti) { void PIIntrospectionContainers::containerDelete(const char * tn) {
PISpinlockLocker _ml(mutex); PIMutexLocker _ml(mutex);
data[ti.id].count--; data[typeID(tn)].count--;
} }
void PIIntrospectionContainers::containerAlloc(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainers::containerAlloc(const char * tn, ullong cnt) {
//printf(" alloc %s %d\n", tn, cnt); //printf(" alloc %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PISpinlockLocker _ml(mutex); PIMutexLocker _ml(mutex);
data[ti.id].allocated += cnt; data[typeID(tn)].allocated += cnt;
} }
void PIIntrospectionContainers::containerFree(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainers::containerFree(const char * tn, ullong cnt) {
//printf(" free %s %d\n", tn, cnt); //printf(" free %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PISpinlockLocker _ml(mutex); PIMutexLocker _ml(mutex);
data[ti.id].allocated -= cnt; data[typeID(tn)].allocated -= cnt;
} }
void PIIntrospectionContainers::containerUsed(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainers::containerUsed(const char * tn, ullong cnt) {
//printf(" used %s %d\n", tn, cnt); //printf(" used %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PISpinlockLocker _ml(mutex); PIMutexLocker _ml(mutex);
data[ti.id].used += cnt; data[typeID(tn)].used += cnt;
} }
void PIIntrospectionContainers::containerUnused(const PIIntrospectionContainersType & ti, ullong cnt) { void PIIntrospectionContainers::containerUnused(const char * tn, ullong cnt) {
//printf("unused %s %d\n", tn, cnt); //printf("unused %s %d\n", tn, cnt);
if (cnt == 0) return; if (cnt == 0) return;
PISpinlockLocker _ml(mutex); PIMutexLocker _ml(mutex);
data[ti.id].used -= cnt; data[typeID(tn)].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));
} }
@@ -84,15 +113,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, PIIntrospectionContainersType> t = types; std::map<uint, std::string> t = typenames;
mutex.unlock(); mutex.unlock();
ret.reserve(t.size()); ret.reserve(t.size());
for (typename std::map<uint, PIIntrospectionContainersType>::const_iterator i = t.begin(); i != t.end(); ++i) { for (typename std::map<uint, std::string>::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 = PIStringAscii(i->second.demangled); ti.name = demangle(i->second.c_str());
} }
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 "pispinlock.h" #include "pimutex.h"
#include <map> #include <map>
#include <string> #include <string>
#include "picrc.h" #include "picrc.h"
@@ -32,37 +32,35 @@ public:
struct TypeInfo; struct TypeInfo;
void containerNew (const PIIntrospectionContainersType & ti, uint isz); void containerNew (const char * tn, uint isz);
void containerDelete(const PIIntrospectionContainersType & ti); void containerDelete(const char * tn);
void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt); void containerAlloc (const char * tn, ullong cnt);
void containerFree (const PIIntrospectionContainersType & ti, ullong cnt); void containerFree (const char * tn, ullong cnt);
void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt); void containerUsed (const char * tn, ullong cnt);
void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt); void containerUnused(const char * tn, ullong cnt);
uint typeID(const char * tn);
PIVector<TypeInfo> getInfo() const; PIVector<TypeInfo> getInfo() const;
#pragma pack(push, 1) #pragma pack(push, 1)
struct PIP_EXPORT _Type { struct PIP_EXPORT _Type {
uint id = 0u; _Type();
uint count = 0u; uint id;
uint item_size = 0u; uint count;
ullong allocated = 0u; uint item_size;
ullong used = 0u; ullong allocated;
ullong used;
}; };
#pragma pack(pop) #pragma pack(pop)
struct PIP_EXPORT TypeInfo: _Type { struct PIP_EXPORT TypeInfo: _Type {
ullong allocated_bytes = 0u;
ullong used_bytes = 0u;
PIString name; PIString name;
PIString item_size_str;
PIString allocated_str;
PIString used_str;
}; };
std::map<uint, _Type> data; std::map<uint, _Type> data;
std::map<uint, PIIntrospectionContainersType> types; std::map<uint, std::string> typenames;
mutable PISpinlock mutex; mutable PIMutex mutex;
}; };
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v); PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v);

View File

@@ -1,9 +1,3 @@
/*! \file piintrospection_server.h
* \ingroup Introspection
* \~\brief
* \~english Introspection server
* \~russian Сервер интроспекции
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Introspection module Introspection module
@@ -26,24 +20,15 @@
#ifndef PIINTROSPECTION_SERVER_H #ifndef PIINTROSPECTION_SERVER_H
#define PIINTROSPECTION_SERVER_H #define PIINTROSPECTION_SERVER_H
#ifdef DOXYGEN #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
//! \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)
#include "pipeer.h" #include "pipeer.h"
class PIIntrospectionServer; class PIIntrospectionServer;
class PISystemMonitor; class PISystemMonitor;
# define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance()) # define PIINTROSPECTION_SERVER (PIIntrospectionServer::instance())
# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name); # define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
class PIP_EXPORT PIIntrospectionServer: public PIPeer { class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer) PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer)
@@ -68,10 +53,8 @@ private:
}; };
# else #else
# 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 char * s) { void PIBinaryLog::propertyChanged(const PIString &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

@@ -1,9 +1,6 @@
/*! \file pibinarylog.h /*! \file pibinarylog.h
* \ingroup IO * \brief Binary log
* \~\brief */
* \~english Binary log
* \~russian Бинарный лог
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for write binary data to logfile, and read or playback this data Class for write binary data to logfile, and read or playback this data
@@ -31,7 +28,7 @@
class PIP_EXPORT PIBinaryLog: public PIIODevice class PIP_EXPORT PIBinaryLog: public PIIODevice
{ {
PIIODEVICE(PIBinaryLog, "binlog") PIIODEVICE(PIBinaryLog)
public: public:
explicit PIBinaryLog(); explicit PIBinaryLog();
virtual ~PIBinaryLog(); virtual ~PIBinaryLog();
@@ -288,6 +285,7 @@ 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;
@@ -296,7 +294,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 char * s); void propertyChanged(const PIString &);
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

@@ -1,9 +1,6 @@
/*! \file pican.h /*! \file pican.h
* \ingroup IO * \brief CAN device
* \~\brief */
* \~english CAN device
* \~russian Устройство CAN
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
CAN CAN
@@ -31,7 +28,7 @@
class PIP_EXPORT PICAN: public PIIODevice class PIP_EXPORT PICAN: public PIIODevice
{ {
PIIODEVICE(PICAN, "can") PIIODEVICE(PICAN)
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,6 +42,7 @@ 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

@@ -1,9 +1,6 @@
/*! \file piconfig.h /*! \file piconfig.h
* \ingroup IO * \brief Configuration parser and writer
* \~\brief */
* \~english Configuration files parser and writer
* \~russian Разбор и запись конфигурационных файлов
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Configuration parser and writer Configuration parser and writer
@@ -303,7 +300,8 @@ public:
PIStringList toStringList() const {return _value.split("%|%");} PIStringList toStringList() const {return _value.split("%|%");}
private: private:
static bool compare(PIConfig::Entry * const & f, PIConfig::Entry * const & s) {return f->_line < s->_line;} typedef PIConfig::Entry * EntryPtr;
static int compare(const EntryPtr * f, const EntryPtr * s) {return (*f)->_line == (*s)->_line ? 0 : (*f)->_line < (*s)->_line ? -1 : 1;}
bool entryExists(const Entry * e, const PIString & name) const; bool entryExists(const Entry * e, const PIString & name) const;
void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;} void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;}
void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;} void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;}
@@ -332,7 +330,7 @@ public:
bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Read configuration string "string" in mode "mode" //! Read configuration string "string" in mode "mode"
bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);\
bool isOpened() const; bool isOpened() const;

View File

@@ -45,16 +45,17 @@ extern "C" {
# include <sys/stat.h> # include <sys/stat.h>
#endif #endif
/*! \class PIDir
//! \class PIDir pidir.h * \brief Local directory
//! \details *
//! \~english \section PIDir_sec0 Synopsis * \section PIDir_sec0 Synopsis
//! \~russian \section PIDir_sec0 Краткий обзор * This class provide access to local file. You can manipulate
//! \~english * binary content or use this class as text stream. To binary
//! This class provide access to local directory. * access there are function \a read(), \a write(), and many
//! * \a writeBinary() functions. For write variables to file in
//! \~russian * their text representation threr are many "<<" operators.
//! *
*/
PIDir::PIDir(const PIString & dir) { PIDir::PIDir(const PIString & dir) {
@@ -114,15 +115,6 @@ 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()) {
@@ -244,35 +236,13 @@ 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) { int 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());
} }
#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;
@@ -352,18 +322,6 @@ 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

@@ -1,9 +1,6 @@
/*! \file pidir.h /*! \file pidir.h
* \ingroup IO * \brief Local directory
* \~\brief */
* \~english Local directory
* \~russian Локальная директория
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Directory Directory
@@ -29,146 +26,93 @@
#include "pifile.h" #include "pifile.h"
//! \ingroup IO
//! \~\brief
//! \~english Local directory.
//! \~russian Локальная директория.
class PIP_EXPORT PIDir class PIP_EXPORT PIDir
{ {
public: public:
//! \~english Constructs directory with path "dir" //! Constructs directory with path "path"
//! \~russian Создает директорию с путём "dir"
PIDir(const PIString & dir = PIString()); PIDir(const PIString & dir = PIString());
//! \~english Constructs directory with "file" directory path //! Constructs directory with "file" directory path "path"
//! \~russian Создает директорию с путём директории файла "file"
PIDir(const PIFile & file); PIDir(const PIFile & file);
//! \~english Returns if this directory exists //! Returns if this directory is exists
//! \~russian Возвращает существует ли эта директория
bool isExists() const {return PIDir::isExists(path());} bool isExists() const {return PIDir::isExists(path());}
//! \~english Returns if path of this directory is absolute //! Returns if path of this directory is absolute
//! \~russian Возвращает абсолютный ли путь у директории
bool isAbsolute() const; bool isAbsolute() const;
//! \~english Returns if path of this directory is relative //! Returns if path of this directory is relative
//! \~russian Возвращает относительный ли путь у директории
bool isRelative() const {return !isAbsolute();} bool isRelative() const {return !isAbsolute();}
//! \~english Returns path of current reading directory. This path valid only while \a allEntries() functions //! Returns path of current reading directory. This path
//! \~russian Возвращает путь текущей директории чтения. Этот путь действителен только во время выполнения метода \a allEntries() //! valid only while \a allEntries functions
const PIString & scanDir() const {return scan_;} const PIString & scanDir() const {return scan_;}
//! \~english Returns path of this directory //! Returns path of this directory
//! \~russian Возвращает путь директории
PIString path() const; PIString path() const;
//! \~english Returns absolute path of this directory //! Returns absolute path of this directory
//! \~russian Возвращает абсолютный путь директории
PIString absolutePath() const; PIString absolutePath() const;
//! \~english Simplify path of this directory /** \brief Simplify path of this directory
//! \~russian Упрощает путь директории * \details This function remove repeatedly separators and
* resolve ".." in path. E.g. "/home/.//peri4/src/../.." will
* become "/home" \n This function returns reference to this %PIDir */
PIDir & cleanPath(); PIDir & cleanPath();
//! \~english Returns %PIDir with simplified path of this directory //! 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;}
//! \~english Returns relative to this directory path "path" //! Returns relative to this directory path "path"
//! \~russian Возвращает путь "path" относительно этой директории
PIString relative(const PIString & path) const; PIString relative(const PIString & path) const;
//! \~english Set this directory path to simplified "path" //! Set this directory path to simplified "path"
//! \~russian Устанавливает путь директории упрощённым "path"
PIDir & setDir(const PIString & path); PIDir & setDir(const PIString & path);
//! \~english Set this directory path as current for application //! Set this directory path as current for application
//! \~russian Устанавливает путь директории текущим путём приложения
bool setCurrent() {return PIDir::setCurrent(path());} bool setCurrent() {return PIDir::setCurrent(path());}
//! \~english Returns this directory content /** \brief Returns this directory content
//! \~russian Возвращает содержимое этой директории * \details 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! */
PIVector<PIFile::FileInfo> entries(); PIVector<PIFile::FileInfo> entries();
//! \~english Returns this directory content recursively /** \brief Returns all this directory content
//! \~russian Возвращает содержимое этой директории рекурсивно * \details 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 */
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:
@@ -186,9 +130,6 @@ 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,7 +21,6 @@
#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>
@@ -920,11 +919,10 @@ bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
} }
void PIEthernet::propertyChanged(const char * name) { void PIEthernet::propertyChanged(const PIString & name) {
PIConstChars pn(name); if (name.endsWith("Timeout")) applyTimeouts();
if (pn.endsWith("Timeout")) applyTimeouts(); if (name == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL());
if (pn == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL()); if (name == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL());
if (pn == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL());
} }
@@ -1003,23 +1001,24 @@ 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);
PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO)); pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO)));
if (!pAdapterInfo) { if (pAdapterInfo == 0) {
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 = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, ulOutBufLen); pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen));
if (!pAdapterInfo) { if (pAdapterInfo == 0) {
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) {
PIP_ADAPTER_INFO pAdapter = pAdapterInfo; pAdapter = pAdapterInfo;
while (pAdapter) { while (pAdapter) {
ci.name = PIString(pAdapter->AdapterName); ci.name = PIString(pAdapter->AdapterName);
ci.index = pAdapter->Index; ci.index = pAdapter->Index;
@@ -1032,8 +1031,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 = PIStringAscii(as->IpAddress.String); ci.address = PIString(as->IpAddress.String);
ci.netmask = PIStringAscii(as->IpMask.String); ci.netmask = PIString(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;
@@ -1054,7 +1053,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
@@ -1214,16 +1213,10 @@ int PIEthernet::ethErrorCore() {
PIString PIEthernet::ethErrorString() { PIString PIEthernet::ethErrorString() {
#ifdef WINDOWS #ifdef WINDOWS
char * msg = nullptr; char * msg;
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);
PIString ret = PIStringAscii("code ") + PIString::fromNumber(err) + PIStringAscii(" - "); return "code " + PIString::fromNumber(err) + " - " + PIString(msg);
if (msg) {
ret += PIString::fromSystem(msg).trim();
LocalFree(msg);
} else
ret += '?';
return ret;
#else #else
return errorString(); return errorString();
#endif #endif

View File

@@ -1,9 +1,6 @@
/*! \file piethernet.h /*! \file piethernet.h
* \ingroup IO * \brief Ethernet device
* \~\brief */
* \~english Ethernet device
* \~russian Устройство Ethernet
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ethernet, UDP/TCP Broadcast/Multicast Ethernet, UDP/TCP Broadcast/Multicast
@@ -38,7 +35,7 @@ class
class PIP_EXPORT PIEthernet: public PIIODevice class PIP_EXPORT PIEthernet: public PIIODevice
{ {
PIIODEVICE(PIEthernet, "eth") PIIODEVICE(PIEthernet)
friend class PIPeer; friend class PIPeer;
public: public:
@@ -201,44 +198,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("parameters", (int)parameters_);} void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {setProperty(PIStringAscii("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("parameters").toInt()))[parameter];} bool isParameterSet(PIEthernet::Parameters parameter) const {return ((PIFlags<PIEthernet::Parameters>)(property(PIStringAscii("parameters")).toInt()))[parameter];}
//! Returns parameters //! Returns parameters
PIFlags<PIEthernet::Parameters> parameters() const {return (PIFlags<PIEthernet::Parameters>)(property("parameters").toInt());} PIFlags<PIEthernet::Parameters> parameters() const {return (PIFlags<PIEthernet::Parameters>)(property(PIStringAscii("parameters")).toInt());}
//! Returns %PIEthernet type //! Returns %PIEthernet type
Type type() const {return (Type)(property("type").toInt());} Type type() const {return (Type)(property(PIStringAscii("type")).toInt());}
//! Returns read timeout //! Returns read timeout
double readTimeout() const {return property("readTimeout").toDouble();} double readTimeout() const {return property(PIStringAscii("readTimeout")).toDouble();}
//! Returns write timeout //! Returns write timeout
double writeTimeout() const {return property("writeTimeout").toDouble();} double writeTimeout() const {return property(PIStringAscii("writeTimeout")).toDouble();}
//! Set timeout for read //! Set timeout for read
void setReadTimeout(double ms) {setProperty("readTimeout", ms);} void setReadTimeout(double ms) {setProperty(PIStringAscii("readTimeout"), ms);}
//! Set timeout for write //! Set timeout for write
void setWriteTimeout(double ms) {setProperty("writeTimeout", ms);} void setWriteTimeout(double ms) {setProperty(PIStringAscii("writeTimeout"), ms);}
//! Returns TTL (Time To Live) //! Returns TTL (Time To Live)
int TTL() const {return property("TTL").toInt();} int TTL() const {return property(PIStringAscii("TTL")).toInt();}
//! Returns multicast TTL (Time To Live) //! Returns multicast TTL (Time To Live)
int multicastTTL() const {return property("MulticastTTL").toInt();} int multicastTTL() const {return property(PIStringAscii("MulticastTTL")).toInt();}
//! Set TTL (Time To Live), default is 64 //! Set TTL (Time To Live), default is 64
void setTTL(int ttl) {setProperty("TTL", ttl);} void setTTL(int ttl) {setProperty(PIStringAscii("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("MulticastTTL", ttl);} void setMulticastTTL(int ttl) {setProperty(PIStringAscii("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,8 +459,9 @@ public:
protected: protected:
explicit PIEthernet(int sock, PIString ip_port); explicit PIEthernet(int sock, PIString ip_port);
void propertyChanged(const char * name); void propertyChanged(const PIString & 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;
@@ -498,7 +496,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("type", (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}} void setType(Type t, bool reopen = true) {setProperty(PIStringAscii("type"), (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}}
static int ethErrorCore(); static int ethErrorCore();
static PIString ethErrorString(); static PIString ethErrorString();

View File

@@ -69,44 +69,25 @@
# define _stat_link_ lstat64 # define _stat_link_ lstat64
#endif #endif
/*! \class PIFile
//! \class PIFile pifile.h * \brief Local file
//! \details *
//! \~english \section PIFile_sec0 Synopsis * \section PIFile_sec0 Synopsis
//! \~russian \section PIFile_sec0 Краткий обзор * This class provide access to local file. You can manipulate
//! \~english * binary content or use this class as text stream. To binary
//! * access there are function \a read(), \a write(), and many
//! This class provide access to local file. You can manipulate * \a writeBinary() functions. For write variables to file in
//! binary content or use this class as text stream. To binary * their text representation threr are many "<<" operators.
//! access there are function \a read(), \a write(), and many *
//! \a writeBinary() functions. For write and read variables to file in * \section PIFile_sec1 Position
//! their text representation there are many "<<" and ">>" operators. * Each opened file has a read/write position - logical position
//! * in the file content you read from or you write to. You can
//! \~russian * 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.
//! \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)
@@ -633,7 +614,7 @@ int PIFile::writeDevice(const void * data, int max_size) {
PIFile &PIFile::operator <<(const PIString & v) { PIFile &PIFile::operator <<(const PIString & v) {
if (canWrite() && v.isNotEmpty() && PRIVATE->fd != 0) if (canWrite() && PRIVATE->fd != 0)
*this << v.toCharset(defaultCharset()); *this << v.toCharset(defaultCharset());
return *this; return *this;
} }

View File

@@ -1,9 +1,6 @@
/*! \file pifile.h /*! \file pifile.h
* \ingroup IO * \brief Local file
* \~\brief */
* \~english Local file
* \~russian Локальный файл
*/
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
File File
@@ -30,62 +27,30 @@
#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, "file") PIIODEVICE(PIFile)
public: public:
//! \~english Constructs file with empty path //! Constructs an empty file
//! \~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 /*! \~english File \~russian Файл */ = 0x01, File = 0x01,
Dir /*! \~english Directory \~russian Директория */ = 0x02, Dir = 0x02,
Dot /*! \~english '.', current directory \~russian '.', текущая директория */ = 0x04, Dot = 0x04,
DotDot /*! \~english '..', parent directory \~russian '..', родительская директория */ = 0x08, DotDot = 0x08,
SymbolicLink /*! \~english Symbolic link \~russian Символическая ссылка */ = 0x10, SymbolicLink = 0x10,
Hidden /*! \~english Hidden \~russian Скрытый */ = 0x20 Hidden = 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 {
@@ -98,321 +63,175 @@ 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"
//! \~english Open temporary file with open mode "mode" //! If "path" is not empty then open file
//! \~russian Открывает временный файл с режимом открытия "mode" explicit PIFile(const PIString & path, DeviceMode mode = ReadWrite);
bool openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Immediate write all buffered data to disk
//! \~russian Немедленно записывает все буферизированные данные на диск //! Open temporary file with open mode "mode"
bool openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PIFile();
//! Immediate write all buffered data to disk
void flush(); void flush();
//! \~english Move read/write position to "position" //! Move read/write position to "position"
//! \~russian Перемещает позицию чтения/записи на "position"
void seek(llong position); void seek(llong position);
//! \~english Move read/write position to the begin of the file //! Move read/write position to the begin of the file
//! \~russian Перемещает позицию чтения/записи на начало файла
void seekToBegin(); void seekToBegin();
//! \~english Move read/write position to the end of the file //! Move read/write position to the end of the file
//! \~russian Перемещает позицию чтения/записи на конец файла
void seekToEnd(); void seekToEnd();
//! \~english Move read/write position to text line number "line" beginning //! Move read/write position to text line number "line"
//! \~russian Перемещает позицию чтения/записи на начало текстовой строки номер "line"
void seekToLine(llong line); void seekToLine(llong line);
//! \~english Skip "bytes" bytes (move position next to "bytes" bytes) //! Skip "bytes" bytes (move position next to "bytes" bytes)
//! \~russian Пропускает "bytes" байт (перемещает позицию на "bytes" байт вперёд)
void skip(llong bytes); void skip(llong bytes);
//! \~english Read one char and return it //! Read one char and return it
//! \~russian Читает один байт и возвращает его
char readChar(); char readChar();
//! \~english Read one text line and return it //! Read one text line and return it
//! \~russian Читает одну текстовую строку и возвращает её
PIString readLine(); PIString readLine();
//! \~english Read all file content to "data" and return readed bytes count. Position leaved unchanged //! Read all file content to "data" and return readed bytes count. Position leaved unchanged
//! \~russian Читает всё содержимое файла в "data" и возвращает количество прочитанных байт. Позиция остаётся неизменной
llong readAll(void * data); llong readAll(void * data);
//! \~english Read all file content to byte array and return it. Position leaved unchanged //! Read all file content to byte array and return it. Position leaved unchanged
//! \~russian Читает всё содержимое файла и возвращает его как массив байтов. Позиция остаётся неизменной
PIByteArray readAll(bool forceRead = false); PIByteArray readAll(bool forceRead = false);
//! \~english Set file path to "path" and reopen file if need //! Set file path to "path" and reopen file if need
//! \~russian Устанавливает путь файла на "path" и переоткрывает его при необходимости
void setPath(const PIString & path); void setPath(const PIString & path);
//! \~english Returns file size in bytes //! Returns file size
//! \~russian Возвращает размер файла в байтах
llong size() const; llong size() const;
//! \~english Returns read/write position //! Returns read/write position
//! \~russian Возвращает позицию чтения/записи
llong pos() const; llong pos() const;
//! \~english Returns if position is at the end of file //! Returns if position is at the end of file
//! \~russian Возвращает достигнут ли конец файла
bool isEnd() const; bool isEnd() const;
//! \~english Returns if file is empty //! Returns if file is empty
//! \~russian Возвращает пустой ли файл
bool isEmpty() const {return (size() <= 0);} bool isEmpty() const {return (size() <= 0);}
//! \~english Returns \a PIFile::FileInfo of current file //! Returns FileInfo of current file
//! \~russian Возвращает \a PIFile::FileInfo текущего файла
FileInfo fileInfo() const {return fileInfo(path());} FileInfo fileInfo() const {return fileInfo(path());}
//! \~english Returns float numbers write precision //! Returns float numbers write precision
//! \~russian Возвращает точность записи чисел с плавающей точкой
int precision() const {return prec_;} int precision() const {return prec_;}
//! \~english Set float numbers write precision to "prec_" digits //! 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();
//! \~english Write to file binary content of "v" //! 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);
@@ -420,56 +239,44 @@ 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);
//! \~english Returns if file with path "path" exists //! Returns if file with path "path" does exists
//! \~russian Возвращает существует ли файл с путём "path"
static bool isExists(const PIString & path); static bool isExists(const PIString & path);
//! \~english Remove file with path "path" and returns if remove successful //! Remove file with path "path" and returns if remove was successful
//! \~russian Удаляет файл с путём "path" и возвращает успешность операции
static bool remove(const PIString & path); static bool remove(const PIString & path);
//! \~english Rename file with path "from" to path "to" and returns if rename successful //! Rename file with path "from" to path "to" and returns if rename was successful
//! \~russian Переименовывает файл с путём "path" на "to" и возвращает успешность операции
static bool rename(const PIString & from, const PIString & to); static bool rename(const PIString & from, const PIString & to);
//! \~english Returns \a PIFile::FileInfo of file or dir with path "path" //! Returns 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);
//! \~english Apply "info" parameters to file or dir with path "path" //! 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);
//! \~english Apply "info" parameters to file or dir with path "info".path //! 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()
//! \~english Clear content of file //! \brief Clear content of file
//! \~russian Очищает содержимое файла
//! \fn void resize(llong new_size) //! \fn void resize(llong new_size)
//! \~english Resize file to "new_size" with null-byte fill //! \brief Resize file to "new_size" with "fill" filling
//! \~russian Изменяет размер файла на "new_size" с заполнением нулевыми байтами
//! \fn void resize(llong new_size, uchar fill) //! \fn void resize(llong new_size, uchar fill)
//! \~english Resize file to "new_size" with "fill" fill //! \brief Resize file to "new_size" with "fill" filling
//! \~russian Изменяет размер файла на "new_size" с заполнением байтами "fill"
//! \fn void remove() //! \fn void remove()
//! \~english Remove file //! \brief Remove file
//! \~russian Удаляет файл
//! \} //! \}
//! \ioparams //! \ioparams
@@ -479,6 +286,7 @@ 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;
@@ -500,10 +308,6 @@ 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) << ", "
@@ -515,17 +319,9 @@ 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

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