77 Commits

Author SHA1 Message Date
443eeed38b Merge pull request 'PIDeque optimize and bugfix' (#165) from deque2 into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/165
2022-08-23 10:30:05 +03:00
d1abfe5213 Merge pull request 'PIVector some optimize code' (#164) from vector into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/164
2022-08-22 20:18:08 +03:00
Бычков Андрей
29e34bdd60 cmake generate right project tree 2022-08-22 18:44:18 +03:00
Бычков Андрей
4635e9ba4f insert optimize 2022-08-22 17:47:45 +03:00
Бычков Андрей
49e553c551 PIDeque optimize and bugfix 2022-08-22 15:59:25 +03:00
1abcf06bf6 PIVector some optimize code 2022-08-16 22:20:04 +03:00
2550f76376 return move-assignment vector optimization 2022-08-16 20:26:42 +03:00
24da7aa644 doc core reference done 2022-08-15 19:35:49 +03:00
494faf862b some doc 2022-08-15 11:43:27 +03:00
67561636e5 return move-assignment dequeue optimization 2022-08-12 23:53:22 +03:00
Бычков Андрей
00f7a24d54 new caontainers functions
atWhere()
lastAtWhere()
contains(v)
filter(), map(), reduce(), forEach() indexed and reverse variants
fix PIDeque reverse for
fix insert with move of complex type potential segfault
2022-08-12 18:14:55 +03:00
Бычков Андрей
f07f814b08 platformio_pre.py 2022-08-11 11:40:49 +03:00
fed2c5991d version 3.0.0_rc 2022-08-10 23:44:26 +03:00
ed888324b2 override 2022-08-10 23:34:11 +03:00
79efd9e15d clang fix 2022-08-10 23:23:23 +03:00
Бычков Андрей
1acd29e474 platformio_pre.py fix for new cmake macros 2022-08-10 16:37:28 +03:00
Бычков Андрей
cd7af5e9b7 remove pimap.cpp 2022-08-10 15:14:47 +03:00
Бычков Андрей
adef5b6781 PIMap some doc 2022-08-09 15:54:53 +03:00
Бычков Андрей
2e9acdb1ba убрал установку лишних инклюдов 2022-08-09 12:31:41 +03:00
f0fee0d78f mispell 2022-08-08 21:09:47 +03:00
Бычков Андрей
60f4db61eb Merge branch 'master' of https://git.shs.tools/SHS/pip 2022-08-08 17:14:21 +03:00
Бычков Андрей
724a2dffcf picout and clean 2022-08-08 16:44:37 +03:00
616b384ad6 Merge pull request 'cmake refactoring' (#104) from cmake_refactor into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/104
2022-08-08 16:43:44 +03:00
8abc9777cc cmake refactoring 2022-08-08 15:41:01 +03:00
8551499a5e PICout refactoring, new SHSTKMacros 2022-08-07 22:07:26 +03:00
Бычков Андрей
1eaecb288f PIMapIterators refactoring
PIChunkStream some refactoring
2022-08-05 17:05:56 +03:00
Бычков Андрей
170a713357 PIMap new functions
PIByteArray checksum crc
some doc fixes
2022-08-04 20:20:08 +03:00
54cc6c55b2 pip_cmg and picodeinfo.h doc 2022-08-03 14:14:24 +03:00
e6aa3c34d4 Merge pull request 'added and fixed documentation for PIMath' (#101) from math-doc into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/101
2022-08-03 08:49:08 +03:00
bb40f69298 doc clean 2022-08-03 08:47:25 +03:00
af9a9e78b9 doc 2022-08-02 17:08:51 +03:00
af1264e42b doc fix 2022-08-02 08:25:34 +03:00
eb91fbfc45 doc stream 2022-08-01 21:23:21 +03:00
4ea5465637 PIString:: mid and cutMid does nothing if "start" < 0 2022-08-01 19:29:40 +03:00
ab7769dd5a map and set fix 2022-08-01 19:07:23 +03:00
b1e220e454 change PIIODevice read* and write* methods size to "ssize_t" 2022-08-01 18:52:30 +03:00
1b499530c5 add pisd deploy 2022-08-01 18:20:58 +03:00
b0d48caaad version 2.98.0
remove PIFile::readLine()
partially migrate PIConfig to text stream
add more "override"
2022-08-01 18:13:22 +03:00
Tamerlan Baziev
d6758a8562 исправление ошибок в документации 2022-08-01 12:29:42 +03:00
97734953dd PIString(int) constructors delete 2022-07-29 22:25:21 +03:00
bd98583116 PIString delete operator += int
PICout fix
2022-07-29 20:09:40 +03:00
Бычков Андрей
ddba8f401b PICout fix 2022-07-29 18:16:42 +03:00
Бычков Андрей
4725eb96d6 replace typedef function ptr by std::function
start PIMap refactoring
2022-07-29 15:49:36 +03:00
Бычков Андрей
38fd1b5dc4 PIPacketExtractor теперь работает 2022-07-28 17:02:33 +03:00
16c12a2756 Merge pull request 'Много исправлений и добавлений' (#100) from pip297 into master
Reviewed-on: https://git.shs.tools/SHS/pip/pulls/100
2022-07-28 14:47:24 +03:00
Бычков Андрей
1b09ad5c27 binlog fixes
PIBinaryStream doc
remove makePIPair
rename bytesAvailable
2022-07-28 14:46:58 +03:00
Бычков Андрей
00d06f71ba version 2022-07-27 15:46:53 +03:00
Бычков Андрей
3873f0b03b PIIODevice::bytesAvailible()
fix pistringlist pibinarystream write
pibinarystream::binaryStreamSize()
PIByteArray pibinarystream read with more size fix
pistring pibinarystream read optimization
fix bug in PIIOBinaryStream read and write if failed
workaround in PIIOString::readDevice
PISPI readDevice bug Fixed
2022-07-27 15:43:04 +03:00
6ae6e9a540 remove test 2022-07-27 10:11:55 +03:00
Tamerlan Baziev
bbc83128b0 added and fixed documentation for PIMath
- added documentation for PIPoint, PILine;
- fixed documentation for PIMathMatrix.
2022-07-26 18:13:28 +03:00
Бычков Андрей
d13e68c206 threadedRead now const uchar *
pipacketextractor Header mode now more flexible
fix splitTime mode
more refactoring
add virtual override to functions
remove piforeach
replace 0 to nullptr
iterate over pimap via iterators
replace CONNECTU to CONNECT# with compile time check
2022-07-26 17:18:08 +03:00
a4882dc054 complex macros with ; 2022-07-25 11:18:09 +03:00
Бычков Андрей
a1b9b7e1d6 убрал лишние ; 2022-07-25 10:32:42 +03:00
Бычков Андрей
e1b89aeca8 PIByteArray begin end indexOf map reduce forEach
PIVector and PIDeque small fixes
2022-07-25 10:07:48 +03:00
242abaaf59 version 2.95.0
get rid of PIByteArray subclassing from PIDeque<uchar>
2022-07-22 16:40:09 +03:00
Бычков Андрей
0116387fe3 PIDeque fix ssize_t
fix uninitialized variables
fix PIDeque prepend with std::initializer_list
2022-07-22 16:31:40 +03:00
Бычков Андрей
f5953a0ba7 PIBinaryLog joinBinLogsSerial
correct timestamp wite with split
2022-07-22 15:24:07 +03:00
Бычков Андрей
7aa407264f Merge remote-tracking branch 'remotes/origin/stream_interface'
PIBinaryLog
2022-07-22 15:22:33 +03:00
Бычков Андрей
59c7896577 Merge branch 'pip2' 2022-07-22 11:18:03 +03:00
Бычков Андрей
a69de63db0 PISerial windows custom speed 2022-07-20 15:41:47 +03:00
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
c7fffe1280 PIBinaryLog miss 2022-06-24 12:19:03 +03:00
1b04d7ecce version 2.93 ready to master
remove PIString << operators
2022-06-24 12:10:57 +03:00
b66272a68a version 2.92
pip_cmg
2022-06-09 17:59:04 +03:00
f67e3030b9 move to PIIOTextStream 2022-05-13 13:24:09 +03:00
1028233553 version 2.91.0, PITextStream works 2022-05-13 11:26:01 +03:00
ef8ffcd02f DEPRECATED[M], createMemoryBlock(), text stream ... 2022-05-11 20:55:51 +03:00
0897a8369f macros rename 2022-05-11 16:49:33 +03:00
fa19ad1093 text stream ... 2022-05-11 12:39:36 +03:00
8c6b3613b6 code brush 2022-05-11 10:48:36 +03:00
a23eb341e2 pitextstream starts 2022-05-10 18:47:11 +03:00
b2bc385397 PIByteArray works on binary stream 2022-05-10 15:23:18 +03:00
0f9e592273 start moving to binarystream 2022-05-10 12:26:05 +03:00
cf4f58ed95 ready to integrate 2022-05-09 23:57:47 +03:00
0243f588bc before error detection 2022-05-09 22:35:53 +03:00
af77974e91 first try 2022-05-09 14:21:38 +03:00
195 changed files with 8878 additions and 5026 deletions

View File

@@ -5,7 +5,7 @@
*/
#define lapi_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lcode_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lctype_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define ldebug_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define ldo_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define ldump_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lfunc_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lgc_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define llex_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lmem_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lobject_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lopcodes_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lparser_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lstate_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lstring_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define ltable_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define ltm_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lundump_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lvm_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -5,7 +5,7 @@
*/
#define lzio_c
#define LUA_CORE
#include "lprefix.h"

View File

@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip)
set(pip_MAJOR 2)
set(pip_MINOR 39)
set(pip_REVISION 0)
set(pip_SUFFIX )
set(pip_COMPANY SHS)
set(pip_DOMAIN org.SHS)
project(PIP)
set(PIP_MAJOR 3)
set(PIP_MINOR 1)
set(PIP_REVISION 0)
set(PIP_SUFFIX dev)
set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS)
set(GIT_CMAKE_DIR)
if (NOT DEFINED SHSTKPROJECT)
@@ -53,7 +53,7 @@ include(CheckFunctionExists)
include(PIPMacros)
include(SHSTKMacros)
shstk_begin_project(pip PIP)
shstk_begin_project(PIP)
set(_ICU_DEFAULT OFF)
if((NOT DEFINED WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT DEFINED APPLE))
@@ -96,7 +96,7 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
set(CRES)
file(GLOB_RECURSE CPPS "libs/${NAME}/*.cpp" "libs/${NAME}/*.c")
file(GLOB_RECURSE HS "libs/${NAME}/*.h")
file(GLOB_RECURSE PHS "libs/${NAME}/*_p.h")
file(GLOB_RECURSE PHS "libs/${NAME}/*_p.h" "libs/${NAME}/3rd/*.h")
file(GLOB_RECURSE RES "libs/${NAME}/*.conf")
if (NOT "x${PHS}" STREQUAL "x")
list(REMOVE_ITEM HS ${PHS})
@@ -105,9 +105,14 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
file(GLOB_RECURSE ASRC "${SOURCES}/*.cpp" "${SOURCES}/*.c")
list(APPEND CPPS ${ASRC})
endif()
#message("${NAME} HS = ${HS}")
list(APPEND HDRS ${HS})
list(APPEND PHDRS ${PHS})
if(${CMAKE_VERSION} VERSION_LESS "3.8.0")
else()
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${CPPS} ${HS} ${PHS})
endif()
set(_target "pip_${NAME}")
set(_libs "${LIBS}")
if ("${NAME}" STREQUAL "main")
@@ -118,11 +123,11 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
string(TOUPPER "${_target}" DEF_NAME)
set(PIP_MSG_${NAME} "yes${MSG}")
import_version(${_target} pip)
set_deploy_property(${_target} ${pip_LIB_TYPE}
import_version(${_target} PIP)
set_deploy_property(${_target} ${PIP_LIB_TYPE}
LABEL "${LABEL}"
FULLNAME "${pip_DOMAIN}.${_target}"
COMPANY "${pip_COMPANY}"
FULLNAME "${PIP_DOMAIN}.${_target}"
COMPANY "${PIP_COMPANY}"
INFO "Platform-Independent Primitives")
make_rc(${_target} _RC)
@@ -139,7 +144,7 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
pip_resources(CRES "${RES}")
endif()
add_definitions(-D${DEF_NAME})
add_library(${_target} ${pip_LIB_TYPE} ${CPPS} ${CRES} ${_RC})
add_library(${_target} ${PIP_LIB_TYPE} ${CPPS} ${CRES} ${_RC} ${HS} ${PHS})
target_include_directories(${_target} PUBLIC ${PIP_INCLUDES})
if (NOT "x${RES}" STREQUAL "x")
add_dependencies(${_target} pip_rc)
@@ -480,13 +485,11 @@ if (NOT CROSSTOOLS)
endif()
list(APPEND HDR_DIRS "${_lua_bri_dir}/LuaBridge")
list(APPEND HDRS ${_lua_src_hdr})
# Test program
if(PIP_UTILS)
#add_library(pip_plugin SHARED "test_plugin.h" "test_plugin.cpp")
#target_link_libraries(pip_plugin pip)
add_executable(pip_test "main.cpp")
target_link_libraries(pip_test pip)
endif()
@@ -592,14 +595,14 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
string(TOUPPER "${_m}" _mdef)
list(APPEND DOXY_DEFINES "PIP_${_mdef}_EXPORT")
endforeach()
set(DOXY_PROJECT_NUMBER "${pip_VERSION}")
set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${pip_VERSION}\"")
set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${pip_VERSION}\"")
set(DOXY_PROJECT_NUMBER "${PIP_VERSION}")
set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
set(DOXY_EXAMPLE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/examples\"")
set(DOXY_IMAGE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/images\"")
set(DOXY_LOGO_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/pip.png\"")
set(DOXY_EXCLUDE "\"${CMAKE_CURRENT_SOURCE_DIR}/libs/lua/3rd\"")
set(DOXY_DOMAIN "${pip_DOMAIN}.${PROJECT_NAME}.doc")
set(DOXY_DOMAIN "${PIP_DOMAIN}.${PROJECT_NAME}.doc")
if ("x${DOC_LANG}" STREQUAL "x")
set(DOXY_OUTPUT_LANGUAGE English)
set(DOXY_OUTPUT_DIR en)
@@ -645,9 +648,9 @@ endmacro()
list(REMOVE_ITEM LIBS_STATUS ${PIP_MODULES})
message("----------PIP----------")
message(" Version: ${pip_VERSION} ")
message(" Linkage: ${pip_LIB_TYPE_MSG}")
message(" Type : ${pip_BUILD_TYPE}")
message(" Version: ${PIP_VERSION} ")
message(" Linkage: ${PIP_LIB_TYPE_MSG}")
message(" Type : ${PIP_BUILD_TYPE}")
if (NOT LOCAL)
message(" Install: \"${CMAKE_INSTALL_PREFIX}\"")
else()

View File

@@ -20,40 +20,35 @@ main library
cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
include(SHSTKMacros)
shstk_set_find_dirs(pip)
if(PIP_DIR)
list(APPEND pip_LIBDIR "${PIP_DIR}/lib")
list(APPEND pip_INCDIR "${PIP_DIR}/include/pip")
list(APPEND pip_BINDIR "${PIP_DIR}/bin")
endif()
shstk_set_find_dirs(PIP)
set(__libs "usb;crypt;console;fftw;compress;io_utils;opencl;cloud;lua")
if (BUILDING_pip)
if (BUILDING_PIP)
#set(_libs "pip;pip_usb;pip_console;pip_crypt;pip_fftw;pip_compress;pip_opencl;pip_io_utils;pip_cloud;pip_lua")
#set(_bins "pip_cmg;pip_rc;deploy_tool")
#get_target_property(_path pip BINARY_DIR)
#get_target_property(_path pip LIBRARY_OUTPUT_NAME)
#message("${_path}")
#set(PIP_LIBRARY "$<TARGET_FILE_DIR:pip>/$<TARGET_FILE_NAME:pip>" CACHE STRING "")
set(PIP_LIBRARY pip CACHE STRING "")
#set(PIP_LIBRARY "$<TARGET_FILE_DIR:pip>/$<TARGET_FILE_NAME:pip>" CACHE STRING "")
set(PIP_LIBRARY pip CACHE STRING "")
set(PIP_FOUND ON CACHE BOOL "")
else()
find_library(PIP_LIBRARY pip HINTS ${pip_LIBDIR})
find_library(PIP_LIBRARY pip HINTS ${PIP_LIBDIR})
foreach (_l ${__libs})
find_library(PIP_LIBRARY_${_l} pip_${_l} HINTS ${pip_LIBDIR})
find_library(PIP_LIBRARY_${_l} pip_${_l} HINTS ${PIP_LIBDIR})
endforeach()
endif()
if (BUILDING_pip AND (NOT CMAKE_CROSSCOMPILING))
if (BUILDING_PIP AND (NOT CMAKE_CROSSCOMPILING))
set(PIP_CMG "$<TARGET_FILE_DIR:pip_cmg>/$<TARGET_FILE_NAME:pip_cmg>" CACHE STRING "")
set(PIP_RC "$<TARGET_FILE_DIR:pip_rc>/$<TARGET_FILE_NAME:pip_rc>" CACHE STRING "")
set(PIP_DEPLOY_TOOL "$<TARGET_FILE_DIR:deploy_tool>/$<TARGET_FILE_NAME:deploy_tool>" CACHE STRING "")
else()
find_program(PIP_CMG pip_cmg${pip_BINEXT} HINTS ${pip_BINDIR} ${pip_FIND_PROGRAM_ARG})
find_program(PIP_RC pip_rc${pip_BINEXT} HINTS ${pip_BINDIR} ${pip_FIND_PROGRAM_ARG})
find_program(PIP_DEPLOY_TOOL deploy_tool${pip_BINEXT} HINTS ${pip_BINDIR} ${pip_FIND_PROGRAM_ARG})
find_program(PIP_CMG pip_cmg${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
find_program(PIP_RC pip_rc${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
find_program(PIP_DEPLOY_TOOL deploy_tool${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
endif()
if (NOT PIP_LIBRARY)
if(PIP_FIND_REQUIRED)
@@ -63,7 +58,7 @@ if (NOT PIP_LIBRARY)
endif()
set(_PIP_LIBRARY_PATH_ "${PIP_LIBRARY}")
set(_PIP_ADD_LIBS_ "")
if (NOT BUILDING_pip)
if (NOT BUILDING_PIP)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
find_library(DL_LIBRARY dl)
list(APPEND PIP_LIBRARY ${DL_LIBRARY})
@@ -80,9 +75,9 @@ if (NOT BUILDING_pip)
endif()
endif()
if (NOT BUILDING_pip)
shstk_find_header(pip PIP "pip_version.h" "${_PIP_LIBRARY_PATH_}")
set(PIP_INCLUDES "${pip_INCLUDES}" CACHE STRING "")
if (NOT BUILDING_PIP)
shstk_find_header(PIP "pip_version.h" "${_PIP_LIBRARY_PATH_}")
set(PIP_INCLUDES "${PIP_INCLUDES}" CACHE STRING "")
endif()
if(PIP_FIND_VERSION VERSION_GREATER PIP_VERSION)
message(FATAL_ERROR "PIP version ${PIP_VERSION} is available, but ${PIP_FIND_VERSION} requested!")
@@ -108,10 +103,10 @@ set(__deps_io_utils "PIP::Crypt")
set(__deps_cloud "PIP::IOUtils")
if (BUILDING_pip)
if (BUILDING_PIP)
if (NOT SET_TARGETS_pip)
set(SET_TARGETS_pip ON CACHE BOOL "")
if (NOT SET_TARGETS_PIP)
set(SET_TARGETS_PIP ON CACHE BOOL "")
#message("create aliases")
if((NOT TARGET PIP) AND PIP_LIBRARY)
#message("alias PIP = pip")
@@ -133,7 +128,7 @@ else()
add_library(PIP UNKNOWN IMPORTED)
set_target_properties(PIP PROPERTIES
IMPORTED_LOCATION "${_PIP_LIBRARY_PATH_}"
INTERFACE_INCLUDE_DIRECTORIES "${pip_INCLUDES}"
INTERFACE_INCLUDE_DIRECTORIES "${PIP_INCLUDES}"
INTERFACE_LINK_LIBRARIES "${_PIP_ADD_LIBS_}")
#message("imported PIP = ${PIP_LIBRARY}")
endif()

View File

@@ -2282,7 +2282,7 @@ EXTERNAL_GROUPS = YES
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
EXTERNAL_PAGES = NO
#---------------------------------------------------------------------------
# Configuration options related to the dot tool

View File

@@ -4,7 +4,7 @@
inline PICout operator <<(PICout s, const PIByteArray & ba) {
s.space(); // insert space after previous output
s.quote(); // ONLY if you want to quoted your type
s.setControl(0, true); // clear all features and
s.saveAndSetControls(0); // clear all features and
// save them to stack,
// now it`s behavior similar to std::cout
@@ -12,7 +12,7 @@ inline PICout operator <<(PICout s, const PIByteArray & ba) {
for (uint i = 0; i < ba.size(); ++i)
s << ba[i];
s.restoreControl(); // restore features from stack
s.restoreControls(); // restore features from stack
s.quote(); // ONLY if you want to quoted your type
return s;
}

View File

@@ -7,19 +7,19 @@ class SomeIO: public PIIODevice {
public:
SomeIO(): PIIODevice() {}
protected:
bool openDevice() {
bool openDevice() override {
// open your device here
return if_success;
}
int read(void * read_to, int max_size) {
ssize_t readDevice(void * read_to, ssize_t max_size) override {
// read from your device here
return readed_bytes;
}
int write(const void * data, int max_size) {
ssize_t writeDevice(const void * data, ssize_t max_size) override {
// write to your device here
return written_bytes;
}
void configureFromFullPath(const PIString & full_path) {
void configureFromFullPathDevice(const PIString & full_path) override {
// parse full_path and configure device here
}
};
@@ -38,7 +38,7 @@ ser.configure("example.conf", "dev");
//! [configureDevice]
class SomeIO: public PIIODevice {
...
bool configureDevice(const void * e_main, const void * e_parent) {
bool configureDevice(const void * e_main, const void * e_parent) override {
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
setStringParam(readDeviceSetting<PIString>("stringParam", stringParam(), em, ep));

297
doc/pages/code_model.md Normal file
View File

@@ -0,0 +1,297 @@
\~english \page code_model Code generation
\~russian \page code_model Генерация кода
\~english
\~russian
# Введение
Кодогенерация помогает в случаях, когда нужен доступ к строковому представлению
сущностей (классов, перечислений, ...), либо автоматизированная де/сериализация
структур и классов.
Например, необходимо для создания интерфейса получить в готовом виде список
пар "имя" = "значение" от какого-либо перечисления, либо обойти список
вложенных в класс структур с дополнительными метками. Или просто описать
структуру любой сложности, пометить поля номерами и получить готовые операторы
де/сериализации для PIBinaryStream с возможностью будущих изменений и сохранением
обратной совместимости.
# pip_cmg
PIP предоставляет утилиту, которая берет на вход файлы исходного кода, пути
включения, параметры и макросы, и на выходе создает h/cpp пару файлов с
необходимым функционалом. В зависимости от параметров, в этих файлах будут
присутствовать секции:
* метаинформации о сущностях;
* операторы де/сериализации;
* возможность получить PIVariant любого члена структуры по имени.
Параметры обработки:
* -s - не следовать "#include" внутри файлов;
* -I<include_dir> - добавить папку включения (например, -I.. -I../some_dir -I/usr/include);
* -D<define> - добавить макрос, PICODE всегда объявлен (например, -DMY_DEFINE добавит макрос MY_DEFINE).
Параметры создания:
* -A - создать всё;
* -M - создать метаинформацию (имена и типы всех членов, иерархия включения);
* -E - создать перечисления (списки перечислений);
* -S - создать операторы де/сериализации;
* -G - создать методы получения значений переменных по именам;
* -o <output_file> - имя файлов модели без расширения (например, "ccm" - создадутся файлы "ccm.h" и "ccm.cpp")
# CMake
Для автоматизации кодогенерации существует CMake макрос pip_code_model, который сам вызывает pip_cmg и
следит за актуальностью модели.
Формат вызова макроса:
\code{.cmake}
pip_code_model(<out_var> file0 [file1 ...] [OPTIONS opt0 [opt1 ...] ] [NAME name])
\endcode
Параметры:
* out_var - имя переменной, куда будут записаны абсолютные пути сгенерённых файлов;
* file... - файлы для генерации, допускаются относительные или абсолютные пути;
* OPTIONS - передаваемые в pip_cmg параметры, например, "-Es";
* NAME - базовое имя файлов модели, если не указано, то используется "ccm_${PROJECT_NAME}".
Этот макрос сам включает все пути для PIP.
Для получения актуальных параметров pip_cmg можно вызывать "pip_cmg -v".
# Подробности
## Метаинформация
Метаинформация - это текстовое представление всех членов и методов структуры или класса C++.
Для доступа к ним используется PICodeInfo::classesInfo->value("name"), который возвращает
указатель на структуру PICodeInfo::ClassInfo, содержащую всю информацию о сущности.
В любой структуре PICodeInfo есть поле "MetaMap meta", содержащее произвольные
данные, видимые для кодогенератора, но невидимые для компилятора.
Для этого используется макрос PIMETA(), который необходимо вписать после объявления
переменной, метода либо сущности, например:
\code{.cpp}
struct MyStruct: Header PIMETA(type=in,port=5005) {
ushort calcChecksum() const PIMETA(show=true);
bool checkChecksum() const;
void setChecksum();
uchar block_id PIMETA(type=int) = 0;
};
enum FOV { // Поле зрения
fovWide PIMETA(label="Широкое",angle=90),
fovNormal PIMETA(label="Нормальное",angle=60),
fovNarrow PIMETA(label="Узкое",angle=30)
};
\endcode
В этом примере в каждом месте, где указана PIMETA, её можно будет получить через "MetaMap meta".
## Перечисления
Перечисления записываются отдельно, для доступа к ним используется PICodeInfo::enumsInfo->value("name"),
который возвращает указатель на структуру PICodeInfo::EnumInfo, содержащую всю информацию о перечеслении.
## Операторы де/сериализации
Эти операторы создаются в h файле для всех сутрктур и классов, в которых есть хотя бы один член,
доступный для работы. Операторы работают с PIBinaryStream в двух вариантах - простом или через PIChunkStream.
Для каждой структуры можно указать режим де/сериализации с помощью фиксированного поля в PIMETA:
* нет указаний - работа через PIChunkStream;
* simple-stream - работа просто через PIBinaryStream;
* no-stream - не создавать операторы.
Например, для структуры
\code{.cpp}
struct DateTime {
uchar seconds;
uchar minutes;
uchar hours;
uchar days;
uchar months;
uchar years;
};
\endcode
создадутся операторы
\code{.cpp}
BINARY_STREAM_WRITE(DateTime) {
PIChunkStream cs;
cs << cs.chunk(1, v.seconds);
cs << cs.chunk(2, v.minutes);
cs << cs.chunk(3, v.hours);
cs << cs.chunk(4, v.days);
cs << cs.chunk(5, v.months);
cs << cs.chunk(6, v.years);
s << cs.data();
return s;
}
BINARY_STREAM_READ (DateTime) {
PIByteArray csba; s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(v.seconds); break;
case 2: cs.get(v.minutes); break;
case 3: cs.get(v.hours); break;
case 4: cs.get(v.days); break;
case 5: cs.get(v.months); break;
case 6: cs.get(v.years); break;
}
}
return s;
}
\endcode
, где порядок id последовательнен.
Для структуры
\code{.cpp}
struct DateTime PIMETA(simple-stream) {
uchar seconds;
uchar minutes;
uchar hours;
uchar days;
uchar months;
uchar years;
};
\endcode
создадутся операторы
\code{.cpp}
BINARY_STREAM_WRITE(DateTime) {
s << v.seconds;
s << v.minutes;
s << v.hours;
s << v.days;
s << v.months;
s << v.years;
return s;
}
BINARY_STREAM_READ (DateTime) {
s >> v.seconds;
s >> v.minutes;
s >> v.hours;
s >> v.days;
s >> v.months;
s >> v.years;
return s;
}
\endcode
Для структуры
\code{.cpp}
struct DateTime PIMETA(no-stream) {
uchar seconds;
uchar minutes;
uchar hours;
uchar days;
uchar months;
uchar years;
};
\endcode
не создадутся операторы
В режиме работы через PIChunkStream также можно указать индивидуальные id,
что очень полезно для сохранения обратной совместимости структур разных версий:
Для структуры
\code{.cpp}
struct DateTime {
PIMETA(id=10) uchar seconds;
PIMETA(id=11) uchar minutes;
PIMETA(id=12) uchar hours;
PIMETA(id=20) uchar days;
PIMETA(id=21) uchar months;
PIMETA(id=22) uchar years;
};
\endcode
\code{.cpp}
BINARY_STREAM_WRITE(DateTime) {
PIChunkStream cs;
cs << cs.chunk(10, v.seconds);
cs << cs.chunk(11, v.minutes);
cs << cs.chunk(12, v.hours);
cs << cs.chunk(20, v.days);
cs << cs.chunk(21, v.months);
cs << cs.chunk(22, v.years);
s << cs.data();
return s;
}
BINARY_STREAM_READ (DateTime) {
PIByteArray csba; s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 10: cs.get(v.seconds); break;
case 11: cs.get(v.minutes); break;
case 12: cs.get(v.hours); break;
case 20: cs.get(v.days); break;
case 21: cs.get(v.months); break;
case 22: cs.get(v.years); break;
}
}
return s;
}
\endcode
Если в этом режиме какую-либо переменную надо проигнорировать, то вместо
числа id можно указать "-":
\code{.cpp}
struct DateTime {
PIMETA(id=10) uchar seconds;
PIMETA(id=11) uchar minutes;
PIMETA(id=-) uchar hours;
PIMETA(id=20) uchar days;
PIMETA(id=21) uchar months;
PIMETA(id=-) uchar years;
};
\endcode
\code{.cpp}
BINARY_STREAM_WRITE(DateTime) {
PIChunkStream cs;
cs << cs.chunk(10, v.seconds);
cs << cs.chunk(11, v.minutes);
cs << cs.chunk(20, v.days);
cs << cs.chunk(21, v.months);
s << cs.data();
return s;
}
BINARY_STREAM_READ (DateTime) {
PIByteArray csba; s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 10: cs.get(v.seconds); break;
case 11: cs.get(v.minutes); break;
case 20: cs.get(v.days); break;
case 21: cs.get(v.months); break;
}
}
return s;
}
\endcode
# Интеграция в проект
При использовании CMake достаточно включить содержимое переменной out_var в приложение
или библиотеку, и включить через "#include" сгенерированный заголовочный файл в нужном месте.
После этого перечисления и метаинформация будут загружены в момент запуска, до int main(),
а операторы станут доступны через заголовочный файл.
CMakeLists.txt:
\code{.cmake}
project(myapp)
pip_code_model(CCM "structures.h" OPTIONS "-EMs")
add_executable(${PROJECT_NAME} ${CPPS} ${CCM})
\endcode
C++:
\code{.cpp}
#include "ccm_myapp.h"
...
PICodeInfo::EnumInfo * ei = PICodeInfo::enumsInfo->value("MyEnum", 0);
if (ei) {
ei->members.forEach([](const PICodeInfo::EnumeratorInfo & e){piCout << e.name << "=" << e.value;});
}
\endcode

117
doc/pages/iostream.md Normal file
View File

@@ -0,0 +1,117 @@
\~english \page iostream Input/Output stream
\~russian \page iostream Поток ввода/вывода
\~english
\~russian
%PIBinaryStream представляет собой интерфейс бинарной сериализации.
Не может быть использован в чистом виде, только в виде миксина или
готовых классов: PIByteArray и PIIOBinaryStream.
Используется для сохранения или чтения любых данных. Простые типы читаются/пишутся
как блоки памяти, если не созданы конкретные операторы. Сложные типы
([нетривиальные](https://ru.cppreference.com/w/cpp/types/is_trivially_copyable))
обязаны иметь операторы ввода/вывода, иначе возникнет ошибка компиляции.
Также поддерживаются контейнеры с типами по таким же правилам.
Перечисления интерпретируются как int, логические типы как один байт.
Операторы сохранения добавляют данные в конец потока, а операторы извлечения
берут данные из его начала.
Для облегчения написания операторов есть макросы:
* BINARY_STREAM_FRIEND(T) - объявить операторы с доступом к приватному
содержимому типа T, необязателен;
* BINARY_STREAM_WRITE(T) - запись в поток, "s" - объект потока, "v" - объект типа T;
* BINARY_STREAM_READ(T) - чтение из потока, "s" - объект потока, "v" - объект типа T.
Пример:
\~\code{.cpp}
#include <pibytearray.h>
class MyType {
BINARY_STREAM_FRIEND(MyType);
public:
void setInt(int v) {m_i = v;}
int getInt() const {return m_i;}
void setString(PIString v) {m_s = v;}
PIString getString() const {return m_s;}
private:
int m_i = 0;
PIString m_s;
};
BINARY_STREAM_WRITE(MyType) {s << v.m_i << v.m_s; return s;}
BINARY_STREAM_READ (MyType) {s >> v.m_i >> v.m_s; return s;}
int main(int argc, char * argv[]) {
MyType t_read, t_write;
t_write.setInt(10);
t_write.setString("text");
PIByteArray data;
data << t_write;
piCout << data.toHex();
data >> t_read;
piCout << t_read.getInt() << t_read.getString();
piCout << data.toHex();
}
\endcode
\~english Result:
\~russian Результат:
\~\code{.cpp}
0a000000040000007400650078007400
10 text
\endcode
\~english
For store/restore custom data blocks this is PIMemoryBlock class. Stream
operators of this class simply store/restore data block to/from stream:
\~russian
Для сохранения/извлечения блоков произвольных данных используется класс PIMemoryBlock.
Потоковые операторы для него просто сохраняют/извлекают блоки байтов в/из потока:
\~\code{.cpp}
float a_read[10], a_write[10];
for (int i = 0; i < 10; ++i) {
a_read [i] = 0.f;
a_write[i] = i / 10.f;
}
PIByteArray data;
data << PIMemoryBlock(a_write, 10 * sizeof(float));
piCout << data.toHex();
data >> PIMemoryBlock(a_read, 10 * sizeof(float));
for (int i = 0; i < 10; ++i)
piCout << a_read[i];
\endcode
\~english Result:
\~russian Результат:
\~\code{.cpp}
00000000cdcccc3dcdcc4c3e9a99993ecdcccc3e0000003f9a99193f3333333fcdcc4c3f6666663f
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
\endcode

View File

@@ -6,7 +6,7 @@
* 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)
* serialization (\a PIBinaryStream, \a PITextStream, \a PIIOBinaryStream, \a PIIOTextStream, \a PIChunkStream)
* string (\a PIConstChars, \a PIString, \a PIStringList)
* base object (events and handlers) (\a PIObject)
* multithreading
@@ -57,7 +57,7 @@
* общение с консолью (\a PICout)
* контейнеры (\a PIVector, \a PIDeque, \a PIVector2D, \a PIStack, \a PIQueue, \a PIMap, \a PISet)
* байтовый массив (\a PIByteArray)
* сериализация (\a PIChunkStream)
* сериализация (\a PIBinaryStream, \a PITextStream, \a PIIOBinaryStream, \a PIIOTextStream, \a PIChunkStream)
* строка (\a PIConstChars, \a PIString, \a PIStringList)
* базовый объект (события и обработчики) (\a PIObject)
* многопоточность

View File

@@ -28,7 +28,7 @@ PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode)
is_deleted = false;
// setReopenEnabled(false);
CONNECTL(&eth, connected, [this](){opened_ = true; tcp.sendStart();});
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
CONNECT1(void, PIByteArray, &streampacker, packetReceiveEvent, this, _readed);
CONNECTL(&eth, disconnected, [this](bool){
if (is_deleted) return;
bool need_disconn = is_connected;
@@ -104,11 +104,11 @@ bool PICloudClient::closeDevice() {
}
int PICloudClient::readDevice(void * read_to, int max_size) {
ssize_t PICloudClient::readDevice(void * read_to, ssize_t max_size) {
if (is_deleted) return -1;
//piCoutObj << "readDevice";
if (!is_connected && eth.isClosed()) openDevice();
int sz = -1;
ssize_t sz = -1;
mutex_buff.lock();
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
if (is_connected) {
@@ -123,7 +123,7 @@ int PICloudClient::readDevice(void * read_to, int max_size) {
}
int PICloudClient::writeDevice(const void * data, int size) {
ssize_t PICloudClient::writeDevice(const void * data, ssize_t size) {
if (is_deleted) return -1;
// piCoutObj << "writeDevice";
return tcp.sendData(PIByteArray(data, size));

View File

@@ -25,7 +25,7 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode)
tcp.setRole(PICloud::TCP::Server);
tcp.setServerName(server_name);
setName("cloud_server__" + server_name);
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
CONNECT1(void, PIByteArray, &streampacker, packetReceiveEvent, this, _readed);
CONNECTL(&eth, connected, [this](){opened_ = true; piCoutObj << "connected"; tcp.sendStart();});
CONNECTL(&eth, disconnected, [this](bool){
piCoutObj << "disconnected";
@@ -88,7 +88,7 @@ bool PICloudServer::closeDevice() {
}
int PICloudServer::readDevice(void * read_to, int max_size) {
ssize_t PICloudServer::readDevice(void * read_to, ssize_t max_size) {
//piCoutObj << "readDevice";
if (!opened_) openDevice();
else piMSleep(eth.readTimeout());
@@ -96,7 +96,7 @@ int PICloudServer::readDevice(void * read_to, int max_size) {
}
int PICloudServer::writeDevice(const void * data, int max_size) {
ssize_t PICloudServer::writeDevice(const void * data, ssize_t max_size) {
//piCoutObj << "writeDevice";
return -1;
}
@@ -145,9 +145,9 @@ bool PICloudServer::Client::closeDevice() {
}
int PICloudServer::Client::readDevice(void * read_to, int max_size) {
ssize_t PICloudServer::Client::readDevice(void * read_to, ssize_t max_size) {
if (!is_connected) return -1;
int sz = -1;
ssize_t sz = -1;
mutex_buff.lock();
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
if (is_connected) {
@@ -160,7 +160,7 @@ int PICloudServer::Client::readDevice(void * read_to, int max_size) {
}
int PICloudServer::Client::writeDevice(const void * data, int size) {
ssize_t PICloudServer::Client::writeDevice(const void * data, ssize_t size) {
return server->sendData(PIByteArray(data, size), client_id);
}
@@ -189,7 +189,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
} else {
//piCoutObj << "new Client" << id;
Client * c = new Client(this, id);
CONNECTU(c, deleted, this, clientDeleted);
CONNECT1(void, PIObject *, c, deleted, this, clientDeleted);
clients_mutex.lock();
clients_ << c;
index_clients.insert(id, c);

View File

@@ -168,14 +168,14 @@ PIByteArray PICloud::TCP::parseConnect_d(PIByteArray & ba) {
uint PICloud::TCP::parseConnect(PIByteArray & ba) {
uint ret;
uint ret = 0;
ba >> ret;
return ret;
}
uint PICloud::TCP::parseDisconnect(PIByteArray & ba) {
uint ret;
uint ret = 0;
ba >> ret;
return ret;
}

View File

@@ -53,7 +53,7 @@ PIByteArray piCompress(const PIByteArray & ba, int level) {
PIByteArray piDecompress(const PIByteArray & zba) {
#ifdef PIP_COMPRESS
ullong sz;
ullong sz = 0;
if (zba.size() < sizeof(ullong)) {
piCout << "[PICompress]" << "Error: invalid input";
return zba;

View File

@@ -51,6 +51,18 @@ PRIVATE_DEFINITION_END(PIScreen::SystemConsole)
PIScreen::SystemConsole::SystemConsole() {
width = height = pwidth = pheight = 0;
mouse_x = mouse_y = -1;
}
PIScreen::SystemConsole::~SystemConsole() {
#ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#endif
}
void PIScreen::SystemConsole::begin() {
int w, h;
#ifdef WINDOWS
PRIVATE->ulcoord.X = 0;
@@ -74,18 +86,6 @@ PIScreen::SystemConsole::SystemConsole() {
# endif
#endif
resize(w, h);
}
PIScreen::SystemConsole::~SystemConsole() {
#ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
#endif
}
void PIScreen::SystemConsole::begin() {
#ifdef WINDOWS
SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
@@ -93,6 +93,7 @@ void PIScreen::SystemConsole::begin() {
PRIVATE->bc.Y = 0;
#endif
clear();
clearScreen();
hideCursor();
}
@@ -391,18 +392,17 @@ PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawe
needLockRun(true);
mouse_ = false;
ret_func = slot;
tile_focus = tile_dialog = 0;
tile_focus = tile_dialog = nullptr;
root.screen = this;
listener = new PIKbdListener(key_eventS, this, startNow);
CONNECTU(listener, mouseEvent, this, mouse_event);
CONNECTU(listener, wheelEvent, this, wheel_event);
CONNECT1(void, PIKbdListener::MouseEvent, listener, mouseEvent, this, mouse_event);
CONNECT1(void, PIKbdListener::WheelEvent, listener, wheelEvent, this, wheel_event);
if (startNow) start();
}
PIScreen::~PIScreen() {
if (isRunning())
stop();
if (isRunning()) stop();
PIThread::waitForFinish(10);
listener->waitForFinish(10);
delete listener;

View File

@@ -538,12 +538,11 @@ TilePICout::TilePICout(const PIString & n): TileList(n) {
max_lines = 1024;
selection_mode = TileList::SingleSelection;
PICout::setOutputDevices(PICout::Buffer);
PICout::setBufferActive(true);
}
void TilePICout::drawEvent(PIScreenDrawer * d) {
PIString out = PICout::buffer(true);
PIString out = PICout::getBufferAndClear();
if (!out.isEmpty()) {
PIStringList l = out.split("\n");
bool scroll = (cur == content.size_s() - 1) || !has_focus;

View File

@@ -151,7 +151,7 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
//piCout << "mcast " << ce->readAddress() << ce->sendAddress();
if (ce->open()) {
eth_mcast << ce;
CONNECTU(ce, threadedReadEvent, this, mcastRead);
CONNECT2(void, const uchar *, ssize_t, ce, threadedReadEvent, this, mcastRead);
} else {
delete ce;
}
@@ -173,7 +173,7 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
//piCout << "bcast " << ce->readAddress() << ce->sendAddress();
if (ce->open()) {
eth_mcast << ce;
CONNECTU(ce, threadedReadEvent, this, mcastRead);
CONNECT2(void, const uchar *, ssize_t, ce, threadedReadEvent, this, mcastRead);
} else {
delete ce;
}
@@ -189,7 +189,7 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
eth_lo->setName("PIMulticast_loopback");
if (!_send_only) {
eth_lo->setParameter(PIEthernet::ReuseAddress, false);
CONNECTU(eth_lo, threadedReadEvent, this, mcastRead);
CONNECT2(void, const uchar *, ssize_t, eth_lo, threadedReadEvent, this, mcastRead);
for (int i = 0; i < lo_pcnt; ++i) {
eth_lo->setReadAddress("127.0.0.1", lo_port + i);
if (eth_lo->open()) {
@@ -248,7 +248,7 @@ void PIBroadcast::reinit() {
}
void PIBroadcast::mcastRead(uchar * data, int size) {
void PIBroadcast::mcastRead(const uchar * data, ssize_t size) {
PIByteArray cd = decryptData(PIByteArray(data, size));
if (cd.isEmpty()) return;
received(cd);

View File

@@ -111,7 +111,7 @@ void PIStreamPacker::send(const PIByteArray & data) {
}
void PIStreamPacker::received(uchar * readed, int size) {
void PIStreamPacker::received(const uchar * readed, ssize_t size) {
received(PIByteArray(readed, size));
}
@@ -195,8 +195,9 @@ void PIStreamPacker::received(const PIByteArray & data) {
void PIStreamPacker::assignDevice(PIIODevice * dev) {
if (!dev) return;
if (!dev->infoFlags()[PIIODevice::Reliable])
if (!dev->infoFlags()[PIIODevice::Reliable]) {
piCoutObj << "Warning! Not recommended to use with non-reliable" << dev;
CONNECTU(dev, threadedReadEvent, this, received);
CONNECTU(this, sendRequest, dev, write);
}
CONNECT2(void, const uchar *, ssize_t, dev, threadedReadEvent, this, received);
CONNECT1(void, PIByteArray, this, sendRequest, dev, write);
}

View File

@@ -34,7 +34,7 @@
class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase
{
PIIODEVICE(PICloudClient, "")
PIIODEVICE(PICloudClient, "");
public:
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudClient();
@@ -42,16 +42,17 @@ public:
void setServerName(const PIString & server_name);
void setKeepConnection(bool on);
bool isConnected() const {return is_connected;}
ssize_t bytesAvailable() const override {return buff.size();}
EVENT(connected)
EVENT(disconnected)
EVENT(connected);
EVENT(disconnected);
protected:
bool openDevice();
bool closeDevice();
int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int size);
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
bool openDevice() override;
bool closeDevice() override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
private:
EVENT_HANDLER1(void, _readed, PIByteArray &, data);

View File

@@ -32,24 +32,25 @@
class PIP_CLOUD_EXPORT PICloudServer: public PIIODevice, public PICloudBase
{
PIIODEVICE(PICloudServer, "")
PIIODEVICE(PICloudServer, "");
public:
//! PICloudServer
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudServer();
class Client : public PIIODevice {
PIIODEVICE(PICloudServer::Client, "")
PIIODEVICE(PICloudServer::Client, "");
friend class PICloudServer;
public:
Client(PICloudServer * srv = nullptr, uint id = 0);
virtual ~Client();
protected:
bool openDevice();
bool closeDevice();
int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int size);
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
bool openDevice() override;
bool closeDevice() override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t size) override;
DeviceInfoFlags deviceInfoFlags() const override {return PIIODevice::Reliable;}
ssize_t bytesAvailable() const override {return buff.size();}
private:
void pushBuffer(const PIByteArray & ba);
@@ -65,13 +66,13 @@ public:
PIVector<PICloudServer::Client *> clients() const;
EVENT1(newConnection, PICloudServer::Client * , client)
EVENT1(newConnection, PICloudServer::Client * , client);
protected:
bool openDevice();
bool closeDevice();
int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size);
bool openDevice() override;
bool closeDevice() override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t max_size) override;
private:
EVENT_HANDLER1(void, _readed, PIByteArray &, ba);

View File

@@ -1,8 +1,8 @@
/*! \file picodeinfo.h
* \ingroup Code
* \~\brief
* \~english C++ code info structs
* \~russian Структуры для C++ кода
* \~english C++ code info structs. See \ref code_model.
* \~russian Структуры для C++ кода. Подробнее \ref code_model.
*/
/*
PIP - Platform Independent Primitives
@@ -34,17 +34,24 @@
class PIVariant;
//! \~english Namespace contains structures for code generation. See \ref code_model.
//! \~russian Пространство имен содержит структуры для кодогенерации. Подробнее \ref code_model.
namespace PICodeInfo {
//! \~english
//! Type modifiers
//! \~russian
//! Модификаторы типа
enum TypeFlag {
NoFlag,
Const = 0x01,
Static = 0x02,
Mutable = 0x04,
Volatile = 0x08,
Inline = 0x10,
Virtual = 0x20,
Extern = 0x40
Const /** const */ = 0x01,
Static /** static */ = 0x02,
Mutable /** mutable */ = 0x04,
Volatile /** volatile */ = 0x08,
Inline /** inline */ = 0x10,
Virtual /** virtual */ = 0x20,
Extern /** extern */ = 0x40
};
typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
@@ -52,49 +59,145 @@ typedef PIMap<PIString, PIString> MetaMap;
typedef PIByteArray(*AccessValueFunction)(const void *, const char *);
typedef const char*(*AccessTypeFunction)(const char *);
//! \~english Type information
//! \~russian Информация о типе
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;}
//! \~english Returns if variable if bitfield
//! \~russian Возвращает битовым ли полем является переменная
bool isBitfield() const {return bits > 0;}
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
MetaMap meta;
//! \~english Name
//! \~russian Имя
PIConstChars name;
//! \~english Type
//! \~russian Тип
PIConstChars type;
//! \~english Modifiers
//! \~russian Модификаторы
PICodeInfo::TypeFlags flags;
//! \~english Bitfield variable bit count
//! \~russian Количество бит битового поля
int bits;
};
//! \~english Method information
//! \~russian Информация о методе
struct PIP_EXPORT FunctionInfo {
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
MetaMap meta;
//! \~english Name
//! \~russian Имя
PIConstChars name;
//! \~english Return type
//! \~russian Возвращаемые тип
TypeInfo return_type;
//! \~english Arguments types
//! \~russian Типы аргументов
PIVector<PICodeInfo::TypeInfo> arguments;
};
//! \~english Class or struct information
//! \~russian Информация о классе или структуре
struct PIP_EXPORT ClassInfo {
ClassInfo() {has_name = true;}
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
MetaMap meta;
//! \~english Has name or not
//! \~russian Имеет или нет имя
bool has_name;
//! \~english Type
//! \~russian Тип
PIConstChars type;
//! \~english Name
//! \~russian Имя
PIConstChars name;
//! \~english Parent names
//! \~russian Имена родителей
PIVector<PIConstChars> parents;
//! \~english Variables
//! \~russian Переменные
PIVector<PICodeInfo::TypeInfo> variables;
//! \~english Methods
//! \~russian Методы
PIVector<PICodeInfo::FunctionInfo> functions;
//! \~english Subclass list
//! \~russian Список наследников
PIVector<PICodeInfo::ClassInfo * > children_info;
};
//! \~english Enumerator information
//! \~russian Информация об элементе перечисления
struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {name = n; value = v;}
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name.toString());}
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
MetaMap meta;
//! \~english Name
//! \~russian Имя
PIConstChars name;
//! \~english Value
//! \~russian Значение
int value;
};
//! \~english Enum information
//! \~russian Информация о перечислении
struct PIP_EXPORT EnumInfo {
//! \~english Returns member name with value "value"
//! \~russian Возвращает имя элемента со значением "value"
PIString memberName(int value) const;
//! \~english Returns member value with name "name"
//! \~russian Возвращает значение элемента с именем "name"
int memberValue(const PIString & name) const;
//! \~english Returns as PIVariantTypes::Enum
//! \~russian Возвращает как PIVariantTypes::Enum
PIVariantTypes::Enum toPIVariantEnum();
//! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA
MetaMap meta;
//! \~english Name
//! \~russian Имя
PIConstChars name;
//! \~english Members
//! \~russian Элементы
PIVector<PICodeInfo::EnumeratorInfo> members;
};
@@ -115,7 +218,7 @@ inline PICout operator <<(PICout s, const PICodeInfo::TypeInfo & v) {
inline PICout operator <<(PICout s, const PICodeInfo::EnumeratorInfo & v) {s << v.name << " = " << v.value << " Meta" << v.meta; return s;}
inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
s.setControl(0, true);
s.saveAndSetControls(0);
s << "class " << v.name;
if (!v.parents.isEmpty()) {
s << ": ";
@@ -143,12 +246,12 @@ inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n";
}
s << "}\n";
s.restoreControl();
s.restoreControls();
return s;
}
inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
s.setControl(0, true);
s.saveAndSetControls(0);
s << "enum " << v.name << " Meta" << v.meta << " {\n";
for (const auto & i: v.members) {
bool f = true;
@@ -157,13 +260,21 @@ inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
s << PICoutManipulators::Tab << i << "\n";
}
s << "}\n";
s.restoreControl();
s.restoreControls();
return s;
}
//! \~english Pointer to single storage of PICodeInfo::ClassInfo, access by name
//! \~russian Указатель на единое хренилище PICodeInfo::ClassInfo, доступ по имени
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::ClassInfo * > * classesInfo;
//! \~english Pointer to single storage of PICodeInfo::EnumInfo, access by name
//! \~russian Указатель на единое хренилище PICodeInfo::EnumInfo, доступ по имени
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::EnumInfo * > * enumsInfo;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {

View File

@@ -35,9 +35,11 @@
//!
//! \~english
//! These files provides parsing C++ code and storage to use results of \a pip_cmg utility.
//! See \ref code_model.
//!
//! \~russian
//! Эти файлы обеспечивают разбор C++ кода и хранение результатов работы утилиты \a pip_cmg.
//! Подробнее \ref code_model.
//!
//! \~\authors
//! \~english

View File

@@ -1050,7 +1050,7 @@ PIString PICodeParser::procMacros(PIString fc) {
if (ifcnt > 0) ifcnt--;
else {
//piCout << "main endif" << skip << grab;
if (grab) pfc << procMacros(nfc);
if (grab) pfc += procMacros(nfc);
skip = grab = false;
continue;
}
@@ -1059,7 +1059,7 @@ PIString PICodeParser::procMacros(PIString fc) {
//piCout << "main elif" << skip << grab << cond_ok;
if (cond_ok) {
if (grab) {
pfc << procMacros(nfc);
pfc += procMacros(nfc);
skip = true; grab = false;
}
continue;
@@ -1075,12 +1075,12 @@ PIString PICodeParser::procMacros(PIString fc) {
}
if (mif.left(4) == s_else && ifcnt == 0) {
//piCout << "main else" << skip << grab;
if (grab) pfc << procMacros(nfc);
if (grab) pfc += procMacros(nfc);
if (skip && !cond_ok) {skip = false; grab = true;}
else {skip = true; grab = false;}
continue;
}
if (grab) nfc << line << '\n';
if (grab) nfc += line + '\n';
continue;
}
if (mif.left(2) == s_if) {
@@ -1095,8 +1095,8 @@ PIString PICodeParser::procMacros(PIString fc) {
//return false; /// WARNING: now skip errors
}
} else {
if (grab) nfc << line << '\n';
else if (!skip) pfc << line << '\n';
if (grab) nfc += line + '\n';
else if (!skip) pfc += line + '\n';
}
}
return pfc;

View File

@@ -33,7 +33,7 @@
class PIP_EXPORT PIKbdListener: public PIThread
{
PIOBJECT_SUBCLASS(PIKbdListener, PIThread)
PIOBJECT_SUBCLASS(PIKbdListener, PIThread);
friend class PIConsole;
friend class PITerminal;
public:
@@ -176,9 +176,9 @@ public:
EVENT_HANDLER(void, setActive) {setActive(true);}
EVENT_HANDLER1(void, setActive, bool, yes);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void * , data)
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void * , data)
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data);
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void * , data);
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void * , data);
//! \handlers
//! \{
@@ -205,9 +205,9 @@ public:
static PIKbdListener * instance() {return _object;}
private:
void begin();
void run() {readKeyboard();}
void end();
void begin() override;
void run() override {readKeyboard();}
void end() override;
#ifndef WINDOWS
struct PIP_EXPORT EscSeq {
@@ -247,13 +247,27 @@ private:
};
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::KeyEvent & v) {s << v.key << v.modifiers; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::MouseEvent & v) {s << v.x << v.y << (int)v.action << v.buttons << v.modifiers; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::WheelEvent & v) {s << (*(PIKbdListener::MouseEvent*)&v) << (uchar)v.direction; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator
//! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIKbdListener::MouseEvent) {s << v.x << v.y << v.action << v.buttons << v.modifiers; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator
//! \~russian Оператор извлечения
BINARY_STREAM_READ (PIKbdListener::MouseEvent) {s >> v.x >> v.y >> v.action >> v.buttons >> v.modifiers; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator
//! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIKbdListener::WheelEvent) {s << (*(PIKbdListener::MouseEvent*)&v) << v.direction; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator
//! \~russian Оператор извлечения
BINARY_STREAM_READ (PIKbdListener::WheelEvent) {s >> (*(PIKbdListener::MouseEvent*)&v) >> v.direction; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::KeyEvent & v) {s >> v.key >> v.modifiers; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::MouseEvent & v) {int a(0); s >> v.x >> v.y >> a >> v.buttons >> v.modifiers; v.action = (PIKbdListener::MouseAction)a; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::WheelEvent & v) {uchar d(0); s >> (*(PIKbdListener::MouseEvent*)&v) >> d; v.direction = d; return s;}
REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent)
REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent)

View File

@@ -33,7 +33,7 @@
class PIP_CONSOLE_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
{
PIOBJECT_SUBCLASS(PIScreen, PIThread)
PIOBJECT_SUBCLASS(PIScreen, PIThread);
class SystemConsole;
public:
@@ -76,8 +76,8 @@ public:
EVENT_HANDLER0(void, stop) {stop(false);}
EVENT_HANDLER1(void, stop, bool, clear);
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e)
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data);
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e);
//! \handlers
//! \{
@@ -134,9 +134,9 @@ private:
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
};
void begin();
void run();
void end();
void begin() override;
void run() override;
void end() override;
void key_event(PIKbdListener::KeyEvent key);
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
@@ -145,9 +145,9 @@ private:
PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e);
PIVector<PIScreenTile*> tilesUnderMouse(int x, int y);
bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent());
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e);
void tileRemovedInternal(PIScreenTile * t);
void tileSetFocusInternal(PIScreenTile * t);
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e) override;
void tileRemovedInternal(PIScreenTile * t) override;
void tileSetFocusInternal(PIScreenTile * t) override;
bool mouse_;
SystemConsole console;

View File

@@ -64,8 +64,8 @@ protected:
};
PIVector<Variable> variables;
PIScreenTypes::Alignment alignment;
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
};

View File

@@ -34,7 +34,7 @@ class PIScreenDrawer;
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject)
PIOBJECT_SUBCLASS(PIScreenTile, PIObject);
public:
PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
virtual ~PIScreenTile();

View File

@@ -31,7 +31,7 @@
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile)
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile);
public:
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
TileSimple(const PIString & n = PIString());
@@ -40,15 +40,15 @@ public:
PIVector<Row> content;
PIScreenTypes::Alignment alignment;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
};
class TileList;
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile)
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile);
friend class TileList;
public:
TileScrollBar(const PIString & n = PIString());
@@ -62,16 +62,16 @@ public:
int thickness;
protected:
void _check();
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool mouseEvent(PIKbdListener::MouseEvent me);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool mouseEvent(PIKbdListener::MouseEvent me) override;
int minimum_, maximum_, value_;
PIChar line_char;
};
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile)
PIOBJECT_SUBCLASS(TileList, PIScreenTile);
public:
enum SelectionMode {
NoSelection,
@@ -93,19 +93,19 @@ public:
PISet<int> selected;
int lhei, cur, offset;
protected:
void sizeHint(int & w, int & h) const;
void resizeEvent(int w, int h);
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
bool wheelEvent(PIKbdListener::WheelEvent we);
void sizeHint(int & w, int & h) const override;
void resizeEvent(int w, int h) override;
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
bool mouseEvent(PIKbdListener::MouseEvent me) override;
bool wheelEvent(PIKbdListener::WheelEvent we) override;
TileScrollBar * scroll;
bool mouse_sel;
};
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile)
PIOBJECT_SUBCLASS(TileButton, PIScreenTile);
public:
TileButton(const PIString & n = PIString());
virtual ~TileButton() {}
@@ -115,17 +115,17 @@ public:
PIScreenTypes::CellFormat format;
PIString text;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
bool mouseEvent(PIKbdListener::MouseEvent me) override;
};
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile)
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile);
public:
TileButtons(const PIString & n = PIString());
virtual ~TileButtons() {}
@@ -137,10 +137,10 @@ public:
PIVector<Button> content;
int cur;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
bool mouseEvent(PIKbdListener::MouseEvent me) override;
struct Rect {
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {}
int x0,y0,x1,y1;
@@ -150,7 +150,7 @@ protected:
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile)
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile);
public:
TileCheck(const PIString & n = PIString());
virtual ~TileCheck() {}
@@ -161,15 +161,15 @@ public:
PIString text;
bool toggled;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
bool mouseEvent(PIKbdListener::MouseEvent me);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
bool mouseEvent(PIKbdListener::MouseEvent me) override;
};
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile)
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile);
public:
TileProgress(const PIString & n = PIString());
virtual ~TileProgress() {}
@@ -179,26 +179,26 @@ public:
double maximum;
double value;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
};
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile)
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);
public:
TilePICout(const PIString & n = PIString());
virtual ~TilePICout() {}
PIScreenTypes::CellFormat format;
int max_lines;
protected:
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
};
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile)
PIOBJECT_SUBCLASS(TileInput, PIScreenTile);
public:
TileInput(const PIString & n = PIString());
virtual ~TileInput() {}
@@ -206,9 +206,9 @@ public:
PIString text;
int max_length;
protected:
void sizeHint(int & w, int & h) const;
void drawEvent(PIScreenDrawer * d);
bool keyEvent(PIKbdListener::KeyEvent key);
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
void reserCursor();
int cur, offset;
bool inv;

View File

@@ -143,11 +143,30 @@ namespace PIScreenTypes {
}
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
//inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
//inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator
//! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIScreenTypes::Cell) {s << v.format.raw_format << v.symbol; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator
//! \~russian Оператор извлечения
BINARY_STREAM_READ (PIScreenTypes::Cell) {s >> v.format.raw_format >> v.symbol; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator
//! \~russian Оператор сохранения
BINARY_STREAM_WRITE(PIScreenTypes::TileEvent) {s << v.type << v.data; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator
//! \~russian Оператор извлечения
BINARY_STREAM_READ (PIScreenTypes::TileEvent) {s >> v.type >> v.data; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::TileEvent & v) {s << v.type << v.data; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::TileEvent & v) {s >> v.type >> v.data; return s;}
REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent)

View File

@@ -33,7 +33,7 @@
class PIP_CONSOLE_EXPORT PITerminal: public PIThread
{
PIOBJECT_SUBCLASS(PITerminal, PIThread)
PIOBJECT_SUBCLASS(PITerminal, PIThread);
public:
//! Constructs %PITerminal
@@ -58,7 +58,7 @@ private:
void readConsole();
void getCursor(int & x, int & y);
uchar invertColor(uchar c);
void run();
void run() override;
#ifndef WINDOWS
void parseInput(const PIString & s);
bool isCompleteEscSeq(const PIString & es);

View File

@@ -20,11 +20,11 @@
#include "picontainers.h"
const ssize_t minAlloc = 64;
const size_t minAlloc = 64;
ssize_t _PIContainerConstantsBase::calcMinCountPoT(ssize_t szof) {
ssize_t ret = 0, elc = 1;
size_t _PIContainerConstantsBase::calcMinCountPoT(size_t szof) {
size_t ret = 0, elc = 1;
while (elc * szof < minAlloc) {
elc *= 2;
++ret;

View File

@@ -65,13 +65,13 @@ private:
class PIP_EXPORT _PIContainerConstantsBase {
public:
static ssize_t calcMinCountPoT(ssize_t szof);
static size_t calcMinCountPoT(size_t szof);
};
template<typename T>
class _PIContainerConstants {
public:
static ssize_t minCountPoT() {static ssize_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
static size_t minCountPoT() {static size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
};

View File

@@ -127,13 +127,13 @@ public:
//! \~english Constructs an empty array.
//! \~russian Создает пустой массив.
inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
inline PIDeque() {
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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc_forward(other.pid_size);
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
@@ -148,7 +148,7 @@ public:
//! 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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc_forward(init_list.size());
newT(pid_data, init_list.begin(), init_list.size());
@@ -158,7 +158,7 @@ public:
//! 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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc_forward(size);
newT(pid_data + pid_start, data, pid_size);
@@ -166,9 +166,9 @@ public:
//! \~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) {
inline PIDeque(size_t pid_size, const T & e = T()) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(pid_size, e);
expand(pid_size, e);
}
//! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
@@ -184,19 +184,23 @@ public:
//! 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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(piv_size, f);
expand(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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
pid_data = other.pid_data;
pid_size = other.pid_size;
pid_rsize = other.pid_rsize;
pid_start = other.pid_start;
other._reset();
}
inline virtual ~PIDeque() {
inline ~PIDeque() {
PIINTROSPECTION_CONTAINER_DELETE(T)
PIINTROSPECTION_CONTAINER_FREE(T, (pid_rsize))
deleteT(pid_data + pid_start, pid_size);
@@ -613,7 +617,8 @@ public:
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент, следующий за последним элементом.
//! \~russian Обратный итератор на элемент,
//! следующий за последним элементом.
//! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png)
//!
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
@@ -645,7 +650,7 @@ public:
inline size_t length() const {return pid_size;}
//! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
//! \~\details
//! \~english To find out the actual number of items, use the function \a size().
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
@@ -655,18 +660,18 @@ public:
inline size_t _start() const {return pid_start;}
//! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли контейнер.
//! \~russian Проверяет пуст ли массив.
//! \~\return
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если контейнер пуст, **false** иначе.
//! \~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);}
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли контейнер.
//! \~russian Проверяет не пуст ли массив.
//! \~\return
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если контейнер не пуст, **false** иначе.
//! \~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);}
@@ -689,7 +694,7 @@ public:
//! \endcode
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
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 (size_t i = pid_start; i < pid_start + pid_size; ++i) {
if (test(pid_data[i])) return true;
}
return false;
@@ -714,7 +719,7 @@ public:
//! \endcode
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
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 (size_t i = pid_start; i < pid_start + pid_size; ++i) {
if (!test(pid_data[i])) return false;
}
return true;
@@ -750,6 +755,30 @@ public:
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const T & at(size_t index) const {return pid_data[pid_start + index];}
//! \~english Returns the first element of the array that
//! passes the test implemented by the provided function `test`
//! or `def` if there is no such element.
//! \~russian Возвращает первый элемент массива, проходящего по условию,
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a indexWhere()
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
ssize_t i = indexWhere(test, start);
if (i < 0) return def;
else return at(i);
}
//! \~english Returns the last element of the array that
//! passes the test implemented by the provided function `test`
//! or `def` if there is no such element.
//! \~russian Возвращает последний элемент массива, проходящего по условию,
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a lastIndexWhere()
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
ssize_t i = lastIndexWhere(test, start);
if (i < 0) return def;
else return at(i);
}
//! \~english Last element.
//! \~russian Последний элемент массива.
//! \~\details
@@ -804,7 +833,7 @@ public:
//! возвращается **false**, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4};
@@ -825,12 +854,39 @@ public:
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 (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
if (e == pid_data[i]) return true;
}
return false;
}
//! \~english Tests if all elements of `v` exists in the array.
//! \~russian Проверяет наличие всех элементов `v` в массиве.
//! \~\details
//! \~\code
//! PIDeque<int> v{1, 2, 3, 4};
//! piCout << v.contains({1,4}); // true
//! piCout << v.contains({1,5}); // false
//! \endcode
//! \~\sa \a every(), \a any(), \a entries(), \a forEach()
inline bool contains(const PIDeque<T> & v, ssize_t start = 0) const {
if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (const T & e : v) {
bool c = false;
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
if (e == pid_data[i]) {
c = true;
break;
}
}
if (!c) return false;
}
return true;
}
//! \~english Count elements equal `e` in the array.
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
//! \~\details
@@ -847,7 +903,7 @@ public:
//! возвращается 0, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<int> v{2, 2, 4, 2, 6};
@@ -856,13 +912,13 @@ public:
//! 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 {
inline int entries(const T & e, ssize_t start = 0) const {
int ec = 0;
if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
if (e == pid_data[i]) ++ec;
}
return ec;
@@ -887,16 +943,16 @@ public:
//! возвращается 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 {
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
int ec = 0;
if (start < 0) {
start = pid_size + start;
if (start < 0) start = 0;
}
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
if (test(pid_data[i])) ++ec;
}
return ec;
@@ -920,7 +976,7 @@ public:
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<int> v{2, 5, 9};
@@ -931,14 +987,14 @@ public:
//! 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, 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) {
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
if (e == pid_data[i]) {
return i - pid_start;
return ssize_t(i) - pid_start;
}
}
return -1;
@@ -963,7 +1019,7 @@ public:
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIDeque<PIString> v{"do", "re", "mi", "re"};
@@ -972,14 +1028,14 @@ public:
//! 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, 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) {
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
if (test(pid_data[i])) {
return i - pid_start;
return ssize_t(i) - pid_start;
}
}
return -1;
@@ -1005,7 +1061,7 @@ public:
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
@@ -1022,9 +1078,9 @@ public:
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 + start;
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
for (ssize_t i = ssize_t(pid_start) + start; i >= ssize_t(pid_start); --i) {
if (e == pid_data[i]) {
return i - pid_start;
return i - ssize_t(pid_start);
}
}
return -1;
@@ -1050,7 +1106,7 @@ public:
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
@@ -1058,9 +1114,9 @@ public:
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 + start;
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
for (ssize_t i = ssize_t(pid_start) + start; i >= ssize_t(pid_start); --i) {
if (test(pid_data[i])) {
return i - pid_start;
return i - ssize_t(pid_start);
}
}
return -1;
@@ -1133,7 +1189,9 @@ public:
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline PIDeque<T> & clear() {
resize(0);
deleteT(&(pid_data[pid_start]), pid_size);
pid_size = 0;
pid_start = (pid_rsize - pid_size) / 2;
return *this;
}
template<typename T1 = T, typename std::enable_if<
@@ -1217,20 +1275,12 @@ public:
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIDeque<T> & resize(size_t new_size, const T & e = T()) {
if (new_size == 0) return clear();
if (new_size < pid_size) {
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
pid_size = new_size;
if (new_size == 0) {
pid_start = (pid_rsize - pid_size) / 2;
}
}
if (new_size > pid_size) {
size_t os = pid_size;
alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, e);
}
}else if (new_size > pid_size) {
expand(new_size, e);
}
return *this;
}
@@ -1247,20 +1297,12 @@ public:
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
if (new_size == 0) return clear();
if (new_size < pid_size) {
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
pid_size = new_size;
if (new_size == 0) {
pid_start = (pid_rsize - pid_size) / 2;
}
}
if (new_size > pid_size) {
size_t os = pid_size;
alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, f(i));
}
} else if (new_size > pid_size) {
expand(new_size, f);
}
return *this;
}
@@ -1376,7 +1418,7 @@ public:
}
#endif
assert(&v != this);
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
bool dir = v.size() > pid_size ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) {
ssize_t os = pid_size - index;
alloc_forward(pid_size + v.pid_size);
@@ -1404,9 +1446,9 @@ public:
//! [списка инициализации 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);
bool dir = init_list.size() > pid_size ? true : (index >= pid_rsize / 2 ? true : false);
if (dir) {
ssize_t os = pid_size - index;
ssize_t os = ssize_t(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));
@@ -1433,7 +1475,10 @@ public:
inline PIDeque<T> & remove(size_t index, size_t count = 1) {
if (count == 0) return *this;
if (index + count >= pid_size) {
resize(index);
if (index < pid_size) {
deleteT(&(pid_data[index + pid_start]), pid_size - index);
pid_size = index;
}
return *this;
}
size_t os = pid_size - index - count;
@@ -1461,7 +1506,7 @@ public:
piSwap<T*>(pid_data, other.pid_data);
piSwap<size_t>(pid_size, other.pid_size);
piSwap<size_t>(pid_rsize, other.pid_rsize);
piSwap<ssize_t>(pid_start, other.pid_start);
piSwap<size_t>(pid_start, other.pid_start);
}
//! \~english Sorts the elements in non-descending order.
@@ -1572,10 +1617,10 @@ public:
//! Если `add_size < 0`, то с конца массива удаляются элементы.
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
//! \~\sa \a resize()
inline PIDeque<T> & enlarge(llong pid_size) {
llong ns = size_s() + pid_size;
inline PIDeque<T> & enlarge(ssize_t add_size, const T & e = T()) {
ssize_t ns = size_s() + add_size;
if (ns <= 0) clear();
else resize(size_t(ns));
else resize(size_t(ns), e);
return *this;
}
@@ -1608,7 +1653,7 @@ public:
//! \endcode
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIDeque<T> & removeAll(const T & e) {
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
for (size_t i = 0; i < pid_size; ++i) {
if (pid_data[i + pid_start] == e) {
remove(i);
--i;
@@ -1629,7 +1674,7 @@ public:
//! \endcode
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
for (size_t i = 0; i < pid_size; ++i) {
if (test(pid_data[i + pid_start])) {
remove(i);
--i;
@@ -1706,6 +1751,7 @@ public:
//! \~russian Перегруженая функция.
//! \~\sa \a push_back()
inline PIDeque<T> & push_back(const PIDeque<T> & v) {
if (v.isEmpty()) return *this;
#ifndef NDEBUG
if (&v == this) {
printf("error with PIDeque<%s>::append\n", __PIP_TYPENAME__(T));
@@ -1835,7 +1881,9 @@ public:
//! \endcode
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIDeque<T> & push_front(const T & e) {
insert(0, e);
if (isEmpty()) return push_back(e);
alloc_backward(pid_size + 1, -1);
elementNew(pid_data + pid_start, e);
return *this;
}
@@ -1846,7 +1894,9 @@ public:
//! \~russian Перегруженая функция.
//! \~\sa \a push_front()
inline PIDeque<T> & push_front(T && e) {
insert(0, std::move(e));
if (isEmpty()) return push_back(std::move(e));
alloc_backward(pid_size + 1, -1);
elementNew(pid_data + pid_start, std::move(e));
return *this;
}
@@ -1862,8 +1912,7 @@ public:
//! \endcode
//! \~\sa \a push_front()
inline PIDeque<T> & push_front(const PIDeque<T> & v) {
insert(0, v);
return *this;
return insert(0, v);
}
//! \~english Appends the given elements to the begin of the array.
@@ -1877,8 +1926,7 @@ public:
//! [списка инициализации 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;
return insert(0, init_list);
}
//! \~english Appends the given element `e` to the begin of the array.
@@ -1938,7 +1986,7 @@ public:
//! Добавляет элементы из
//! [списка инициализации 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);}
inline PIDeque<T> & prepend(std::initializer_list<T> init_list) {return push_front(init_list);}
//! \~english Remove one element from the end of the array.
//! \~russian Удаляет один элемент с конца массива.
@@ -1955,7 +2003,8 @@ public:
//! \~\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);
elementDelete(pid_data[pid_size + pid_start - 1]);
pid_size = pid_size - 1;
return *this;
}
@@ -1976,7 +2025,9 @@ public:
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
inline PIDeque<T> & pop_front() {
if (pid_size == 0) return *this;
remove(0);
elementDelete(pid_data[pid_start]);
pid_start += 1;
pid_size -= 1;
return *this;
}
@@ -2047,6 +2098,39 @@ public:
return ret;
}
//! \~english Same as \a filter() but with `index` parameter in `test`.
//! \~russian Аналогично \a filter() но с параметром индекса `index` в функции `test`.
//! \~\sa \a filter()
inline PIDeque<T> filterIndexed(std::function<bool(size_t index, const T & e)> test) const {
PIDeque<T> ret;
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
if (test(i - pid_start, pid_data[i])) ret << pid_data[i];
}
return ret;
}
//! \~english Same as \a filter() but from end to begin (from right to left).
//! \~russian Аналогично \a filter() но от конца до начала (справа на лево).
//! \~\sa \a filter()
inline PIDeque<T> filterReverse(std::function<bool(const T & e)> test) const {
PIDeque<T> ret;
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
if (test(pid_data[i])) ret << pid_data[i];
}
return ret;
}
//! \~english Same as \a filterReverse() but with `index` parameter in `test`.
//! \~russian Аналогично \a filterReverse() но с параметром индекса `index` в функции `test`.
//! \~\sa \a filterReverse()
inline PIDeque<T> filterReverseIndexed(std::function<bool(size_t index, const T & e)> test) const {
PIDeque<T> ret;
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
if (test(i - pid_start, 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
@@ -2087,6 +2171,63 @@ public:
return *this;
}
//! \~english Same as \a forEach() but with `index` parameter in `f`.
//! \~russian Аналогично \a forEach() но с параметром индекса `index` в функции `f`.
//! \~\sa \a forEach()
inline void forEachIndexed(std::function<void(size_t index, const T & e)> f) const {
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
f(i - pid_start, pid_data[i]);
}
}
//! \~english Same as \a forEachIndexed(), but allows you to change the elements of the array.
//! \~russian Аналогично \a forEachIndexed(), но позволяет изменять элементы массива.
//! \~\sa \a forEach(), \a forEachIndexed()
inline PIDeque<T> & forEachIndexed(std::function<void(size_t index, T & e)> f) {
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
f(i - pid_start, pid_data[i]);
}
return *this;
}
//! \~english Same as \a forEach() but from end to begin (from right to left).
//! \~russian Аналогично \a forEach() но от конца до начала (справа на лево).
//! \~\sa \a forEach()
inline void forEachReverse(std::function<void(const T & e)> f) const {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(pid_data[i]);
}
}
//! \~english Same as \a forEachReverse(), but allows you to change the elements of the array.
//! \~russian Аналогично \a forEachReverse(), но позволяет изменять элементы массива.
//! \~\sa \a forEach(), \a forEachReverse()
inline PIDeque<T> & forEachReverse(std::function<void(T & e)> f) {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(pid_data[i]);
}
return *this;
}
//! \~english Same as \a forEachIndexed() but from end to begin (from right to left).
//! \~russian Аналогично \a forEachIndexed() но от конца до начала (справа на лево).
//! \~\sa \a forEachIndexed(), \a forEachReverse(), \a forEach()
inline void forEachReverseIndexed(std::function<void(size_t index, const T & e)> f) const {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(i - pid_start, pid_data[i]);
}
}
//! \~english Same as \a forEachReverseIndexed(), but allows you to change the elements of the array.
//! \~russian Аналогично \a forEachReverseIndexed(), но позволяет изменять элементы массива.
//! \~\sa \a forEachReverseIndexed(), \a forEachIndexed(), \a forEachReverse(), \a forEach()
inline PIDeque<T> & forEachReverseIndexed(std::function<void(size_t index, T & e)> f) {
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
f(i - pid_start, pid_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 Создаёт новый массив с результатом вызова указанной функции
@@ -2096,12 +2237,12 @@ public:
//! once for each element in an array, in order,
//! and constructs a new array from the results.
//! \~russian Метод `map` вызывает переданную функцию `ST f(const T & e)`
//! один раз для каждого элемента в порядке их появления
//! один раз для каждого элемента в порядке их появления от начала к концу (слева на право)
//! и конструирует новый массив из результатов её вызова.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! PIStringList sl = v.map<PIString>([](const int & i){return PIString::fromNumber(i);});
//! piCout << sl; {"1", "2", "3"}
//! piCout << sl; // {"1", "2", "3"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST>
@@ -2113,6 +2254,57 @@ public:
return ret;
}
//! \~english Same as \a map() but with `index` parameter in `f`.
//! \~russian Аналогично \a map() но с параметром индекса `index` в функции `f`.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! PIStringList sl = v.mapIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
//! piCout << sl; // {"0", "1", "2"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
inline PIDeque<ST> mapIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size);
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
ret << f(i - pid_start, pid_data[i]);
}
return ret;
}
//! \~english Same as \a map() but from end to begin (from right to left).
//! \~russian Аналогично \a map() но от конца до начала (справа на лево).
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! PIStringList sl = v.mapReverse<PIString>([](const int & i){return PIString::fromNumber(i);});
//! piCout << sl; // {"3", "2", "1"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
inline PIDeque<ST> mapReverse(std::function<ST(const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret << f(pid_data[i]);
}
return ret;
}
//! \~english Same as \a mapReverse() but with `index` parameter in `f`.
//! \~russian Аналогично \a mapReverse() но с параметром индекса `index` в функции `f`.
//! \~\code
//! PIDeque<int> v{1, 2, 3};
//! PIStringList sl = v.mapReverseIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
//! piCout << sl; // {"2", "1", "0"}
//! \endcode
//! \~\sa \a mapReverse()
template <typename ST>
inline PIDeque<ST> mapReverseIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIDeque<ST> ret; ret.reserve(pid_size);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret << f(size_t(i) - pid_start, pid_data[i]);
}
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)`
@@ -2133,7 +2325,7 @@ public:
//! \param initial _optional_ Object used as the second argument
//! when the `f` function is first called.
//! \~russian Метод reduce() выполняет функцию `f`
//! один раз для каждого элемента, присутствующего в массиве.
//! один раз для каждого элемента, присутствующего в массиве от начала к концу (слева на право).
//! Если при вызове reduce() передан аргумент `initial`,
//! то при первом вызове функции `f` значение `acc`
//! будет равным значению `initial`.
@@ -2153,7 +2345,7 @@ public:
//! int s = v.reduce<int>([](const int & e, const int & acc){return e + acc;});
//! piCout << s; // 15
//! \endcode
//! \~\sa \a forEach(), \a map()
//! \~\sa \a reduceIndexed(), \a reduceReverse(), \a reduceReverseIndexed(), \a forEach(), \a map()
template <typename ST>
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
@@ -2163,6 +2355,42 @@ public:
return ret;
}
//! \~english Same as \a reduce() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduce()
template <typename ST>
inline ST reduceIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
ret = f(i - pid_start, pid_data[i], ret);
}
return ret;
}
//! \~english Same as \a reduce() but from end to begin (from right to left).
//! \~russian Аналогично \a reduce() но от конца до начала (справа на лево).
//! \~\sa \a reduce()
template <typename ST>
inline ST reduceReverse(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret = f(pid_data[i], ret);
}
return ret;
}
//! \~english Same as \a reduceReverse() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduceReverse()
template <typename ST>
inline ST reduceReverseIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = ssize_t(pid_start+pid_size) - 1; i >= ssize_t(pid_start); --i) {
ret = f(size_t(i) - pid_start, pid_data[i], ret);
}
return ret;
}
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
//! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
//! \~\details
@@ -2191,7 +2419,7 @@ public:
}
#endif
assert(rows*cols == pid_size);
ret.resize(rows);
ret.expand(rows);
if (order == ReshapeByRow) {
for (size_t r = 0; r < rows; r++) {
ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols);
@@ -2199,7 +2427,7 @@ public:
}
if (order == ReshapeByColumn) {
for (size_t r = 0; r < rows; r++) {
ret[r].resize(cols);
ret[r].expand(cols);
for (size_t c = 0; c < cols; c++) {
ret[r][c] = pid_data[c*rows + r];
}
@@ -2274,25 +2502,34 @@ public:
}
private:
inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
inline void _reset() {
pid_size = 0;
pid_rsize = 0;
pid_start = 0;
pid_data = nullptr;
}
inline size_t asize(ssize_t s) {
if (s <= 0) return 0;
if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) {
return pid_rsize + pid_rsize;
}
ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
while (s_ >> t)
++t;
size_t t = _PIContainerConstants<T>::minCountPoT();
size_t s_ = s - 1;
while (s_ >> t) ++t;
return (1 << t);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void newT(T * dst, const T * src, size_t s) {
PIINTROSPECTION_CONTAINER_USED(T, s)
for (size_t i = 0; i < s; ++i)
for (size_t i = 0; i < s; ++i) {
elementNew(dst + i, src[i]);
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
@@ -2300,56 +2537,78 @@ private:
PIINTROSPECTION_CONTAINER_USED(T, s)
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
if ((uchar*)d != 0) {
if (d != nullptr) {
for (size_t i = 0; i < sz; ++i) {
elementDelete(d[i]);
}
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T * to, const T & from) {new(to)T(from);}
inline void elementNew(T * to, const T & from) {
new(to)T(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
inline void elementNew(T * to, T && from) {
new(to)T(std::move(from));
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T1 * to, const T & from) {(*to) = from;}
inline void elementNew(T1 * to, const T & from) {
(*to) = from;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T * to, T && from) {(*to) = std::move(from);}
inline void elementNew(T * to, T && from) {
(*to) = std::move(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementDelete(T & from) {from.~T();}
inline void elementDelete(T & from) {
from.~T();
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementDelete(T & from) {}
inline void dealloc() {
if ((uchar*)pid_data != 0) free((uchar*)pid_data);
pid_data = 0;
if (pid_data != nullptr) {
free((void*)pid_data);
pid_data = nullptr;
}
}
inline void checkMove() {
if (pid_size >= 4) {
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))) {
ssize_t ns = (pid_rsize - pid_size) / 2;
if (pid_start < (pid_size * 2) || ssize_t(pid_start) > (ssize_t(pid_rsize) - (ssize_t(pid_size) * 2))) {
size_t ns = (pid_rsize - pid_size) / 2;
if (pid_start != ns) {
memmove((void*)(pid_data + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
pid_start = ns;
@@ -2357,61 +2616,82 @@ private:
}
}
} else {
ssize_t ns = (pid_rsize - pid_size) / 2;
size_t ns = (pid_rsize - pid_size) / 2;
if (pid_start != ns) {
memmove((void*)(pid_data + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
pid_start = ns;
}
}
}
inline void alloc_forward(size_t new_size) { // direction == true -> alloc forward
if (pid_start + new_size <= pid_rsize) {
pid_size = new_size;
checkMove();
return;
}
inline void alloc_forward(size_t new_size) {
if (pid_start + new_size <= pid_rsize) {
pid_size = new_size;
size_t as = asize(pid_start + new_size);
if (as != pid_rsize) {
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T)));
if (pid_start > 0) checkMove();
return;
}
pid_size = new_size;
size_t as = asize(pid_start + new_size);
if (as != pid_rsize) {
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
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));
}
if (!p_d) {
printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
}
#endif
assert(p_d);
pid_data = p_d;
pid_rsize = as;
}
}
inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) { //alloc backward
size_t as;
if (pid_start + start_offset < 0) {
as = asize(pid_rsize - start_offset);
} else {
as = pid_rsize;
}
if (as > pid_rsize) {
T * td = (T*)(malloc(as * sizeof(T)));
ssize_t ns = pid_start + as - pid_rsize;
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
if (pid_rsize > 0 && pid_data != 0) {
memcpy((void*)(td + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
dealloc();
}
pid_data = td;
pid_rsize = as;
pid_start = ns;
}
pid_start += start_offset;
pid_size = new_size;
checkMove();
assert(p_d);
pid_data = p_d;
pid_rsize = as;
}
}
T * pid_data;
size_t pid_size, pid_rsize;
ssize_t pid_start;
inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) {
size_t as;
if (ssize_t(pid_start) + start_offset < 0) {
as = asize(pid_rsize - start_offset);
} else {
as = pid_rsize;
}
if (as > pid_rsize) {
T * td = (T*)(malloc(as * sizeof(T)));
size_t ns = pid_start + as - pid_rsize;
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
if (pid_rsize > 0 && pid_data != 0) {
memcpy((void*)(td + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
dealloc();
}
pid_data = td;
pid_rsize = as;
pid_start = ns;
}
pid_start += start_offset;
pid_size = new_size;
checkMove();
}
inline void expand(size_t new_size, const T & e = T()) {
size_t os = pid_size;
alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, e);
}
}
inline void expand(size_t new_size, std::function<T(size_t i)> f) {
size_t os = pid_size;
alloc_forward(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
elementNew(pid_data + i, f(i));
}
}
T * pid_data = nullptr;
size_t pid_size = 0;
size_t pid_rsize = 0;
size_t pid_start = 0;
};
@@ -2437,14 +2717,14 @@ inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {
template<typename T>
inline PICout operator <<(PICout s, const PIDeque<T> & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "{";
for (size_t i = 0; i < v.size(); ++i) {
s << v[i];
if (i < v.size() - 1) s << ", ";
}
s << "}";
s.restoreControl();
s.restoreControls();
return s;
}

View File

@@ -1,187 +0,0 @@
/** \class PIMap
* \brief Associative array
* \details This class used to store Key = Value array of any
* type of data. \a value() returns value for key and leave map
* unchaged in any case. \a operator [] create entry in map if
* there is no entry for given key. You can retrieve all
* keys by method \a keys() and all values by methos \a values().
* To iterate all entries use class PIMapIterator, or methods
* \a makeIterator() and \a makeReverseIterator().
* \fn PIMap::PIMap();
* \brief Contructs an empty map
* \fn PIMap::PIMap(const PIMap & other);
* \brief Contructs a copy of "other"
* \fn PIMap & PIMap::operator =(const PIMap & other);
* \brief Copy operator
* \fn PIMap::PIMap(const PIMap & other);
* \brief Contructs a copy of "other"
* \fn PIMapIterator PIMap::makeIterator() const
* \brief Returns PIMapIterator for this map
* \fn PIMapIterator PIMap::makeReverseIterator() const
* \brief Returns reverse PIMapIterator for this map
* \fn size_t PIMap::size() const
* \brief Returns entries count
* \fn int PIMap::size_s() const
* \brief Returns entries count
* \fn size_t PIMap::length() const
* \brief Returns entries count
* \fn bool PIMap::isEmpty() const
* \brief Returns if map is empty
* \fn T & PIMap::operator [](const Key & key)
* \brief Returns value for key "key". If there is no key in map, create one.
* \fn const T PIMap::operator [](const Key & key) const
* \brief Returns value for key "key". If there is no key in map, returns default T().
* \fn T & PIMap::at(const Key & key)
* \brief Equivalent to operator []
* \fn const T PIMap::at(const Key & key) const
* \brief Equivalent to operator []
* \fn PIMap & PIMap::operator <<(const PIMap & other)
* \brief Insert all etries of "other" to this map. Override existing values.
* \fn bool PIMap::operator ==(const PIMap & t) const
* \brief Compare operator
* \fn bool PIMap::operator !=(const PIMap & t) const
* \brief Compare operator
* \fn bool PIMap::contains(const Key & key) const
* \brief Returns "true" if map contains entry with key "key"
* \fn PIMap & PIMap::reserve(size_t new_size)
* \brief Reserve space for "new_size" entries
* \fn PIMap & PIMap::removeOne(const Key & key)
* \brief Remove entry with key "key"
* \fn PIMap & PIMap::remove(const Key & key)
* \brief Equivalent \a removeOne(key)
* \fn PIMap & PIMap::erase(const Key & key)
* \brief Equivalent \a removeOne(key)
* \fn PIMap & PIMap::clear()
* \brief Clear map
* \fn void PIMap::swap(PIMap & other)
* \brief Swap map with "other"
* \fn PIMap & PIMap::insert(const Key & key, const T & value)
* \brief Insert or rewrite entry with key "key" and value "value"
* \fn const T PIMap::value(const Key & key, const T & default = T())
* \brief Returns value for key "key". If there is no key in map, returns "default".
* \fn PIVector<T> PIMap::values() const
* \brief Returns all values as PIVector
* \fn Key PIMap::key(const T & value, const Key & default = Key()) const
* \brief Returns key for first founded value "value". If there is no such value in map, returns "default".
* \fn PIVector<Key> PIMap::keys() const
* \brief Returns all keys as PIVector
* */
/** \class PIMapIterator
* \brief Helper class to iterate over PIMap
* \details This class used to access keys and values in PIMap.
* You can use constructor to create iterator, or use \a PIMap::makeIterator()
* and \a PIMap::makeReverseIterator() methods.
*
* First usage variant:
* \code
* PIMap<int, PIString> m;
* m[1] = "one";
* m[2] = "two";
* m[4] = "four";
*
* auto it = m.makeIterator();
* while (it.next()) {
* piCout << it.key() << it.value();
* }
* // 1 one
* // 2 two
* // 4 four
* \endcode
*
* Using hasNext():
* \code
* while (it.hasNext()) {
* it.next();
* \endcode
*
* Using constructor:
* \code
* PIMapIterator<int, PIString> it(m);
* \endcode
*
* Write access:
* \code
* while (it.next()) {
* it.valueRef().append("_!");
* piCout << it.key() << it.value();
* }
*
* // 1 one_!
* // 2 two_!
* // 4 four_!
* \endcode
*
* Reverse iterator:
* \code
* auto it = m.makeReverseIterator();
* while (it.next()) {
* piCout << it.key() << it.value();
* }
*
* // 4 four
* // 2 two
* // 1 one
* \endcode
* \fn PIMapIterator(const PIMap & map, bool reverse = false)
* \brief Contructs iterator for "map". Current position is invalid.
* \fn const Key & PIMapIterator::key() const
* \brief Returns current entry key
* \fn const T & PIMapIterator::value() const
* \brief Returns current entry value
* \fn T & PIMapIterator::valueRef() const
* \brief Returns reference to current entry value
* \fn bool PIMapIterator::hasNext()
* \brief Returns if iterator can jump to next entry
* \fn bool PIMapIterator::next()
* \brief Jump to next entry and return if new position is valid.
* \fn void PIMapIterator::reset()
* \brief Reset iterator to initial position.
* */

View File

@@ -1,8 +1,17 @@
/*! \file pimap.h
* \brief Associative array with custom types of key and value
*
* This file declares PIMap
*/
//! \addtogroup Containers
//! \{
//! \file pideque.h
//! \brief
//! \~english Declares \a PIMap
//! \~russian Объявление \a PIMap
//! \~\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
Associative array with custom types of key and value
@@ -30,40 +39,99 @@
#include "pipair.h"
template <typename Key, typename T>
class PIMapIterator;
template <typename Key, typename T> class PIMapIteratorConst;
template <typename Key, typename T> class PIMapIteratorConstReverse;
template <typename Key, typename T> class PIMapIterator;
template <typename Key, typename T> class PIMapIteratorReverse;
//! \addtogroup Containers
//! \{
//! \class PIMap
//! \brief
//! \~english Associative array.
//! \~russian Словарь.
//! \~\}
//! \details
//! \~english
//! A collection of key/value pairs, from which you retrieve a value using its associated key.
//! There is a finite number of keys in the map, and each key has exactly one value associated with it.
//! \a value() returns value for key and leave map
//! unchaged in any case. \a operator [] create entry in map if
//! there is no entry for given key. You can retrieve all
//! keys by method \a keys() and all values by methos \a values().
//! To iterate all entries use class PIMapIterator, or methods
//! \a makeIterator() and \a makeReverseIterator().
//! A key in the Map may only occur once.
//! \~russian
//! Словари, в принципе, похожи на обычные, используемые в повседневной жизни.
//! Они хранят элементы одного и того же типа, индексируемые ключевыми значениями.
//! Достоинство словаря в том, что он позволяет быстро получать значение,
//! ассоциированное с заданным ключом.
//! Ключи должны быть уникальными.
//! Элемент
//! В контейнеры этого типа заносятся элементы вместе с ключами,
//! по которым их можно найти, которыми могут выступать значения любого типа.
//! \a operator [] позволяет получить доступ к элементу по ключу,
//! и если такого эелемента не было, то он будет создан.
template <typename Key, typename T>
class PIMap {
template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, 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 PIMapIteratorConst;
template <typename Key1, typename T1> friend class PIMapIteratorConstReverse;
template <typename Key1, typename T1> friend class PIMapIterator;
template <typename Key1, typename T1> friend class PIMapIteratorReverse;
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMap<Key1, T1> & v);
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMap<Key1, T1> & v);
public:
PIMap() {}
PIMap(const PIMap<Key, T> & other) {*this = other;}
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)) {}
PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
for (auto i: init_list)
insert(std::get<0>(i), std::get<1>(i));
}
virtual ~PIMap() {;}
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
if (this == &other) return *this;
clear();
pim_content = other.pim_content;
return *this;
}
PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
swap(other);
return *this;
}
typedef T mapped_type;
typedef Key key_type;
typedef PIPair<Key, T> value_type;
//! \~english Constructs an empty map.
//! \~russian Создает пустой словарь.
inline PIMap() {}
//! \~english Copy constructor.
//! \~russian Копирующий конструктор.
inline PIMap(const PIMap<Key, T> & other) : pim_content(other.pim_content), pim_index(other.pim_index) {}
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
inline PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
//! \~english Contructs map 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
//! PIMap <int, PIString> m{{1, "a"}, {2, "b"}};
//! piCout << m; // {1, 2, 3}
//! \endcode
inline PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
for (auto i: init_list) {
insert(std::get<0>(i), std::get<1>(i));
}
}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
if (this == &other) return *this;
clear();
pim_content = other.pim_content;
pim_index = other.pim_index;
return *this;
}
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
swap(other);
return *this;
}
class iterator {
friend class PIMap<Key, T>;
@@ -72,10 +140,12 @@ public:
const PIMap<Key, T> * parent;
ssize_t pos;
public:
iterator(): parent(0), pos(0) {}
iterator(): parent(nullptr), pos(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
inline PIPair<Key, T> operator *() const {return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));}
inline PIPair<Key, T> operator *() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));
}
void operator ++() {++pos;}
void operator ++(int) {++pos;}
void operator --() {--pos;}
@@ -91,10 +161,12 @@ public:
const PIMap<Key, T> * parent;
ssize_t pos;
public:
reverse_iterator(): parent(0), pos(0) {}
reverse_iterator(): parent(nullptr), pos(0) {}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
inline PIPair<Key, T> operator *() const {return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));}
inline PIPair<Key, T> operator *() const {
return PIPair<Key, T>(const_cast<PIMap<Key, T> * >(parent)->_key(pos), const_cast<PIMap<Key, T> * >(parent)->_value(pos));
}
void operator ++() {--pos;}
void operator ++(int) {--pos;}
void operator --() {++pos;}
@@ -110,9 +182,8 @@ public:
const PIMap<Key, T> * parent;
ssize_t pos;
public:
const_iterator(): parent(0), pos(0) {}
const_iterator(): parent(nullptr), pos(0) {}
const value_type operator *() const {return parent->_pair(pos);}
const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;}
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
const T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
void operator ++() {++pos;}
@@ -121,7 +192,6 @@ public:
void operator --(int) {--pos;}
bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
mutable value_type cval;
};
class const_reverse_iterator {
@@ -131,54 +201,121 @@ public:
const PIMap<Key, T> * parent;
ssize_t pos;
public:
const_reverse_iterator(): parent(0), pos(0) {}
const_reverse_iterator(): parent(nullptr), pos(0) {}
const value_type operator *() const {return parent->_pair(pos);}
const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;}
void operator ++() {--pos;}
void operator ++(int) {--pos;}
void operator --() {++pos;}
void operator --(int) {++pos;}
bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
mutable value_type cval;
};
iterator begin() {return iterator(this, 0);}
iterator end() {return iterator(this, size());}
const_iterator begin() const {return const_iterator(this, 0);}
const_iterator end() const {return const_iterator(this, size());}
const_iterator constBegin() const {return const_iterator(this, 0);}
const_iterator constEnd() const {return const_iterator(this, size());}
reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);}
reverse_iterator rend() {return reverse_iterator(this, -1);}
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);}
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);}
const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);}
PIMapIterator<Key, T> makeIterator() const {return PIMapIterator<Key, T>(*this);}
PIMapIterator<Key, T> makeReverseIterator() const {return PIMapIterator<Key, T>(*this, true);}
//! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент.
inline iterator begin() {return iterator(this, 0);}
size_t size() const {return pim_content.size();}
int size_s() const {return pim_content.size_s();}
size_t length() const {return pim_content.size();}
bool isEmpty() const {return (pim_content.size() == 0);}
T & operator [](const Key & key) {
//! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
inline iterator end() {return iterator(this, size());}
inline const_iterator begin() const {return const_iterator(this, 0);}
inline const_iterator end() const {return const_iterator(this, size());}
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
inline reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);}
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент,
//! следующий за последним элементом.
inline reverse_iterator rend() {return reverse_iterator(this, -1);}
inline const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);}
inline const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
//! \relatesalso PIMapIteratorConst
inline PIMapIteratorConst<Key, T> makeIterator() const {return PIMapIteratorConst<Key, T>(*this);}
//! \relatesalso PIMapIterator
inline PIMapIterator<Key, T> makeIterator() {return PIMapIterator<Key, T>(*this);}
//! \relatesalso PIMapIteratorConstReverse
inline PIMapIteratorConstReverse<Key, T> makeReverseIterator() const {return PIMapIteratorConstReverse<Key, T>(*this);}
//! \relatesalso PIMapIteratorReverse
inline PIMapIteratorReverse<Key, T> makeReverseIterator() {return PIMapIteratorReverse<Key, T>(*this);}
//! \~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 pim_content.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 int size_s() const {return pim_content.size_s();}
//! \~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 pim_content.size();}
//! \~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 (pim_content.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 (pim_content.size() > 0);}
//! \~english Full access to element key `key`.
//! \~russian Полный доступ к элементу по ключу `key`.
//! \~\details
//! \~english If the map contains no item with key `key`,
//! the function inserts a default-constructed value into the map with key `key`,
//! and returns a reference to it.
//! \~russian Если элемента с таким ключом `key` не существует,
//! то он будет создан конструктором по умолчанию и добавлен в массив
//! по ключу `key`, а затем возвращена ссылка на этот новый элемент.
//! \~\sa \a insert(), \a value(), \a key()
inline T & operator [](const Key & key) {
bool f(false);
ssize_t i = _find(key, f);
if (!f) pim_content.insert(i, PIPair<Key, T>(key, T()));
return pim_content[i].second;
if (f) return pim_content[pim_index[i].index];
pim_content.push_back(T());
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
return pim_content.back();
}
const T operator [](const Key & key) const {
//! \~english Same as \a value().
//! \~russian Синоним \a value().
//! \~\sa \a operator[](), \a value(), \a key()
inline T at(const Key & key) const {return value(key);}
inline T take(const Key & key) const {
bool f(false);
ssize_t i = _find(key, f);
if (f) return pim_content[i].second;
return T();
if (!f) return T();
T ret(pim_content[pim_index[i].index]);
_remove(i);
return ret;
}
const T at(const Key & key) const {return (*this)[key];}
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
//! \~english Inserts all elements in array `other` to this array with overwrite.
//! \~russian Вставляет все элементы `other` этот массив с перезаписью.
inline 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));
@@ -186,172 +323,555 @@ public:
#endif
assert(&other != 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() == 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)
insert(other.pim_content[i].first, other.pim_content[i].second);
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;
}
for (int i = 0; i < other.pim_index.size_s(); ++i) {
insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]);
}
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);}
bool contains(const Key & key) const {bool f(false); _find(key, f); return f;}
//! \~english Compare operator with array `m`.
//! \~russian Оператор сравнения с массивом `m`.
inline bool operator ==(const PIMap<Key, T> & m) const {
return (pim_content == m.pim_content && pim_index == m.pim_index);
}
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size);return *this;}
//! \~english Compare operator with array `m`.
//! \~russian Оператор сравнения с массивом `m`.
inline bool operator !=(const PIMap<Key, T> & m) const {
return (pim_content != m.pim_content || pim_index != m.pim_index);
}
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> & erase(const Key & key) {return removeOne(key);}
PIMap<Key, T> & clear() {pim_content.clear(); return *this;}
//! \~english Tests if element with key `key` exists in the array.
//! \~russian Проверяет наличие элемента с ключом `key` в массиве.
inline bool contains(const Key & key) const {
bool f(false); _find(key, f);
return f;
}
inline bool containsValue(const T & value) const {
return pim_content.contains(value);
}
inline PIMap<Key, T> & reserve(size_t new_size) {
pim_content.reserve(new_size);
pim_index.reserve(new_size);
return *this;
}
inline PIMap<Key, T> & remove(const Key & key) {
bool f(false);
ssize_t i = _find(key, f);
if (f) _remove(i);
return *this;
}
inline PIMap<Key, T> & removeWhere(std::function<bool(const Key & key, const T & value)> test) {
for (int i = 0; i < pim_index.size_s(); ++i) {
if (pim_index[i].key, pim_content[pim_index[i].index]) {
_remove(i);
--i;
}
}
}
inline PIMap<Key, T> & erase(const Key & key) {return remove(key);}
inline PIMap<Key, T> & clear() {
pim_content.clear();
pim_index.clear();
return *this;
}
void swap(PIMap<Key, T> & other) {
inline void swap(PIMap<Key, T> & other) {
pim_content.swap(other.pim_content);
pim_index.swap(other.pim_index);
}
PIMap<Key, T> & insert(const Key & key, const T & value) {
inline PIMap<Key, T> & insert(const Key & key, const T & value) {
bool f(false);
ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) {
pim_content[i].second = value;
pim_content[pim_index[i].index] = value;
} 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;
}
PIMap<Key, T> & insert(const Key & key, T && value) {
inline PIMap<Key, T> & insert(const Key & key, T && value) {
bool f(false);
ssize_t i = _find(key, f);
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
if (f) {
pim_content[i].second = std::move(value);
pim_content[pim_index[i].index] = std::move(value);
} else {
// pim_content.push_back(std::move(value));
// pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
pim_content.insert(i, PIPair<Key, T>(key, std::move(value)));
pim_content.push_back(std::move(value));
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
}
return *this;
}
const T value(const Key & key, const T & default_ = T()) const {
inline PIMap<Key, T> & insert(const PIPair<Key, T> & pair) {
bool f(false);
ssize_t i = _find(pair.first, f);
if (f) {
pim_content[pim_index[i].index] = pair.second;
} else {
pim_content.push_back(pair.second);
pim_index.insert(i, MapIndex(pair.first, pim_content.size() - 1));
}
return *this;
}
inline PIMap<Key, T> & insert(PIPair<Key, T> && pair) {
bool f(false);
Key k(std::move(pair.first));
ssize_t i = _find(k, f);
if (f) {
pim_content[pim_index[i].index] = std::move(pair.second);
} else {
pim_content.push_back(std::move(pair.second));
pim_index.insert(i, MapIndex(k, pim_content.size() - 1));
}
return *this;
}
inline 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[i].second;
return pim_content[pim_index[i].index];
}
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;
inline PIVector<T> values() const {return pim_content;}
inline 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_;
}
PIVector<Key> keys() const {
inline PIVector<Key> keys() const {
PIVector<Key> ret;
for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].first;
ret.reserve(pim_index.size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret << pim_index[i].key;
}
return ret;
}
inline void forEach(std::function<void(const Key & key, const T & value)> f) const {
for (int i = 0; i < pim_index.size_s(); ++i) {
f(pim_index[i].key, pim_content[pim_index[i].index]);
}
}
template <typename Key2, typename T2>
inline PIMap<Key2, T2> map(std::function<PIPair<Key2, T2>(const Key & key, const T & value)> f) const {
PIMap<Key2, T2> ret; ret.reserve(size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret.insert(f(pim_index[i].key, pim_content[pim_index[i].index]));
}
return ret;
}
template <typename ST>
inline PIVector<ST> map(std::function<ST(const Key & key, const T & value)> f) const {
PIVector<ST> ret; ret.reserve(size());
for (int i = 0; i < pim_index.size_s(); ++i) {
ret << f(pim_index[i].key, pim_content[pim_index[i].index]);
}
return ret;
}
void dump() {
piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:";
for (size_t i = 0; i < pim_content.size(); ++i)
piCout << PICoutManipulators::Tab << i << ":" << pim_content[i];
// piCout << "index:";
// for (size_t i = 0; i < pim_index.size(); ++i)
// piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index;
}
protected:
// struct MapIndex {
// MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;}
// Key key;
// 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;}
// };
// 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);
private:
struct MapIndex {
MapIndex(const Key & k = Key(), size_t i = 0): key(k), index(i) {}
MapIndex(Key && k, size_t i = 0): key(std::move(k)), index(i) {}
Key key;
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;}
};
ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
template <typename P, typename Key1, typename T1>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
inline ssize_t _binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
ssize_t mid;
while (first <= last) {
mid = (first + last) / 2;
if (key > pim_content[mid].first) first = mid + 1;
else if (key < pim_content[mid].first) last = mid - 1;
if (key > pim_index[mid].key) first = mid + 1;
else if (key < pim_index[mid].key) last = mid - 1;
else {found = true; return mid;}
}
found = false;
return first;
}
ssize_t _find(const Key & k, bool & found) const {
if (pim_content.isEmpty()) {
inline ssize_t _find(const Key & k, bool & found) const {
if (pim_index.isEmpty()) {
found = false;
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) {
pim_content.remove(index);
inline void _remove(ssize_t index) {
size_t ci = pim_index[index].index, bi = pim_index.size() - 1;
pim_index.remove(index);
for (size_t i = 0; i < pim_index.size(); ++i) {
if (pim_index[i].index == bi) {
pim_index[i].index = ci;
break;
}
}
piSwap<T>(pim_content[ci], pim_content.back());
pim_content.resize(pim_index.size());
}
const value_type _pair(ssize_t index) const {
if (index < 0 || index >= pim_content.size_s()) return value_type();
return pim_content[index];
inline const value_type _pair(ssize_t index) const {
if (index < 0 || index >= pim_index.size_s()) return value_type();
return value_type(pim_index[index].key, pim_content[pim_index[index].index]);
}
Key & _key(ssize_t index) {return pim_content[index].first;}
T & _value(ssize_t index) {return pim_content[index].second;}
inline Key & _key(ssize_t index) {return pim_index[index].key;}
inline const Key & _key(ssize_t index) const {return pim_index[index].key;}
inline T & _value(ssize_t index) {return pim_content[pim_index[index].index];}
inline const T & _value(ssize_t index) const {return pim_content[pim_index[index].index];}
PIDeque<PIPair<Key, T>> pim_content;
PIVector<T> pim_content;
PIDeque<MapIndex> pim_index;
};
//! \addtogroup Containers
//! \{
//! \class PIMapIteratorConst
//! \brief
//! \~english Java-style iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap.
//! \~\}
//! \details
//! \~english
//! This class used to easy serial access keys and values in PIMap with read only permitions.
//! Use constructor to create iterator, or use \a PIMap::makeIterator()
//! \~russian
//! Этот класс используется для удобного перебора ключей и значений всего словаря только для чтения.
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeIterator().
//! \~
//! \code
//! PIMap<int, PIString> m;
//! m[1] = "one";
//! m[2] = "two";
//! m[4] = "four";
//! auto it = m.makeIterator();
//! while (it.next()) {
//! piCout << it.key() << it.value();
//! }
//! // 1 one
//! // 2 two
//! // 4 four
//! \endcode
template <typename Key, typename T>
class PIMapIterator {
class PIMapIteratorConst {
typedef PIMap<Key, T> MapType;
public:
PIMapIterator(const PIMap<Key, T> & map, bool reverse = false): m(map), pos(-1), rev(reverse) {
if (rev) pos = m.size_s();
inline PIMapIteratorConst(const PIMap<Key, T> & map): m(map), pos(-1) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
const Key & key() const {return const_cast<MapType & >(m)._key(pos);}
const T & value() const {return const_cast<MapType & >(m)._value(pos);}
T & valueRef() const {return const_cast<MapType & >(m)._value(pos);}
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline const T & value() const {
return m._value(pos);
}
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
if (rev) {
return pos > 0;
} else {
return pos < (m.size_s() - 1);
}
return false;
return pos < (m.size_s() - 1);
}
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
//! \~\sa \a hasNext(), \a reset()
inline bool next() {
if (rev) {
--pos;
return pos >= 0;
} else {
++pos;
return pos < m.size_s();
}
return false;
++pos;
return pos < m.size_s();
}
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
if (rev) {
pos = m.size_s();
} else {
pos = -1;
}
pos = -1;
}
private:
const MapType & m;
ssize_t pos;
bool rev;
};
//! \addtogroup Containers
//! \{
//! \class PIMapIteratorConstReverse
//! \brief
//! \~english Java-style reverse iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap в обратном порядке.
//! \~\}
//! \details
//! \~english
//! This class used to easy serial reverse access keys and values in PIMap with read only permitions.
//! Use constructor to create iterator, or use \a PIMap::makeReverseIterator().
//! \~russian
//! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке только для чтения.
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeReverseIterator().
//! \~
//! \code
//! PIMap<int, PIString> m;
//! m[1] = "one";
//! m[2] = "two";
//! m[4] = "four";
//! auto it = m.makeReverseIterator();
//! while (it.next()) {
//! piCout << it.key() << it.value();
//! }
//! // 4 four
//! // 2 two
//! // 1 one
//! \endcode
template <typename Key, typename T>
class PIMapIteratorConstReverse {
typedef PIMap<Key, T> MapType;
public:
inline PIMapIteratorConstReverse(const PIMap<Key, T> & map): m(map), pos(m.size_s()) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline const T & value() const {
return m._value(pos);
}
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
return pos > 0;
}
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
//! \~\sa \a hasNext(), \a reset()
inline bool next() {
--pos;
return pos >= 0;
}
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
pos = m.size_s();
}
private:
const MapType & m;
ssize_t pos;
};
//! \addtogroup Containers
//! \{
//! \class PIMapIterator
//! \brief
//! \~english Java-style iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap.
//! \~\}
//! \details
//! \~english
//! This class used to easy serial access keys and values in PIMap with write permitions.
//! Use constructor to create iterator, or use \a PIMap::makeIterator()
//! \~russian
//! Этот класс используется для удобного перебора ключей и значений всего словаря с доступом на запись.
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeIterator().
//! \~
//! \code
//! PIMap<int, PIString> m;
//! m[1] = "one";
//! m[2] = "two";
//! m[4] = "four";
//! auto it = m.makeIterator();
//! while (it.next()) {
//! it.value().append("_!");
//! piCout << it.key() << it.value();
//! }
//! // 1 one_!
//! // 2 two_!
//! // 4 four_!
//! \endcode
template <typename Key, typename T>
class PIMapIterator {
typedef PIMap<Key, T> MapType;
public:
inline PIMapIterator(PIMap<Key, T> & map): m(map), pos(-1) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline T & value() {
return m._value(pos);
}
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
return pos < (m.size_s() - 1);
}
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
//! \~\sa \a hasNext(), \a reset()
inline bool next() {
++pos;
return pos < m.size_s();
}
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
pos = -1;
}
private:
MapType & m;
ssize_t pos;
};
//! \addtogroup Containers
//! \{
//! \class PIMapIteratorReverse
//! \brief
//! \~english Java-style reverse iterator for \a PIMap.
//! \~russian Итератор Java стиля для \a PIMap в обратном порядке.
//! \~\}
//! \details
//! \~english
//! This class used to easy serial reverse access keys and values in PIMap with write permitions.
//! Use constructor to create iterator, or use \a PIMap::makeReverseIterator().
//! \~russian
//! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке с доступом на запись.
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeReverseIterator().
//! \~
//! \code
//! PIMap<int, PIString> m;
//! m[1] = "one";
//! m[2] = "two";
//! m[4] = "four";
//! auto it = m.makeReverseIterator();
//! while (it.next()) {
//! it.value().append("_!");
//! piCout << it.key() << it.value();
//! }
//! // 4 four_!
//! // 2 two_!
//! // 1 one_!
//! \endcode
template <typename Key, typename T>
class PIMapIteratorReverse {
typedef PIMap<Key, T> MapType;
public:
inline PIMapIteratorReverse(PIMap<Key, T> & map): m(map), pos(m.size_s()) {}
//! \~english Returns current key.
//! \~russian Возвращает ключ текущего элемента.
//! \~\sa \a value()
inline const Key & key() const {
return m._key(pos);
}
//! \~english Returns current value.
//! \~russian Возвращает значение текущего элемента.
//! \~\sa \a key()
inline T & value() {
return m._value(pos);
}
//! \~english Returns true if iterator can jump to next entry
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
//! \~\sa \a next()
inline bool hasNext() const {
return pos > 0;
}
//! \~english Jump to next entry and return true if new position is valid.
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
//! \~\sa \a hasNext(), \a reset()
inline bool next() {
--pos;
return pos >= 0;
}
//! \~english Reset iterator to initial position.
//! \~russian Переходит на начало.
//! \~\sa \a next()
inline void reset() {
pos = m.size_s();
}
private:
MapType & m;
ssize_t pos;
};
#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 Key, typename Type>
inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v) {
s << "{";
@@ -360,31 +880,36 @@ inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v)
if (!first)
s << ", ";
first = false;
s << i->first << ": " << i->second;
s << i.key() << ": " << i.value();
}
s << "}";
return s;
}
#endif
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename Key, typename Type>
inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "{";
bool first = true;
for (typename PIMap<Key, Type>::const_iterator i = v.begin(); i != v.end(); ++i) {
if (!first)
s << ", ";
first = false;
s << i->first << ": " << i->second;
s << i.key() << ": " << i.value();
}
s << "}";
s.restoreControl();
s.restoreControls();
return s;
}
template<typename Key, typename Type> inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
template<typename Key, typename Type>
inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
#endif // PIMAP_H

View File

@@ -114,9 +114,9 @@ inline std::ostream & operator <<(std::ostream & s, const PIPair<Type0, Type1> &
template<typename Type0, typename Type1>
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "(" << v.first << ", " << v.second << ")";
s.restoreControl();
s.restoreControls();
return s;
}
@@ -133,6 +133,7 @@ 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()
@@ -141,4 +142,5 @@ PIPair<T1,T2> createPIPair(T1 && f, T2 && s) {
return PIPair<T1,T2>(std::move(f), std::move(s));
}
#endif // PIPAIR_H

View File

@@ -33,19 +33,13 @@ template<typename T>
class PIQueue: public PIDeque<T> {
public:
PIQueue() {}
virtual ~PIQueue() {}
PIDeque<T> & enqueue(const T & v) {PIDeque<T>::push_front(v); return *this;}
PIDeque<T> & enqueue(T && v) {PIDeque<T>::push_front(std::move(v)); return *this;}
T dequeue() {return PIDeque<T>::take_back();}
T & head() {return PIDeque<T>::back();}
const T & head() const {return PIDeque<T>::back();}
PIVector<T> toVector() {
PIVector<T> v;
v.reserve(PIDeque<T>::size());
for (uint i = 0; i < PIDeque<T>::size(); ++i)
v.push_back(PIDeque<T>::at(i));
return v;
}
PIVector<T> toVector() {return PIVector<T>(PIDeque<T>::data(), PIDeque<T>::size());}
PIDeque<T> toDeque() {return PIDeque<T>(*this);}
};
#endif // PIQUEUE_H

View File

@@ -42,8 +42,6 @@ public:
//! Contructs an empty set
PISet() {}
virtual ~PISet() {;}
//! Contructs set with one element "value"
PISet(const T & value) {_CSet::insert(value, 0);}
@@ -87,14 +85,14 @@ public:
//! Unite set with "v"
PISet<T> & unite(const PISet<T> & v) {
for (typename PIMap<T, uchar>::const_iterator i = v.begin(); i != v.end(); ++i)
_CSet::insert(i->first, 0);
_CSet::insert(i.key(), 0);
return *this;
}
//! Subtract set with "v"
PISet<T> & subtract(const PISet<T> & v) {
for (typename PIMap<T, uchar>::const_iterator i = v.begin(); i != v.end(); ++i)
_CSet::remove(i->first);
_CSet::remove(i.key());
return *this;
}
@@ -121,10 +119,10 @@ public:
PISet<T> & operator &=(const PISet<T> & v) {return intersect(v);}
//! Returns content of set as PIVector
PIVector<T> toVector() const {PIVector<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << (*i).first; return ret;}
PIVector<T> toVector() const {PIVector<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << i.key(); return ret;}
//! Returns content of set as PIDeque
PIDeque<T> toDeque() const {PIDeque<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << (*i).first; return ret;}
PIDeque<T> toDeque() const {PIDeque<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << i.key(); return ret;}
};
@@ -145,17 +143,17 @@ template <typename T> PISet<T> operator &(const PISet<T> & v0, const PISet<T> &
template<typename Type>
inline PICout operator <<(PICout s, const PISet<Type> & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "{";
bool first = true;
for (typename PIMap<Type, uchar>::const_iterator i = v.begin(); i != v.end(); ++i) {
if (!first)
s << ", ";
first = false;
s << i->first;
s << i.key();
}
s << "}";
s.restoreControl();
s.restoreControls();
return s;
}

View File

@@ -26,24 +26,19 @@
#define PISTACK_H
#include "pivector.h"
#include "pideque.h"
template<typename T>
class PIStack: public PIVector<T> {
public:
PIStack() {;}
virtual ~PIStack() {;}
PIStack() {}
PIVector<T> & push(const T & v) {PIVector<T>::push_back(v); return *this;}
PIVector<T> & push(T && v) {PIVector<T>::push_back(std::move(v)); return *this;}
T pop() {return PIVector<T>::take_back();}
T & top() {return PIVector<T>::back();}
const T & top() const {return PIVector<T>::back();}
PIVector<T> toVector() {
PIVector<T> v;
v.reserve(PIVector<T>::size());
for (uint i = 0; i < PIVector<T>::size(); ++i)
v.push_back(PIVector<T>::at(i));
return v;
}
PIVector<T> toVector() {return PIVector<T>(*this);}
PIDeque<T> toDeque() {return PIDeque<T>(PIVector<T>::data(), PIVector<T>::size());}
};
#endif // PISTACK_H

View File

@@ -127,7 +127,7 @@ public:
//! \~english Constructs an empty array.
//! \~russian Создает пустой массив.
inline PIVector(): piv_data(0), piv_size(0), piv_rsize(0) {
inline PIVector() {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
}
@@ -135,7 +135,7 @@ public:
//! 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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(size);
newT(piv_data, data, piv_size);
@@ -143,7 +143,7 @@ public:
//! \~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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(v.piv_size);
newT(piv_data, v.piv_data, piv_size);
@@ -158,7 +158,7 @@ public:
//! 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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
alloc(init_list.size());
newT(piv_data, init_list.begin(), init_list.size());
@@ -166,9 +166,9 @@ public:
//! \~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) {
inline PIVector(size_t size, const T & e = T()) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(size, e);
expand(size, e);
}
//! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
@@ -184,24 +184,26 @@ public:
//! 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) {
inline PIVector(size_t size, std::function<T(size_t i)> f) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
resize(size, f);
expand(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) {
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
piv_data = v.piv_data;
piv_size = v.piv_size;
piv_rsize = v.piv_rsize;
v._reset();
}
inline virtual ~PIVector() {
inline ~PIVector() {
PIINTROSPECTION_CONTAINER_DELETE(T)
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
deleteT(piv_data, piv_size);
dealloc();
_reset();
}
//! \~english Assign operator.
@@ -645,7 +647,7 @@ public:
inline size_t length() const {return piv_size;}
//! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
//! \~\details
//! \~english To find out the actual number of items, use the function \a size().
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
@@ -653,18 +655,18 @@ public:
inline size_t capacity() const {return piv_rsize;}
//! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли контейнер.
//! \~russian Проверяет пуст ли массив.
//! \~\return
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если контейнер пуст, **false** иначе.
//! \~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);}
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли контейнер.
//! \~russian Проверяет не пуст ли массив.
//! \~\return
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если контейнер не пуст, **false** иначе.
//! \~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);}
@@ -748,6 +750,31 @@ public:
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const T & at(size_t index) const {return piv_data[index];}
//! \~english Returns the first element of the array that
//! passes the test implemented by the provided function `test`
//! or `def` if there is no such element.
//! \~russian Возвращает первый элемент массива, проходящего по условию,
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a indexWhere()
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
ssize_t i = indexWhere(test, start);
if (i < 0) return def;
else return at(i);
}
//! \~english Returns the last element of the array that
//! passes the test implemented by the provided function `test`
//! or `def` if there is no such element.
//! \~russian Возвращает последний элемент массива, проходящего по условию,
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
//! \~\sa \a lastIndexWhere()
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
ssize_t i = lastIndexWhere(test, start);
if (i < 0) return def;
else return at(i);
}
//! \~english Last element.
//! \~russian Последний элемент массива.
//! \~\details
@@ -802,7 +829,7 @@ public:
//! возвращается **false**, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIVector<int> v{1, 2, 3, 4};
@@ -829,6 +856,33 @@ public:
return false;
}
//! \~english Tests if all elements of `v` exists in the array.
//! \~russian Проверяет наличие всех элементов `v` в массиве.
//! \~\details
//! \~\code
//! PIVector<int> v{1, 2, 3, 4};
//! piCout << v.contains({1,4}); // true
//! piCout << v.contains({1,5}); // false
//! \endcode
//! \~\sa \a every(), \a any(), \a entries(), \a forEach()
inline bool contains(const PIVector<T> & v, ssize_t start = 0) const {
if (start < 0) {
start = piv_size + start;
if (start < 0) start = 0;
}
for (const T & e : v) {
bool c = false;
for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) {
c = true;
break;
}
}
if (!c) return false;
}
return true;
}
//! \~english Count elements equal `e` in the array.
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
//! \~\details
@@ -845,7 +899,7 @@ public:
//! возвращается 0, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIVector<int> v{2, 2, 4, 2, 6};
@@ -885,7 +939,7 @@ public:
//! возвращается 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 {
@@ -918,7 +972,7 @@ public:
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIVector<int> v{2, 5, 9};
@@ -959,7 +1013,7 @@ public:
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIVector<PIString> v{"do", "re", "mi", "re"};
@@ -999,7 +1053,7 @@ public:
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
@@ -1042,7 +1096,7 @@ public:
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
@@ -1123,7 +1177,8 @@ public:
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline PIVector<T> & clear() {
resize(0);
deleteT(piv_data, piv_size);
piv_size = 0;
return *this;
}
template<typename T1 = T, typename std::enable_if<
@@ -1207,17 +1262,10 @@ public:
//! \~\sa \a size(), \a clear()
inline PIVector<T> & resize(size_t new_size, const T & e = T()) {
if (new_size < piv_size) {
T * de = &(piv_data[new_size]);
deleteT(de, piv_size - new_size);
deleteT(&(piv_data[new_size]), piv_size - new_size);
piv_size = new_size;
}
if (new_size > piv_size) {
size_t os = piv_size;
alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, e);
}
} else if (new_size > piv_size) {
expand(new_size, e);
}
return *this;
}
@@ -1238,14 +1286,8 @@ public:
T * de = &(piv_data[new_size]);
deleteT(de, piv_size - new_size);
piv_size = new_size;
}
if (new_size > piv_size) {
size_t os = piv_size;
alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, f(i));
}
} else if (new_size > piv_size) {
expand(new_size, f);
}
return *this;
}
@@ -1254,12 +1296,14 @@ public:
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline PIVector<T> & _resizeRaw(size_t new_size) {
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
if (new_size > piv_size) {
PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size));
}
if (new_size < piv_size) {
PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size));
}
#endif
alloc(new_size);
return *this;
}
@@ -1384,7 +1428,10 @@ public:
inline PIVector<T> & remove(size_t index, size_t count = 1) {
if (count == 0) return *this;
if (index + count >= piv_size) {
resize(index);
if (index < piv_size) {
deleteT(&(piv_data[index]), piv_size - index);
piv_size = index;
}
return *this;
}
size_t os = piv_size - index - count;
@@ -1512,8 +1559,8 @@ public:
//! Если `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;
inline PIVector<T> & enlarge(ssize_t add_size, const T & e = T()) {
ssize_t ns = size_s() + add_size;
if (ns <= 0) clear();
else resize(size_t(ns), e);
return *this;
@@ -1880,7 +1927,8 @@ public:
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
inline PIVector<T> & pop_back() {
if (piv_size == 0) return *this;
resize(piv_size - 1);
deleteT(&(piv_data[piv_size-1]), 1);
piv_size = piv_size - 1;
return *this;
}
@@ -1972,6 +2020,39 @@ public:
return ret;
}
//! \~english Same as \a filter() but with `index` parameter in `test`.
//! \~russian Аналогично \a filter() но с параметром индекса `index` в функции `test`.
//! \~\sa \a filter()
inline PIVector<T> filterIndexed(std::function<bool(size_t index, const T & e)> test) const {
PIVector<T> ret;
for (size_t i = 0; i < piv_size; ++i) {
if (test(i, piv_data[i])) ret << piv_data[i];
}
return ret;
}
//! \~english Same as \a filter() but from end to begin (from right to left).
//! \~russian Аналогично \a filter() но от конца до начала (справа на лево).
//! \~\sa \a filter()
inline PIVector<T> filterReverse(std::function<bool(const T & e)> test) const {
PIVector<T> ret;
for (ssize_t i = piv_size; i >= 0; --i) {
if (test(piv_data[i])) ret << piv_data[i];
}
return ret;
}
//! \~english Same as \a filterReverse() but with `index` parameter in `test`.
//! \~russian Аналогично \a filterReverse() но с параметром индекса `index` в функции `test`.
//! \~\sa \a filterReverse()
inline PIVector<T> filterReverseIndexed(std::function<bool(size_t index, const T & e)> test) const {
PIVector<T> ret;
for (ssize_t i = piv_size; i >= 0; --i) {
if (test(i, 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
@@ -2012,6 +2093,63 @@ public:
return *this;
}
//! \~english Same as \a forEach() but with `index` parameter in `f`.
//! \~russian Аналогично \a forEach() но с параметром индекса `index` в функции `f`.
//! \~\sa \a forEach()
inline void forEachIndexed(std::function<void(size_t index, const T & e)> f) const {
for (size_t i = 0; i < piv_size; ++i) {
f(i, piv_data[i]);
}
}
//! \~english Same as \a forEachIndexed(), but allows you to change the elements of the array.
//! \~russian Аналогично \a forEachIndexed(), но позволяет изменять элементы массива.
//! \~\sa \a forEach(), \a forEachIndexed()
inline PIVector<T> & forEachIndexed(std::function<void(size_t index, T & e)> f) {
for (size_t i = 0; i < piv_size; ++i) {
f(i, piv_data[i]);
}
return *this;
}
//! \~english Same as \a forEach() but from end to begin (from right to left).
//! \~russian Аналогично \a forEach() но от конца до начала (справа на лево).
//! \~\sa \a forEach()
inline void forEachReverse(std::function<void(const T & e)> f) const {
for (ssize_t i = piv_size; i >= 0; --i) {
f(piv_data[i]);
}
}
//! \~english Same as \a forEachReverse(), but allows you to change the elements of the array.
//! \~russian Аналогично \a forEachReverse(), но позволяет изменять элементы массива.
//! \~\sa \a forEach(), \a forEachReverse()
inline PIVector<T> & forEachReverse(std::function<void(T & e)> f) {
for (ssize_t i = piv_size; i >= 0; --i) {
f(piv_data[i]);
}
return *this;
}
//! \~english Same as \a forEachIndexed() but from end to begin (from right to left).
//! \~russian Аналогично \a forEachIndexed() но от конца до начала (справа на лево).
//! \~\sa \a forEachIndexed(), \a forEachReverse(), \a forEach()
inline void forEachReverseIndexed(std::function<void(size_t index, const T & e)> f) const {
for (ssize_t i = piv_size; i >= 0; --i) {
f(i, piv_data[i]);
}
}
//! \~english Same as \a forEachReverseIndexed(), but allows you to change the elements of the array.
//! \~russian Аналогично \a forEachReverseIndexed(), но позволяет изменять элементы массива.
//! \~\sa \a forEachReverseIndexed(), \a forEachIndexed(), \a forEachReverse(), \a forEach()
inline PIVector<T> & forEachReverseIndexed(std::function<void(size_t index, T & e)> f) {
for (ssize_t i = piv_size; i >= 0; --i) {
f(i, 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 Создаёт новый массив с результатом вызова указанной функции
@@ -2026,7 +2164,7 @@ public:
//! \~\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"}
//! piCout << sl; // {"1", "2", "3"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST>
@@ -2038,6 +2176,57 @@ public:
return ret;
}
//! \~english Same as \a map() but with `index` parameter in `f`.
//! \~russian Аналогично \a map() но с параметром индекса `index` в функции `f`.
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! PIVector<PIString> sl = v.mapIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
//! piCout << sl; // {"0", "1", "2"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
inline PIVector<ST> mapIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size);
for (size_t i = 0; i < piv_size; ++i) {
ret << f(i, piv_data[i]);
}
return ret;
}
//! \~english Same as \a map() but from end to begin (from right to left).
//! \~russian Аналогично \a map() но от конца до начала (справа на лево).
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! PIVector<PIString> sl = v.mapReverse<PIString>([](const int & i){return PIString::fromNumber(i);});
//! piCout << sl; // {"3", "2", "1"}
//! \endcode
//! \~\sa \a map()
template <typename ST>
inline PIVector<ST> mapReverse(std::function<ST(const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size);
for (ssize_t i = piv_size; i >= 0; --i) {
ret << f(piv_data[i]);
}
return ret;
}
//! \~english Same as \a mapReverse() but with `index` parameter in `f`.
//! \~russian Аналогично \a mapReverse() но с параметром индекса `index` в функции `f`.
//! \~\code
//! PIVector<int> v{1, 2, 3};
//! PIVector<PIString> sl = v.mapReverseIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
//! piCout << sl; // {"2", "1", "0"}
//! \endcode
//! \~\sa \a mapReverse()
template <typename ST>
inline PIVector<ST> mapReverseIndexed(std::function<ST(size_t index, const T & e)> f) const {
PIVector<ST> ret; ret.reserve(piv_size);
for (ssize_t i = piv_size; i >= 0; --i) {
ret << f(i, piv_data[i]);
}
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)`
@@ -2088,6 +2277,42 @@ public:
return ret;
}
//! \~english Same as \a reduce() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduce()
template <typename ST>
inline ST reduceIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t i = 0; i < piv_size; ++i) {
ret = f(i, piv_data[i], ret);
}
return ret;
}
//! \~english Same as \a reduce() but from end to begin (from right to left).
//! \~russian Аналогично \a reduce() но от конца до начала (справа на лево).
//! \~\sa \a reduce()
template <typename ST>
inline ST reduceReverse(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = piv_size; i >= 0; --i) {
ret = f(piv_data[i], ret);
}
return ret;
}
//! \~english Same as \a reduceReverse() but with `index` parameter in `f`.
//! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`.
//! \~\sa \a reduceReverse()
template <typename ST>
inline ST reduceReverseIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (ssize_t i = piv_size; i >= 0; --i) {
ret = f(i, piv_data[i], ret);
}
return ret;
}
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
//! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
//! \~\details
@@ -2199,25 +2424,31 @@ public:
}
private:
inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;}
inline void _reset() {
piv_size = piv_rsize = 0;
piv_data = nullptr;
}
inline size_t asize(size_t s) {
if (s == 0) return 0;
if (piv_rsize + piv_rsize >= s && piv_rsize < s) {
return piv_rsize + piv_rsize;
}
ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
while (s_ >> t)
++t;
while (s_ >> t) ++t;
return (1 << t);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void newT(T * dst, const T * src, size_t s) {
PIINTROSPECTION_CONTAINER_USED(T, s)
for (size_t i = 0; i < s; ++i)
for (size_t i = 0; i < s; ++i) {
elementNew(dst + i, src[i]);
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
@@ -2225,51 +2456,90 @@ private:
PIINTROSPECTION_CONTAINER_USED(T, s)
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
if ((uchar*)d != 0) {
if (d != nullptr) {
for (size_t i = 0; i < sz; ++i) {
elementDelete(d[i]);
}
}
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T * to, const T & from) {new(to)T(from);}
inline void elementNew(T * to, const T & from) {
new(to)T(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
inline void elementNew(T * to, T && from) {
new(to)T(std::move(from));
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T1 * to, const T & from) {(*to) = from;}
inline void elementNew(T1 * to, const T & from) {
(*to) = from;
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementNew(T * to, T && from) {(*to) = std::move(from);}
inline void elementNew(T * to, T && from) {
(*to) = std::move(from);
}
template<typename T1 = T, typename std::enable_if<
!std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementDelete(T & from) {from.~T();}
inline void elementDelete(T & from) {
from.~T();
}
template<typename T1 = T, typename std::enable_if<
std::is_trivially_copyable<T1>::value
, int>::type = 0>
inline void elementDelete(T & from) {}
inline void dealloc() {
if ((uchar*)piv_data != 0) free((uchar*)piv_data);
piv_data = 0;
if (piv_data != nullptr) free((uchar*)piv_data);
piv_data = nullptr;
piv_size = piv_rsize = 0;
}
inline void expand(size_t new_size, const T & e = T()) {
size_t os = piv_size;
alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, e);
}
}
inline void expand(size_t new_size, std::function<T(size_t i)> f) {
size_t os = piv_size;
alloc(new_size);
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
for (size_t i = os; i < new_size; ++i) {
elementNew(piv_data + i, f(i));
}
}
inline void alloc(size_t new_size) {
if (new_size <= piv_rsize) {
piv_size = new_size;
@@ -2290,8 +2560,9 @@ private:
piv_rsize = as;
}
T * piv_data;
size_t piv_size, piv_rsize;
T * piv_data = nullptr;
size_t piv_size = 0;
size_t piv_rsize = 0;
};
@@ -2316,7 +2587,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {
template<typename T>
inline PICout operator <<(PICout s, const PIVector<T> & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "{";
for (size_t i = 0; i < v.size(); ++i) {
s << v[i];
@@ -2325,7 +2596,7 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
}
}
s << "}";
s.restoreControl();
s.restoreControls();
return s;
}

View File

@@ -39,17 +39,21 @@ template <typename T>
class PIVector2D {
public:
inline PIVector2D() {rows_ = cols_ = 0;}
inline PIVector2D(size_t rows, size_t cols, const T & f = T()) {
rows_ = rows;
cols_ = cols;
mat.resize(rows*cols, f);
}
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) : rows_(rows), cols_(cols), mat(v) {
mat.resize(rows*cols);
}
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v) : rows_(rows), cols_(cols), mat(std::move(v)) {
mat.resize(rows*cols);
}
inline PIVector2D(const PIVector<PIVector<T>> & v) {
rows_ = v.size();
if (rows_) {
@@ -64,13 +68,21 @@ public:
}
inline size_t rows() const {return rows_;}
inline size_t cols() const {return cols_;}
inline size_t size() const {return mat.size();}
inline ssize_t size_s() const {return mat.size_s();}
inline size_t length() const {return mat.length();}
inline size_t capacity() const {return mat.capacity();}
inline bool isEmpty() const {return mat.isEmpty();}
inline bool isNotEmpty() const {return mat.isNotEmpty();}
class Row {
friend class PIVector2D<T>;
private:
@@ -243,16 +255,19 @@ public:
}
inline bool operator !=(const PIVector2D<T> & t) const {return !(*this == t);}
PIVector<PIVector<T> > toVectors() const {
inline PIVector<PIVector<T> > toVectors() const {
PIVector<PIVector<T> > ret;
ret.reserve(rows_);
for(size_t i = 0; i < rows_; ++i)
ret << PIVector<T>(mat.data(i*cols_), cols_);
return ret;
}
PIVector<T> toPlainVector() const {return mat;}
PIVector<T> & plainVector() {return mat;}
const PIVector<T> & plainVector() const {return mat;}
inline PIVector<T> toPlainVector() const {return mat;}
inline PIVector<T> & plainVector() {return mat;}
inline const PIVector<T> & plainVector() const {return mat;}
inline void swap(PIVector2D<T> & other) {
mat.swap(other.mat);
@@ -275,11 +290,16 @@ public:
mat.clear();
}
void forEach(std::function<void(const T &)> f) const {
template <typename ST>
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const {
return PIVector2D<ST>(rows_, cols_, mat.map(f));
}
inline void forEach(std::function<void(const T &)> f) const {
mat.forEach(f);
}
PIVector2D<T> & forEach(std::function<void(T &)> f) {
inline PIVector2D<T> & forEach(std::function<void(T &)> f) {
mat.forEach(f);
return *this;
}
@@ -292,7 +312,7 @@ protected:
template<typename T>
inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
s.setControl(0, true);
s.saveAndSetControls(0);
s << "{";
for (size_t i = 0; i < v.rows(); ++i) {
s << "{ ";
@@ -305,7 +325,7 @@ inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
}
if (v.isEmpty()) s << "{ }";
s << "}";
s.restoreControl();
s.restoreControls();
return s;
}

View File

@@ -194,6 +194,16 @@
//! \~russian Макрос для окончания статической инициализации
# define STATIC_INITIALIZER_END
//! \~\brief
//! \~english Macro to remove class copy availability
//! \~russian Макрос для запрета копирования класса
# define NO_COPY_CLASS(Class)
//! \~\brief
//! \~english Macro to supress compiler warning about unused variable
//! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной
# define NO_UNUSED(x)
#undef MICRO_PIP
#undef FREERTOS
#endif //DOXYGEN
@@ -265,13 +275,15 @@
#ifdef CC_GCC
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED __attribute__((deprecated))
# define DEPRECATEDM(msg) __attribute__((deprecated(msg)))
# if CC_GCC_VERSION > 0x025F // > 2.95
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
# ifdef LINUX
# define HAS_LOCALE
# endif
# ifdef MAC_OS
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
# pragma GCC diagnostic ignored "-Wc++11-extensions"
# endif
@@ -287,7 +299,9 @@
#ifdef CC_VC
# undef DEPRECATED
# define DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED __declspec(deprecated)
# define DEPRECATEDM(msg) __declspec(deprecated(msg))
# pragma warning(disable: 4018)
# pragma warning(disable: 4061)
# pragma warning(disable: 4100)
@@ -312,7 +326,9 @@
#ifdef CC_OTHER
# undef DEPRECATED
# undef DEPRECATEDM
# define DEPRECATED
# define DEPRECATEDM(msg)
#endif
#endif //DOXYGEN

View File

@@ -0,0 +1,525 @@
/*! \file pibinarystream.h
* \ingroup Core
* \~\brief
* \~english Binary serialization interface
* \~russian Интерфейс бинарной сериализации
*/
/*
PIP - Platform Independent Primitives
Binary serialization interface
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIBINARYSTREAM_H
#define PIBINARYSTREAM_H
#include "pimemoryblock.h"
#include "pibitarray.h"
#include "pimap.h"
#include "pivector2d.h"
#define PIP_BINARY_STREAM
#define BINARY_STREAM_FRIEND(T) \
template<typename P> friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v); \
template<typename P> friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v);
#define BINARY_STREAM_WRITE(T) \
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v)
#define BINARY_STREAM_READ(T) \
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v)
//! \ingroup Core
//! \~\brief
//! \~english Binary serialization interface.
//! \~russian Интерфейс бинарной сериализации.
//! \~\details
//! \~english In your class you should implement this methods:
//! \~russian В производном классе вы должны реализовать следующие методы:
//! \~\code
//! bool binaryStreamAppendImp (const void * d, size_t s);
//! bool binaryStreamTakeImp (void * d, size_t s);
//! ssize_t binaryStreamSizeImp () const;
//! \endcode
//! \~english Function binaryStreamSizeImp should return -1 if size unknown.
//! \~russian Функция binaryStreamSizeImp должна возвращать -1 если нет информации о размере.
//! \~english See details \ref iostream.
//! \~russian Подробнее \ref iostream.
template<typename P>
class PIBinaryStream {
public:
//! \~russian Записать данные
bool binaryStreamAppend(const void * d, size_t s) {
if (!static_cast<P*>(this)->binaryStreamAppendImp(d, s)) {
return false;
printf("[PIBinaryStream] binaryStreamAppend() error\n");
}
return true;
}
//! \~russian Прочитать данные
bool binaryStreamTake(void * d, size_t s) {
if (!static_cast<P*>(this)->binaryStreamTakeImp(d, s)) {
return false;
printf("[PIBinaryStream] binaryStreamTake() error\n");
}
return true;
}
//! \~russian Узнать оставшийся размер
//!\~\details
//!\~russian Возвращает -1 если нет информации о размере
ssize_t binaryStreamSize() const {
return static_cast<P*>(this)->binaryStreamSizeImp();
}
//! \~russian Записать данные
template<typename T>
void binaryStreamAppend(T v) {binaryStreamAppend(&v, sizeof(v));}
//! \~russian Прочитать int
int binaryStreamTakeInt() {
int r = 0;
binaryStreamTake(&r, sizeof(r));
return r;
}
};
// helper class to detect default operators
template<typename P>
class PIBinaryStreamTrivialRef {
public:
PIBinaryStreamTrivialRef(PIBinaryStream<P> & s): p(s) {}
PIBinaryStream<P> & p;
};
template<typename P, typename T> inline PIBinaryStream<P> & operator <<(PIBinaryStreamTrivialRef<P> s, const T & v) {
s.p << v;
return s.p;
}
template<typename P, typename T> inline PIBinaryStream<P> & operator >>(PIBinaryStreamTrivialRef<P> s, T & v) {
s.p >> v;
return s.p;
}
// specify types
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const bool v) {
s.binaryStreamAppend((uchar)v);
return s;
}
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, bool & v) {
uchar c;
s.binaryStreamTake(&c, sizeof(c));
v = c;
return s;
}
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMemoryBlock v) {
s.binaryStreamAppend(v.data(), v.size());
return s;
}
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMemoryBlock v) {
s.binaryStreamTake(v.data(), v.size());
return s;
}
// store simple types
template<typename P, typename T,
typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v) {
//piCout << "<< enum";
s.binaryStreamAppend((int)v);
return s;
}
template<typename P, typename T,
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStreamTrivialRef<P> operator <<(PIBinaryStream<P> & s, const T & v) {
s.binaryStreamAppend(&v, sizeof(v));
return s;
}
//! \~english Store operator for PIVector of any trivial copyable type
//! \~russian Оператор сохранения для PIVector тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
//piCout << "<< vector trivial default";
s.binaryStreamAppend((int)v.size());
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
//piCout << "<< vector trivial custom";
s.binaryStreamAppend((int)v.size());
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIDeque of any trivial copyable type
//! \~russian Оператор сохранения для PIDeque тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
//piCout << "<< deque trivial default";
s.binaryStreamAppend((int)v.size());
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
//piCout << "<< deque trivial custom";
s.binaryStreamAppend((int)v.size());
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIVector2D of any trivial copyable type
//! \~russian Оператор сохранения для PIVector2D тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
//piCout << "<< vector2d trivial default";
s.binaryStreamAppend((int)v.rows());
s.binaryStreamAppend((int)v.cols());
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
//piCout << "<< vector2d trivial custom";
s.binaryStreamAppend((int)v.rows());
s.binaryStreamAppend((int)v.cols());
s << v.toPlainVector();
return s;
}
//! \~english Store operator
//! \~russian Оператор сохранения
template<typename P>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
//! \~english Store operator
//! \~russian Оператор сохранения
template<typename P, typename Type0, typename Type1>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
// restore simple types
template<typename P, typename T,
typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v) {
//piCout << ">> enum";
v = (T)s.binaryStreamTakeInt();
return s;
}
template<typename P, typename T,
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStreamTrivialRef<P> operator >>(PIBinaryStream<P> & s, T & v) {
if (!s.binaryStreamTake(&v, sizeof(v))) {
printf("error with %s\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
//! \~english Restore operator for PIVector of any trivial copyable type
//! \~russian Оператор извлечения для PIVector тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
//piCout << ">> vector trivial default";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
//piCout << ">> vector trivial custom";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIDeque of any trivial copyable type
//! \~russian Оператор извлечения для PIDeque тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
//piCout << ">> deque trivial default";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
//piCout << ">> deque trivial custom";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIVector2D of any trivial copyable type
//! \~russian Оператор извлечения для PIVector2D тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
//piCout << ">> vector2d trivial default";
int r, c;
r = s.binaryStreamTakeInt();
c = s.binaryStreamTakeInt();
v._resizeRaw(r, c);
if (!s.binaryStreamTake(v.data(), v.size() * sizeof(T))) {
printf("error with PIVector2D<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
//piCout << ">> vector2d trivial custom";
int r, c;
PIVector<T> tmp;
r = s.binaryStreamTakeInt();
c = s.binaryStreamTakeInt();
s >> tmp;
v = PIVector2D<T>(r, c, tmp);
return s;
}
//! \~english Restore operator
//! \~russian Оператор извлечения
template<typename P>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIBitArray & v) {s >> v.size_ >> v.data_; return s;}
//! \~english Restore operator
//! \~russian Оператор извлечения
template<typename P, typename Type0, typename Type1>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
// store complex types
//! \~english Store operator for PIVector of any compound type
//! \~russian Оператор сохранения для PIVector сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
//piCout << "<< vector complex";
s.binaryStreamAppend(int(v.size_s()));
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIDeque of any compound type
//! \~russian Оператор сохранения для PIDeque сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
//piCout << "<< deque complex";
s.binaryStreamAppend(int(v.size_s()));
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIVector2D of any compound type
//! \~russian Оператор сохранения для PIVector2D сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
//piCout << "<< vector2d complex";
s.binaryStreamAppend(int(v.rows()));
s.binaryStreamAppend(int(v.cols()));
s << v.toPlainVector();
return s;
}
// restore complex types
//! \~english Restore operator for PIVector of any compound type
//! \~russian Оператор извлечения для PIVector сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
//piCout << ">> vector complex";
/*if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
v.resize(s.binaryStreamTakeInt());
for (size_t i = 0; i < v.size(); ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIDeque of any compound type
//! \~russian Оператор извлечения для PIDeque сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
//piCout << ">> deque complex";
/*if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
v.resize(s.binaryStreamTakeInt());
for (size_t i = 0; i < v.size(); ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIVector2D of any compound type
//! \~russian Оператор извлечения для PIVector2D сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
//piCout << ">> vector2d complex";
/*if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 8);
}*/
int r, c;
PIVector<T> tmp;
r = s.binaryStreamTakeInt();
c = s.binaryStreamTakeInt();
s >> tmp;
v = PIVector2D<T>(r, c, tmp);
return s;
}
// other types
//! \~english Store operator
//! \~russian Оператор сохранения
template <typename P, typename Key, typename T>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMap<Key, T> & v) {
s.binaryStreamAppend((int)v.pim_index.size_s());
for (uint i = 0; i < v.size(); ++i) {
s.binaryStreamAppend((int)v.pim_index[i].index);
s << v.pim_index[i].key;
}
s << v.pim_content;
return s;
}
//! \~english Restore operator
//! \~russian Оператор извлечения
template <typename P, typename Key, typename T>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMap<Key, T> & v) {
/*if (s.size_s() < 4) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
int sz = s.binaryStreamTakeInt(); v.pim_index.resize(sz);
int ind = 0;
for (int i = 0; i < sz; ++i) {
ind = s.binaryStreamTakeInt();
s >> v.pim_index[i].key;
v.pim_index[i].index = ind;
}
s >> v.pim_content;
if (v.pim_content.size_s() != v.pim_index.size_s()) {
piCout << "Warning: loaded invalid PIMap, clear";
v.clear();
}
return s;
}
// non-defined complex types
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & ) {
static_assert(std::is_trivially_copyable<T>::value, "[PIBinaryStream] Error: using undeclared operator << for complex type!");
return s;
}
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & ) {
static_assert(std::is_trivially_copyable<T>::value, "[PIBinaryStream] Error: using undeclared operator >> for complex type!");
return s;
}
#endif

View File

@@ -23,12 +23,12 @@
PICout operator <<(PICout s, const PIBitArray & ba) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
for (uint i = 0; i < ba.bitSize(); ++i) {
s << int(ba[i]);
if (i % 8 == 7) s << ' ';
}
s.restoreControl();
s.restoreControls();
return s;
}

View File

@@ -27,29 +27,83 @@
#include "pivector.h"
class PIP_EXPORT PIBitArray {
friend PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v);
friend PIByteArray & operator >>(PIByteArray & s, PIBitArray & v);
public:
PIBitArray(const int & size = 0) {resize(size);}
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(ulong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(const uchar * bytes, uint size) {resize(size * 8); memcpy(data(), bytes, size);}
//! \ingroup Core
//! \~\brief
//! \~english The %PIBitArray class provides an space-efficient array of bits.
//! \~russian Класс %PIBitArray представляет собой компактный массив битов.
class PIP_EXPORT PIBitArray {
template <typename P>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIBitArray & v);
template <typename P>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIBitArray & v);
public:
//! \~english Constructs bit array with "size" size.
//! \~russian Создает битовый массив с размером "size".
PIBitArray(const int & size = 0) {resize(size);}
//! \~english Constructs bit array with size 8 and values from "val".
//! \~russian Создает битовый массив с размером 8 и значениями из "val".
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
//! \~english Constructs bit array with size 16 and values from "val".
//! \~russian Создает битовый массив с размером 16 и значениями из "val".
PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Constructs bit array with size 32 and values from "val".
//! \~russian Создает битовый массив с размером 32 и значениями из "val".
PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Constructs bit array with size 64 and values from "val".
//! \~russian Создает битовый массив с размером 64 и значениями из "val".
PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Constructs bit array with size "bytes * 8" and values from "data".
//! \~russian Создает битовый массив с размером "bytes * 8" и значениями из "data".
PIBitArray(const uchar * data, uint bytes) {resize(bytes * 8); memcpy(this->data(), data, bytes);}
//! \~english Returns a size in bits.
//! \~russian Возвращает размер в битах.
uint bitSize() const {return size_;}
//! \~english Returns a size in bytes.
//! \~russian Возвращает размер в байтах.
uint byteSize() const {return bytesInBits(size_);}
//! \~english Resize this array to "size" bits.
//! \~russian Изменяет размер массива до "size" битов.
PIBitArray & resize(const uint & size) {size_ = size; data_.resize(bytesInBits(size_)); return *this;}
//! \~english Set bit with index "index" to 0.
//! \~russian Устанавливает бит с индексом "index" в 0.
PIBitArray & clearBit(const uint & index) {data_[index / 8] &= ~(1 << (index % 8)); return *this;}
//! \~english Set bit with index "index" to 1.
//! \~russian Устанавливает бит с индексом "index" в 1.
PIBitArray & setBit(const uint & index) {data_[index / 8] |= (1 << (index % 8)); return *this;}
//! \~english Set bit with index "index" to "value".
//! \~russian Устанавливает бит с индексом "index" в "value".
PIBitArray & writeBit(const uint & index, const bool & value) {if (value) setBit(index); else clearBit(index); return *this;}
//! \~english Set bit with index "index" to "value".
//! \~russian Устанавливает бит с индексом "index" в "value".
PIBitArray & writeBit(const uint & index, const uchar & value) {return writeBit(index, value > 0);}
//! \~english Add bit with value "value" to the end of array.
//! \~russian Добавляет бит со значением "value" в конец массива.
PIBitArray & push_back(const bool & value) {resize(size_ + 1); writeBit(size_ - 1, value); return *this;}
//! \~english Add bit with value "value" to the end of array.
//! \~russian Добавляет бит со значением "value" в конец массива.
PIBitArray & push_back(const uchar & value) {return push_back(value > 0);}
//! \~english Insert bit with value "value" after "index" position.
//! \~russian Вставляет бит со значением "value" после положения "index".
PIBitArray & insert(const uint & index, const bool & value) {
resize(size_ + 1);
uint fi = byteSize() - 1, si = index / 8, ti = index % 8;
@@ -63,10 +117,25 @@ public:
if (value) data_[si] |= (1 << ti);
else data_[si] &= ~(1 << ti);
return *this;}
//! \~english Insert bit with value "value" after "index" position.
//! \~russian Вставляет бит со значением "value" после положения "index".
PIBitArray & insert(const uint & index, const uchar & value) {return insert(index, value > 0);}
//! \~english Add bit with value "value" to the beginning of array.
//! \~russian Добавляет бит со значением "value" в начало массива.
PIBitArray & push_front(const bool & value) {return insert(0, value);}
//! \~english Add bit with value "value" to the beginning of array.
//! \~russian Добавляет бит со значением "value" в начало массива.
PIBitArray & push_front(const uchar & value) {return push_front(value > 0);}
//! \~english Remove one bit from the end of array.
//! \~russian Удаляет один бит с конца массива.
PIBitArray & pop_back() {return resize(size_ - 1);}
//! \~english Remove one bit from the beginning of array.
//! \~russian Удаляет один бит с начала массива.
PIBitArray & pop_front() {
if (size_ == 0) return *this;
uint fi = byteSize() - 1;
@@ -77,24 +146,67 @@ public:
data_[fi] >>= 1;
resize(size_ - 1);
return *this;}
//! \~english Add bits "ba" to the end of array.
//! \~russian Добавляет биты "ba" в конец массива.
PIBitArray & append(const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) push_back(ba[i]); return *this;}
//! \~english Returns pointer to bytes data of array.
//! \~russian Возвращает указатель на байтовое содержимое массива.
uchar * data() {return data_.data();}
//! \~english Returns data of array as \b uchar.
//! \~russian Возвращает байтовое содержимое массива как \b uchar.
uchar toUChar() {if (size_ == 0) return 0; return data_[0];}
//! \~english Returns data of array as \b ushort.
//! \~russian Возвращает байтовое содержимое массива как \b ushort.
ushort toUShort() {ushort t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
//! \~english Returns data of array as \b uint.
//! \~russian Возвращает байтовое содержимое массива как \b uint.
uint toUInt() {uint t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
ulong toULong() {ulong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
//! \~english Returns data of array as \b ullong.
//! \~russian Возвращает байтовое содержимое массива как \b ullong.
ullong toULLong() {ullong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
//! \~english Returns bit value at index "index".
//! \~russian Возвращает значение бита с индексом "index".
bool at(const uint & index) const {return (1 & (data_[index / 8] >> (index % 8))) == 1 ? true : false;}
//! \~english Returns bit value at index "index".
//! \~russian Возвращает значение бита с индексом "index".
bool operator [](const uint & index) const {return at(index);}
//! \~english Similar to \a append().
//! \~russian Аналог \a append().
void operator +=(const PIBitArray & ba) {append(ba);}
//! \~english Returns if two bit arrays are similar.
//! \~russian Возвращает равны ли для битовых массива.
bool operator ==(const PIBitArray & ba) const {if (bitSize() != ba.bitSize()) return false; for (uint i = 0; i < bitSize(); ++i) if (at(i) != ba[i]) return false; return true;}
//! \~english Returns if two bit arrays are not similar.
//! \~russian Возвращает не равны ли для битовых массива.
bool operator !=(const PIBitArray & ba) const {return !(*this == ba);}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "val".
void operator =(const uchar & val) {resize(sizeof(val) * 8); data_[0] = val;}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "val".
void operator =(const ushort & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "val".
void operator =(const uint & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
void operator =(const ulong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "val".
void operator =(const ullong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
private:
@@ -109,6 +221,9 @@ private:
//std::ostream & operator <<(std::ostream & s, const PIBitArray & ba);
#endif
//! \relatesalso PIByteArray
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
PICout operator <<(PICout s, const PIBitArray & ba);
#endif // PIBITARRAY_H

View File

@@ -20,6 +20,7 @@
#include "pibytearray.h"
#include "pistringlist.h"
#include <iostream>
#include "picrc.h"
//! \class PIByteArray pibytearray.h
//! \~\details
@@ -28,53 +29,30 @@
//! It can be constructed from any data and size.
//! You can use %PIByteArray as binary stream
//! to serialize/deserialize any objects and data.
//! This class based on PIDeque<uchar> and provide some handle function
//! See details \ref iostream.
//! This class use PIDeque<uchar> and provide some handle function
//! to manipulate it.
//! \~russian
//! %PIByteArray используется для хранения байтов.
//! Он может быть сконструирован из любых даных.
//! Можно использовать %PIByteArray как потоковый объект
//! для сериализации/десериализации любых типов и данных.
//! Этот класс наследован от PIDeque<uchar> и предоставляет набор
//! Подробнее \ref iostream.
//! Этот класс использует PIDeque<uchar> и предоставляет набор
//! удобных методов для работы с байтами.
//!
//! \~english \section PIByteArray_sec0 Usage
//! \~russian \section PIByteArray_sec0 Использование
//! \~english
//! %PIByteArray can be used to store custom data and manipulate it. There are many
//! stream operators to store/restore common types to byte array. Store operators
//! places data at the end of array, restore operators takes data from the beginning
//! %PIByteArray subclass PIBinaryStream and can be used to store custom data and manipulate it.
//! Store operators places data at the end of array, restore operators takes data from the beginning
//! of array.
//! In addition there are Hex and Base64 convertions
//! In addition there are Hex and Base64 convertions.
//! \~russian
//! %PIByteArray может быть использован для сохранения любых данных и работы с ними.
//! Он предоставляет множество операторов для сохранения/извлечения общих типов.
//! %PIByteArray наследован от PIBinaryStream и может быть использован для сохранения любых данных и работы с ними.
//! Операторы сохранения добавляют данные в конец массива, а операторы извлечения
//! берут данные из его начала.
//!
//! \~english
//! One of the major usage of %PIByteArray is stream functions. You can form binary
//! packet from many types (also dynamic types, e.g. PIVector) with one line:
//! \~russian
//! Один из основных сценариев использования %PIByteArray - это потоковый объект.
//! Можно сформировать пакет бинарных данных из многих типов (также и контейнеров,
//! например, PIVector) в одну строку:
//! \~\snippet pibytearray.cpp 0
//!
//! \~english
//! Or you can descibe stream operator of your own type and store/restore vectors of
//! your type:
//! \~russian
//! Также можно описать операторы сохранения/извлечения для собственных типов:
//! \~\snippet pibytearray.cpp 1
//!
//! \~english
//! For store/restore custom data blocks there is PIByteArray::RawData class. Stream
//! operators of this class simply store/restore data block to/from byte array:
//! \~russian
//! Для сохранения/извлечения блоков произвольных данных используется класс PIByteArray::RawData.
//! Потоковые операторы для него просто сохраняют/извлекают блоки байтов:
//! \~\snippet pibytearray.cpp 2
//! Также есть методы для преобразования в Hex и Base64.
//!
//! \~english \section PIByteArray_sec1 Attention
//! \~russian \section PIByteArray_sec1 Внимание
@@ -88,7 +66,7 @@
//! а не просто добавляет его содержимое в конец. Этот оператор полезен для управляемой
//! упаковки произвольных данных в виде %PIByteArray.
//! Для добавления содержимого одного байтового массива к другому используется
//! метов \a append().
//! метод \a append().
//! \~\snippet pibytearray.cpp 3
//!
@@ -315,6 +293,19 @@ uchar PIByteArray::checksumPlain8(bool inverse) const {
}
uchar PIByteArray::checksumCRC8() const {
return standardCRC_8().calculate(data(), size());
}
ushort PIByteArray::checksumCRC16() const {
return standardCRC_16().calculate(data(), size());
}
uint PIByteArray::checksumCRC32() const {
return standardCRC_32().calculate(data(), size());
}
//! \~\details
//! \~english
//! This is sum of all bytes multiplied by index+1, if inverse then add 1 and inverse.
@@ -415,14 +406,14 @@ PIByteArray PIByteArray::fromHex(PIString str) {
PICout operator <<(PICout s, const PIByteArray & ba) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "{";
for (uint i = 0; i < ba.size(); ++i) {
s << ba[i];
if (i < ba.size() - 1) s << ", ";
}
s << "}";
s.restoreControl();
s.restoreControls();
return s;
}
@@ -438,38 +429,3 @@ std::ostream &operator <<(std::ostream & s, const PIByteArray & ba) {
return s;
}
#endif
PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {
if (s.size_s() < 4) {
s.clear();
v.clear();
return s;
}
assert(s.size_s() >= 4);
int sz = 0;
s >> sz;
if (sz > s.size_s()) {
piCout << "[PIByteArray] Warning: operator >> wants too much data, discard!" << sz << s.size_s();
s.clear();
v.clear();
return s;
}
v.resize(sz);
if (sz > 0) {
memcpy(v.data(), s.data(), sz);
s.remove(0, sz);
}
return s;
}
PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {
s << int(v.size_s());
int os = s.size_s();
if (v.size_s() > 0) {
s.enlarge(v.size_s());
memcpy(s.data(os), v.data(), v.size());
}
return s;
}

View File

@@ -27,9 +27,7 @@
#define PIBYTEARRAY_H
#include "pichar.h"
#include "pibitarray.h"
#include "pimap.h"
#include "pivector2d.h"
#include "pibinarystream.h"
#include <stdio.h>
class PIString;
@@ -40,23 +38,24 @@ class PIByteArray;
//! \~\brief
//! \~english The %PIByteArray class provides an array of bytes.
//! \~russian Класс %PIByteArray представляет собой массив байтов.
class PIP_EXPORT PIByteArray: public PIDeque<uchar>
class PIP_EXPORT PIByteArray: public PIBinaryStream<PIByteArray>
{
public:
typedef ::PIMemoryBlock RawData DEPRECATEDM("use PIMemoryBlock instead");
//! \~english Constructs an empty byte array
//! \~russian Создает пустой байтовый массив
PIByteArray() {;}
PIByteArray() {}
//! \~english Constructs copy of byte array "o"
//! \~russian Создает копию байтового массива "o"
PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {}
PIByteArray(const PIByteArray & o): d(o.d) {}
//! \~english Constructs copy of byte array "o"
//! \~russian Создает копию байтового массива "o"
PIByteArray(const PIDeque<uchar> & o): PIDeque<uchar>(o) {}
PIByteArray(const PIDeque<uchar> & o): d(o) {}
PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {}
PIByteArray(PIByteArray && o): d(std::move(o.d)) {}
//! \~english Constructs 0-filled byte array with size "size"
//! \~russian Создает заполненный "0" байтовый массив размером "size"
@@ -64,42 +63,989 @@ public:
//! \~english Constructs byte array from data "data" and size "size"
//! \~russian Создает байтовый массив из данных по указателю "data" размером "size"
PIByteArray(const void * data, const uint size): PIDeque<uchar>((const uchar*)data, size_t(size)) {}
PIByteArray(const void * data, const uint size): d((const uchar*)data, size_t(size)) {}
//! \~english Constructs byte array with size "size" filled by "t"
//! \~russian Создает заполненный "t" байтовый массив размером "size"
PIByteArray(const uint size, uchar t): PIDeque<uchar>(size, t) {}
PIByteArray(const uint size, uchar t): d(size, t) {}
//! \~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
//! PIByteArray v{1,2,3};
//! piCout << v; // {1, 2, 3}
//! \endcode
PIByteArray(std::initializer_list<uchar> init_list) : d(init_list) {}
//! \~english Help struct to store/restore custom blocks of data to/from PIByteArray
//! \~russian Вспомогательная структура для сохранения/извлечения произвольного блока данных в/из байтового массива
struct RawData {
friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
public:
//! \~english Constructs data block
//! \~russian Создает блок данных
RawData(void * data = 0, int size = 0) {d = data; s = size;}
RawData(const RawData & o) {d = o.d; s = o.s;}
//! \~english Constructs data block
//! \~russian Создает блок данных
RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;}
RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
private:
void * d;
int s;
};
//! \~english Swaps array `v` other with this array.
//! \~russian Меняет местами массив `v` с этим массивом.
//! \~\details
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
inline void swap(PIByteArray & other) {
d.swap(other.d);
}
//! \~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 PIDeque<uchar>::iterator begin() {return d.begin();}
//! \~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 PIDeque<uchar>::iterator end() {return d.end();}
inline PIDeque<uchar>::const_iterator begin() const {return d.begin();}
inline PIDeque<uchar>::const_iterator end() const {return d.end();}
//! \~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 PIDeque<uchar>::reverse_iterator rbegin() {return d.rbegin();}
//! \~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 PIDeque<uchar>::reverse_iterator rend() {return d.rend();}
inline PIDeque<uchar>::const_reverse_iterator rbegin() const {return d.rbegin();}
inline PIDeque<uchar>::const_reverse_iterator rend() const {return d.rend();}
//! \~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 d.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 d.size_s();}
//! \~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 d.length();}
//! \~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 d.capacity();}
//! \~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 d.isEmpty();}
//! \~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 d.isNotEmpty();}
//! \~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
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
inline bool any(std::function<bool(uchar e)> test) const {
return d.any(test);
}
//! \~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
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
inline bool every(std::function<bool(uchar e)> test) const {
return d.every(test);
}
//! \~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`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! \~\sa \a at()
inline uchar & operator [](size_t index) {return d[index];}
inline uchar operator [](size_t index) const {return d[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 uchar at(size_t index) const {return d.at(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 uchar & back() {return d.back();}
inline uchar back() const {return d.back();}
//! \~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 uchar & front() {return d.front();}
inline uchar front() const {return d.front();}
//! \~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
//! PIByteArray 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()
inline bool contains(uchar e, ssize_t start = 0) const {
return d.contains(e, start);
}
//! \~english Count elements equal `e` 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,
//! 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 indexOf()
inline int entries(uchar e, ssize_t start = 0) const {
return d.entries(e, start);
}
//! \~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 indexWhere()
inline int entries(std::function<bool(uchar e)> test, ssize_t start = 0) const {
return d.entries(test, start);
}
//! \~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
//! PIByteArray 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 uchar & e, ssize_t start = 0) const {
return d.indexOf(e, start);
}
//! \~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
//! PIByteArray v{2, 5, 9};
//! piCout << v.indexWhere([](const uchar & s){return s > 3;}); // 1
//! piCout << v.indexWhere([](const uchar & s){return s > 3;}, 2); // 2
//! piCout << v.indexWhere([](const uchar & s){return s > 10;}); // -1
//! \endcode
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
inline ssize_t indexWhere(std::function<bool(const uchar & e)> test, ssize_t start = 0) const {
return d.indexWhere(test, start);
}
//! \~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
//! PIByteArray 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 uchar & e, ssize_t start = -1) const {
return d.lastIndexOf(e, start);
}
//! \~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 uchar & e)> test, ssize_t start = -1) const {
return d.lastIndexWhere(test, start);
}
//! \~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 которого брать указатель.
//! По умолчанию указывает на начало массива.
inline uchar * data(size_t index = 0) {return d.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 которого брать указатель.
//! По умолчанию указывает на начало массива.
inline const uchar * data(size_t index = 0) const {return d.data(index);}
//! \~english Clear array, remove all elements.
//! \~russian Очищает массив, удаляет все элементы.
//! \~\details
//! \~\note
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
inline PIByteArray & clear() {
resize(0);
return *this;
}
//! \~english Assigns element 'e' to all items in the array.
//! \~russian Заполняет весь массив копиями элемента 'e'.
//! \~\details
//! \~\sa \a resize()
inline PIByteArray & fill(uchar e = 0) {
d.fill(e);
return *this;
}
//! \~english Assigns result of function 'f(size_t i)' to all items in the array.
//! \~russian Заполняет весь массив результатом вызова функции 'f(size_t i)'.
//! \~\details
//! \~\sa \a resize()
inline PIByteArray & fill(std::function<uchar(size_t i)> f) {
d.fill(f);
return *this;
}
//! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize()
inline PIByteArray & assign(uchar e = 0) {return fill(e);}
//! \~english First does `resize(new_size)` then `fill(e)`.
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
//! \~\sa \a fill(), \a resize()
inline PIByteArray & assign(size_t new_size, uchar e) {
resize(new_size);
return fill(e);
}
//! \~english Sets size of the array, new elements are copied from `e`.
//! \~russian Устанавливает размер массива, новые элементы копируются из `e`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements are initialized from `e`.
//! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и создаются из `e`.
//! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIByteArray & resize(size_t new_size, uchar e = 0) {
d.resize(new_size, e);
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 PIByteArray & resize(size_t new_size, std::function<uchar(size_t i)> f) {
d.resize(new_size, f);
return *this;
}
//! \~english Return resized byte array
//! \~russian Возвращает копию байтового массива с измененным размером
PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
PIByteArray resized(uint new_size) const {
PIByteArray ret(new_size);
memcpy(ret.data(), data(), new_size);
return ret;
}
//! \~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 PIByteArray & reserve(size_t new_size) {
d.reserve(new_size);
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 PIByteArray & insert(size_t index, uchar e = 0) {
d.insert(index, e);
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 PIByteArray & insert(size_t index, const PIByteArray & v) {
d.insert(index, v.d);
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 PIByteArray & insert(size_t index, std::initializer_list<uchar> init_list) {
d.insert(index, init_list);
return *this;
}
//! \~english Removes `count` elements from the middle of the array, starting at `index` position.
//! \~russian Удаляет элементы из массива, начиная с позиции `index` в количестве `count`.
//! \~\details
//! \~\sa \a resize(), \a insert(), \a removeOne(), \a removeAll(), \a removeWhere()
inline PIByteArray & remove(size_t index, size_t count = 1) {
d.remove(index, count);
return *this;
}
//! \~english Return sub-array starts from "index" and has "count" or less bytes
//! \~russian Возвращает подмассив с данными от индекса "index" и размером не более "count"
PIByteArray getRange(size_t index, size_t count) const {
return PIDeque<uchar>::getRange(index, count);
return d.getRange(index, count);
}
//! \~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() на месте переставляет элементы массива,
//! на котором он был вызван, изменяет массив и возвращает ссылку на него.
//! Первый элемент массива становится последним, а последний — первым.
//! \~\sa \a reversed()
inline PIByteArray & reverse() {
d.reverse();
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 PIByteArray reversed() const {
PIByteArray 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 PIByteArray & enlarge(ssize_t add_size, uchar e = 0) {
d.enlarge(add_size, e);
return *this;
}
//! \~english Remove no more than one element equal `e`.
//! \~russian Удаляет первый элемент, который равен элементу `e`.
//! \~\details
//! \~\sa \a remove(), \a removeAll(), \a removeWhere()
inline PIByteArray & removeOne(uchar e) {
d.removeOne(e);
return *this;
}
//! \~english Remove all elements equal `e`.
//! \~russian Удаляет все элементы, равные элементу `e`.
//! \~\details
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIByteArray & removeAll(uchar e) {
d.removeAll(e);
return *this;
}
//! \~english Remove all elements in the array
//! passes the test implemented by the provided function `test`.
//! \~russian Удаляет все элементы, удовлетворяющие условию,
//! заданному в передаваемой функции `test`.
//! \~\details
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIByteArray & removeWhere(std::function<bool(uchar e)> test) {
d.removeWhere(test);
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(),
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов, указывающих на конец массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_front(), \a append(), \a prepend(), \a insert()
inline PIByteArray & push_back(uchar e) {
d.push_back(e);
return *this;
}
//! \~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 push_back()
inline PIByteArray & push_back(std::initializer_list<uchar> init_list) {
d.push_back(init_list);
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 PIByteArray & push_back(const PIByteArray & v) {
d.push_back(v.d);
return *this;
}
//! \~english Add to the end data "data" with size "size"
//! \~russian Добавляет в конец массива данные по указателю "data" размером "size"
PIByteArray & push_back(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); 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 Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIByteArray & push_front(uchar e) {
d.push_front(e);
return *this;
}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_front()
inline PIByteArray & push_front(const PIByteArray & v) {
d.push_front(v.d);
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 PIByteArray & push_front(std::initializer_list<uchar> init_list) {
d.push_front(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 Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIByteArray & prepend(uchar e) {
d.prepend(e);
return *this;
}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a prepend()
inline PIByteArray & prepend(const PIByteArray & v) {
d.prepend(v.d);
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 PIByteArray & prepend(std::initializer_list<uchar> init_list) {
d.prepend(init_list);
return *this;
}
//! \~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 Удаление элемента с конца выполняется очень быстро
//! и не зависит от размера массива.
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
inline PIByteArray & pop_back() {
d.pop_back();
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 Удаление элемента с начала выполняется дольше, чем с конца.
//! Это время прямопропорционально размеру массива.
//! При удалении элемента все итераторы и указатели становятся нерабочими.
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
inline PIByteArray & pop_front() {
d.pop_front();
return *this;
}
//! \~english Remove one element from the end of the array and return it.
//! \~russian Удаляет один элемент с начала массива и возвращает его.
//! \~\details
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline uchar take_back() {
return d.take_back();
}
//! \~english Remove one element from the begining of the array and return it.
//! \~russian Удаляет один элемент с конца массива и возвращает его.
//! \~\details
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline uchar take_front() {
return d.take_front();
}
//! \~english Returns a new array with all elements
//! that pass the test implemented by the provided function `test`.
//! \~russian Возвращает новый массив со всеми элементами,
//! прошедшими проверку, задаваемую в передаваемой функции `test`.
//! \~\details
//! \~\code
//! PIByteArray v{3, 2, 5, 2, 7};
//! PIByteArray v2 = v.filter([](const uchar & i){return i > 2;});
//! piCout << v2; // {3, 5, 7}
//! \endcode
//! \~\sa \a map(), \a any(), \a every()
inline PIByteArray filter(std::function<bool(const uchar & e)> test) const {
return PIByteArray(d.filter(test));
}
//! \~english Execute function `void f(const uchar & e)` for every element in array.
//! \~russian Выполняет функцию `void f(const uchar & e)` для каждого элемента массива.
//! \~\details
//! \~russian Не позволяет изменять элементы массива.
//! Для редактирования элементов используйте функцию вида `void f(uchar & e)`.
//! \~english Does not allow changing array elements.
//! To edit elements, use the function like `void f(T & e)`
//! \~\code
//! PIByteArray v{1, 2, 3, 4, 5};
//! int s = 0;
//! v.forEach([&s](const uchar & 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 uchar & e)> f) const {
d.forEach(f);
}
//! \~english Execute function `void f(uchar & e)` for every element in array.
//! \~russian Выполняет функцию `void f(uchar & e)` для каждого элемента массива.
//! \~\details
//! \~english Overloaded function.
//! Allows you to change the elements of the array.
//! \~russian Перегруженая функция.
//! Позволяет изменять элементы массива.
//! \~\code
//! PIByteArray v{1, 2, 3, 4, 5};
//! v.forEach([](uchar & e){e++;});
//! piCout << v; // {2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
inline PIByteArray & forEach(std::function<void(uchar & e)> f) {
d.forEach(f);
return *this;
}
//! \~english Сreates a new array populated with the results
//! of calling a provided function `ST f(const uchar & e)` on every element in the calling array.
//! \~russian Создаёт новый массив с результатом вызова указанной функции
//! `ST f(const T & e)` для каждого элемента массива.
//! \~\details
//! \~english Calls a provided function`ST f(const uchar & e)`
//! once for each element in an array, in order,
//! and constructs a new array from the results.
//! \~russian Метод `map` вызывает переданную функцию `ST f(const uchar & e)`
//! один раз для каждого элемента в порядке их появления
//! и конструирует новый массив из результатов её вызова.
//! \~\code
//! PIByteArray v{0x31, 0x0A, 0xFF};
//! PIStringList sl = v.map<PIString>([](const uchar & i){return PIString::fromNumber(i, 16);});
//! piCout << sl; {"31", "A", "FF"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST>
inline PIDeque<ST> map(std::function<ST(const uchar & e)> f) const {
return d.map<ST>(f);
}
//! \~english Applies the function `ST f(const uchar & e, const ST & acc)`
//! to each element of the array (from left to right), returns one value.
//! \~russian Применяет функцию `ST f(const uchar & 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 uchar & 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 uchar & e, const ST & acc)`,
//! выполняющаяся для каждого элемента массива.
//! Она принимает два аргумента:
//! * **e** - текущий элемент массива
//! * **acc** - аккумулятор, аккумулирующий значение
//! которое возвращает эта функция после посещения очередного элемента
//!
//! \param initial _опциональный_ Объект,
//! используемый в качестве второго аргумента при первом вызове функции `f`.
//!
//! \~\code
//! PIByteArray v{1, 2, 3, 4, 5};
//! PIString s = v.reduce<PIString>([](const uchar & e, const PIString & acc){return acc + PIString::fromNumber(e);});
//! piCout << s; // "12345"
//! \endcode
//! \~\sa \a forEach(), \a map()
template <typename ST>
inline ST reduce(std::function<ST(const uchar & e, const ST & acc)> f, const ST & initial = ST()) const {
return d.reduce<ST>(f, initial);
}
//! \~english Convert data to Base 64 and return this byte array
//! \~russian Преобразует данные в Base 64 и возвращает текущий массив
@@ -142,6 +1088,21 @@ public:
//! \~russian Добавляет в конец массива байт "t"
PIByteArray & append(uchar t) {push_back(t); return *this;}
//! \~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 push_back()
inline PIByteArray & append(std::initializer_list<uchar> init_list) {
d.append(init_list);
return *this;
}
//! \~english Returns 8-bit checksum
//! \~russian Возвращает 8-битную контрольную сумму
uchar checksumPlain8(bool inverse = true) const;
@@ -150,11 +1111,23 @@ public:
//! \~russian Возвращает 32-битную контрольную сумму
uint checksumPlain32(bool inverse = true) const;
//! \~english Returns 8-bit checksum CRC-8
//! \~russian Возвращает 8-битную контрольную сумму CRC-8
uchar checksumCRC8() const;
//! \~english Returns 16-bit checksum CRC-16
//! \~russian Возвращает 16-битную контрольную сумму CRC-16
ushort checksumCRC16() const;
//! \~english Returns 32-bit checksum CRC-32
//! \~russian Возвращает 32-битную контрольную сумму CRC-32
uint checksumCRC32() const;
//! \~english Returns hash of content
//! \~russian Возвращает хэш содержимого
uint hash() const;
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
void operator =(const PIDeque<uchar> & o) {resize(o.size()); memcpy(data(), o.data(), o.size());}
PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
@@ -170,13 +1143,22 @@ public:
static PIByteArray fromBase64(const PIString & base64);
class StreamRef {
public:
StreamRef(PIByteArray & s): ba(s) {}
operator PIByteArray&() {return ba;}
private:
PIByteArray & ba;
};
bool binaryStreamAppendImp(const void * d_, size_t s) {
append(d_, s);
return true;
}
bool binaryStreamTakeImp(void * d_, size_t s) {
size_t rs = size();
if (rs > s) rs = s;
memcpy(d_, data(), rs);
remove(0, rs);
return rs == s;
}
ssize_t binaryStreamSizeImp() const {return size();}
private:
PIDeque<uchar> d;
};
@@ -235,443 +1217,21 @@ inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
// store operators for basic types
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray
//! \~english Store operator for any trivial copyable type
//! \~russian Оператор сохранения для тривиальных типов
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
int os = s.size_s();
s.enlarge(sizeof(v));
memcpy(s.data(os), &v, sizeof(v));
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIByteArray) {
s.binaryStreamAppend((int)v.size_s());
s.binaryStreamAppend(v.data(), v.size());
return s;
}
//! \relatesalso PIByteArray
//! \~english Store operator, see \ref PIByteArray_sec1 for details
//! \~russian Оператор сохранения, подробнее в \ref PIByteArray_sec1
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
int os = s.size_s();
if (v.s > 0) {
s.enlarge(v.s);
memcpy(s.data(os), v.d, v.s);
}
return s;
}
//! \relatesalso PIByteArray
//! \~english Store operator for PIVector of any trivial copyable type
//! \~russian Оператор сохранения для PIVector тривиальных типов
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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, const PIVector<T> & v) {
s << int(v.size_s());
int os = s.size_s();
if (v.size_s() > 0) {
s.enlarge(v.size_s()*sizeof(T));
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
}
return s;
}
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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, const PIVector<T> & v) {
s << int(v.size_s());
for (uint i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Store operator for PIDeque of any trivial copyable type
//! \~russian Оператор сохранения для PIDeque тривиальных типов
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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, const PIDeque<T> & v) {
s << int(v.size_s());
int os = s.size_s();
if (v.size_s() > 0) {
s.enlarge(v.size_s()*sizeof(T));
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
}
return s;
}
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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, const PIDeque<T> & v) {
s << int(v.size_s());
for (uint i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Store operator for PIVector2D of any trivial copyable type
//! \~russian Оператор сохранения для PIVector2D тривиальных типов
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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, const PIVector2D<T> & v) {
s << int(v.rows()) << int(v.cols());
int os = s.size_s();
if (v.size_s() > 0) {
s.enlarge(v.size_s()*sizeof(T));
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
}
return s;
}
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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, const PIVector2D<T> & v) {
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
return s;
}
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
//! \relatesalso PIPair
//! \~english Store operator
//! \~russian Оператор сохранения
template<typename Type0, typename Type1>
inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
// restore operators for basic types
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray
//! \~english Restore operator for any trivial copyable type
//! \~russian Оператор извлечения для тривиальных типов
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
if (s.size() < sizeof(v)) {
printf("error with %s\n", __PIP_TYPENAME__(T));
assert(s.size() >= sizeof(v));
}
memcpy((void*)(&v), s.data(), sizeof(v));
s.remove(0, sizeof(v));
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator, see \ref PIByteArray_sec1 for details
//! \~russian Оператор извлечения, подробнее в \ref PIByteArray_sec1
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
if (s.size_s() < v.s) {
printf("error with RawData %d < %d\n", (int)s.size_s(), v.s);
assert(s.size_s() >= v.s);
}
if (v.s > 0) {
memcpy((void*)(v.d), s.data(), v.s);
s.remove(0, v.s);
}
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator for PIVector of any trivial copyable type
//! \~russian Оператор извлечения для PIVector тривиальных типов
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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) {
if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}
int sz; s >> sz;
v._resizeRaw(sz);
if (sz > 0) {
memcpy(v.data(), s.data(), sz*sizeof(T));
s.remove(0, sz*sizeof(T));
}
return s;
}
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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) {
if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}
int sz; s >> sz;
v.resize(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator for PIDeque of any trivial copyable type
//! \~russian Оператор извлечения для PIDeque тривиальных типов
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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) {
if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}
int sz; s >> sz;
v._resizeRaw(sz);
if (sz > 0) {
memcpy(v.data(), s.data(), sz*sizeof(T));
s.remove(0, sz*sizeof(T));
}
return s;
}
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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) {
if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}
int sz; s >> sz;
v.resize(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator for PIVector2D of any trivial copyable type
//! \~russian Оператор извлечения для PIVector2D тривиальных типов
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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) {
if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 8);
}
int r, c; s >> r >> c;
v._resizeRaw(r, c);
int sz = r*c;
if (sz > 0) {
memcpy(v.data(), s.data(), sz*sizeof(T));
s.remove(0, sz*sizeof(T));
}
return s;
}
template<typename T,
typename std::enable_if< std::is_trivially_copyable<T>::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) {
if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 8);
}
int r,c;
PIVector<T> tmp;
s >> r >> c >> tmp;
v = PIVector2D<T>(r, c, tmp);
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
//! \relatesalso PIPair
//! \~english Restore operator
//! \~russian Оператор извлечения
template<typename Type0, typename Type1>
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
// store operators for complex types
//! \relatesalso PIByteArray
//! \~english Store operator for PIVector of any compound type
//! \~russian Оператор сохранения для PIVector сложных типов
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
s << int(v.size_s());
for (uint i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Store operator for PIDeque of any compound type
//! \~russian Оператор сохранения для PIDeque сложных типов
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
s << int(v.size_s());
for (uint i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Store operator for PIVector2D of any compound type
//! \~russian Оператор сохранения для PIVector2D сложных типов
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
return s;
}
// restore operators for complex types
//! \relatesalso PIByteArray
//! \~english Restore operator for PIVector of any compound type
//! \~russian Оператор извлечения для PIVector сложных типов
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}
int sz; s >> sz;
v.resize(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator for PIDeque of any compound type
//! \~russian Оператор извлечения для PIDeque сложных типов
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}
int sz; s >> sz;
v.resize(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator for PIVector2D of any compound type
//! \~russian Оператор извлечения для PIVector2D сложных типов
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 8);
}
int r,c;
PIVector<T> tmp;
s >> r >> c >> tmp;
v = PIVector2D<T>(r, c, tmp);
return s;
}
// other types
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
template <typename Key, typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
// s << int(v.pim_index.size_s());
// for (uint i = 0; i < v.size(); ++i)
// s << int(v.pim_index[i].index) << v.pim_index[i].key;
s << v.pim_content;
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
template <typename Key, typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
if (s.size_s() < 4) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}
// int sz; s >> sz; v.pim_index.resize(sz);
// int ind = 0;
// for (int i = 0; i < sz; ++i) {
// s >> ind >> v.pim_index[i].key;
// v.pim_index[i].index = ind;
// }
s >> v.pim_content;
// if (v.pim_content.size_s() != v.pim_index.size_s()) {
// piCout << "Warning: loaded invalid PIMap, clear";
// v.clear();
// }
return s;
}
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator <<(PIByteArray & s, const T & ) {
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
return s;
}
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIByteArray & operator >>(PIByteArray & s, T & ) {
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator >> for complex type!");
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIByteArray) {
v.resize(s.binaryStreamTakeInt());
s.binaryStreamTake(v.data(), v.size());
return s;
}

View File

@@ -359,7 +359,7 @@ PIChar PIChar::toLower() const {
PICout operator <<(PICout s, const PIChar & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
if (v.isAscii()) s << char(v.ch);
else {
#ifdef PIP_ICU
@@ -380,6 +380,6 @@ PICout operator <<(PICout s, const PIChar & v) {
s << PIString(v);
#endif
}
s.restoreControl();
s.restoreControls();
return s;
}

View File

@@ -39,11 +39,11 @@ extern PIP_EXPORT char * __utf8name__;
class PIP_EXPORT PIChar
{
friend class PIString;
friend PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
friend PICout operator <<(PICout s, const PIChar & v);
public:
//! \~english Contructs Ascii symbol
//! \~russian Создает символ Ascii
PIChar(char c) {ch = c; ch &= 0xFF;}
PIChar(char c) {ch = c;}
//! \~english Contructs ascii symbol
//! \~russian Создает символ Ascii
@@ -183,7 +183,7 @@ private:
//! \relatesalso PIChar
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
PIP_EXPORT PICout operator <<(PICout s, const PIChar & v);
//! \relatesalso PIChar
//! \~english Compare operator

View File

@@ -117,7 +117,7 @@ int PIChunkStream::read() {
last_id = readVInt(*data_);
last_data.resize(readVInt(*data_));
//piCout << last_id << last_data.size();
(*data_) >> PIByteArray::RawData(last_data.data(), last_data.size_s());
(*data_) >> PIMemoryBlock(last_data.data(), last_data.size_s());
break;
default: break;
}
@@ -125,15 +125,14 @@ int PIChunkStream::read() {
}
int PIChunkStream::peekVInt(Version version_, PIByteArray * data_, int pos, PIByteArray & hdr, uint & ret) {
int PIChunkStream::peekVInt(Version version_, uchar * data_, int sz, uint & ret) {
switch (version_) {
case Version_1:
memcpy(&ret, data_->data(pos), 4);
memcpy(&ret, data_, 4);
return 4;
case Version_2: {
PIByteArray hdr(data_, piMini(4, sz));
hdr.resize(4);
hdr.fill(uchar(0));
memcpy(hdr.data(), data_->data(pos), piMini(4, data_->size_s() - pos));
uchar hsz = 0;
ret = readVInt(hdr, &hsz);
return hsz;
@@ -153,13 +152,16 @@ void PIChunkStream::replaceChunk(int id, const PIByteArray & v) {
pos.length = v.size_s();
if (size_mod != 0) {
auto it = data_map.makeIterator();
while (it.next())
if (it.valueRef().start > pos.start)
it.valueRef().start += size_mod;
if (size_mod > 0)
while (it.next()) {
if (it.value().start > pos.start) {
it.value().start += size_mod;
}
}
if (size_mod > 0) {
data_->insert(pos.start, PIByteArray(size_mod));
else
} else {
data_->remove(pos.start, -size_mod);
}
}
memcpy(data_->data(pos.start - pos.size_bytes), nsba.data(), nsba.size());
pos.start += nsba.size_s() - pos.size_bytes;
@@ -172,10 +174,9 @@ void PIChunkStream::readAll() {
if (!data_) return;
int pos = 0, sz = data_->size_s(), hsz = 0;
uint csz = 0, cid = 0;
PIByteArray hdr;
while (pos < sz) {
pos += peekVInt((Version)version_, data_, pos, hdr, cid);
hsz = peekVInt((Version)version_, data_, pos, hdr, csz);
pos += peekVInt((Version)version_, data_->data(pos), data_->size_s() - pos, cid);
hsz = peekVInt((Version)version_, data_->data(pos), data_->size_s() - pos, csz);
pos += hsz;
data_map[cid] = CacheEntry(pos, csz, hsz);
pos += csz;
@@ -193,8 +194,7 @@ bool PIChunkStream::extract(PIByteArray & data, bool read_all) {
if (tmp_data.size_s() < 4) return false;
data_ = &tmp_data;
_init();
if (read_all)
readAll();
if (read_all) readAll();
return true;
}
@@ -208,19 +208,27 @@ void PIChunkStream::_init() {
if ((v & 0x80) == 0x80) {
v &= 0x7f;
switch (v) {
case 2: version_ = (uchar)Version_2; data_->pop_front(); first_byte_taken = true; break;
default: version_ = Version_1; break;
case 2:
version_ = (uchar)Version_2;
data_->pop_front();
first_byte_taken = true;
break;
default:
version_ = Version_1;
break;
}
} else
} else {
version_ = Version_1;
}
}
}
uint PIChunkStream::readVInt(PIByteArray & s, uchar * bytes_cnt) {
if (s.isEmpty()) return 0;
uchar bytes[4]; s >> bytes[0];
uchar abc = 0;
uchar bytes[4];
uchar abc;
s >> bytes[0];
for (abc = 0; abc < 3; ++abc) {
uchar mask = (0x80 >> abc);
if ((bytes[0] & mask) == mask) {

View File

@@ -124,7 +124,7 @@ public:
//! \~english Returns value of last readed chunk
//! \~russian Возвращает значение последнего прочитанного чанка
template <typename T>
T getData() const {T ret; PIByteArray s(last_data); s >> ret; return ret;}
T getData() const {T ret{}; PIByteArray s(last_data); s >> ret; return ret;}
//! \~english Place value of last readed chunk into \"v\"
//! \~russian Записывает значение последнего прочитанного чанка в \"v\"
@@ -165,7 +165,7 @@ private:
static uint readVInt(PIByteArray & s, uchar * bytes = 0);
static void writeVInt(PIByteArray & s, uint val);
static int peekVInt(Version version_, PIByteArray * data_, int pos, PIByteArray & hdr, uint & ret);
static int peekVInt(Version version_, uchar * data_, int sz, uint & ret);
void replaceChunk(int id, const PIByteArray & v);
int last_id;

View File

@@ -35,7 +35,7 @@
//! Этот класс предоставляет удобный механизм для разбора аргументов командной строки.
//! Сперва необходимо добавить аргументы в %PICLI с помощью методов \a addArgument().
//! Далее можно проверять аргументы на наличие в командной строке методом \a hasArgument(),
//! а также получить их значения при помощи \a argumentValue().
//! а также получать их значения при помощи \a argumentValue().
//!
//! \~english \section PICLI_sec1 Example
//! \~russian \section PICLI_sec1 Пример
@@ -52,8 +52,12 @@
//! piCout << "Value =" << cli.argumentValue("Value");
//! return 0;
//! }
//! \endcode
//!
//! These executions are similar:
//! \~english These executions are similar:
//! \~russian Эти вызовы будут идентичны:
//!
//! \~\code
//! a.out -cd -v 10
//! a.out --value 10 -dc
//! a.out -c -v 10 -d

View File

@@ -37,56 +37,62 @@ class PIP_EXPORT PICLI
{
public:
//! \~english Constructor
//! \~russian Конструктор
//! \~english Constructs %PICLI from "argc" and "argv" from "int main()" method.
//! \~russian Создает %PICLI из "argc" и "argv" из метода "int main()".
PICLI(int argc, char * argv[]);
//! \~english Add argument with name "name", short key = name first letter and full key = name
//! \~russian Добавляет аргумент с именем "name", коротким ключом = первой букве имени и полным ключом = имени
//! \~english Add argument with name "name", short key = name first letter and full key = name.
//! \~russian Добавляет аргумент с именем "name", коротким ключом = первой букве имени и полным ключом = имени.
void addArgument(const PIString & name, bool value = false) {_args << Argument(name, name[0], name, value); needParse = true;}
//! \~english Add argument with name "name", short key = "shortKey" and full key = name
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени
//! \~english Add argument with name "name", short key = "shortKey" and full key = name.
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени.
void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {_args << Argument(name, shortKey, name, value); needParse = true;}
//! \~english Add argument with name "name", short key = "shortKey" and full key = name
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени
//! \~english Add argument with name "name", short key = "shortKey" and full key = name.
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени.
void addArgument(const PIString & name, const char * shortKey, bool value = false) {_args << Argument(name, PIChar(shortKey), name, value); needParse = true;}
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey"
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey"
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey".
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey".
void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, shortKey, fullKey, value); needParse = true;}
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey"
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey"
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey".
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey".
void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, PIChar(shortKey), fullKey, value); needParse = true;}
//! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command
//! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы
//! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command.
//! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы.
PIString rawArgument(int index) {parse(); return _args_raw[index];}
PIString mandatoryArgument(int index) {parse(); return _args_mand[index];}
PIString optionalArgument(int index) {parse(); return _args_opt[index];}
//! \~english Returns unparsed command-line arguments
//! \~russian Возвращает исходные аргументы командной строки
//! \~english Returns unparsed command-line arguments.
//! \~russian Возвращает исходные аргументы командной строки.
const PIStringList & rawArguments() {parse(); return _args_raw;}
const PIStringList & mandatoryArguments() {parse(); return _args_mand;}
const PIStringList & optionalArguments() {parse(); return _args_opt;}
//! \~english Returns program execute command without arguments
//! \~russian Возвращает команду вызова программы без аргументов
//! \~english Returns program execute command without arguments.
//! \~russian Возвращает команду вызова программы без аргументов.
PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();}
//! \~english Returns if argument "name" found
//! \~russian Возвращает найден ли аргумент "name"
//! \~english Returns if argument "name" found.
//! \~russian Возвращает найден ли аргумент "name".
bool hasArgument(const PIString & name) {parse(); piForeach (Argument & i, _args) if (i.name == name && i.found) return true; return false;}
//! \~english Returns argument "name" value, or empty string if this is no value
//! \~russian Возвращает значение аргумента "name" или пустую строку, если значения нет
//! \~english Returns argument "name" value, or empty string if this is no value.
//! \~russian Возвращает значение аргумента "name" или пустую строку, если значения нет.
PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();}
//! \~english Returns short key of argument "name", or empty string if this is no argument.
//! \~russian Возвращает короткий ключ аргумента "name" или пустую строку, если аргумента нет.
PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();}
//! \~english Returns full key of argument "name", or empty string if this is no argument.
//! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет.
PIString argumentFullKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.full_key; return PIString();}
const PIString & shortKeyPrefix() const {return _prefix_short;}

View File

@@ -42,6 +42,13 @@
//!
bool PIConstChars::contains(char c) const {
for (int i = 0; i < (int)len; ++i)
if (str[i] == c) return true;
return false;
}
bool PIConstChars::startsWith(const PIConstChars & str) const {
if (size() < str.size()) return false;
return str == left(str.size());

View File

@@ -86,6 +86,10 @@ public:
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
inline bool isNotEmpty() const {return len > 0;}
//! \~english Returns \c true if string contains character "c".
//! \~russian Возвращает \c true если строка содержит символ "c".
bool contains(char c) const;
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
inline size_t length() const {return len;}

View File

@@ -108,7 +108,7 @@ class NotifierObject: public PIObject {
PIOBJECT(NotifierObject)
public:
NotifierObject() {}
EVENT2(finished, int, id, PIString*, buffer)
EVENT2(finished, int, id, PIString*, buffer);
};
@@ -154,21 +154,13 @@ DWORD PICout::__Private__::smode = 0;
#endif
PICout::PICout(int controls): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(controls) {
buffer_ = nullptr;
init();
}
PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) {
buffer_ = nullptr;
if (act_)
init();
}
PICout::PICout(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls): fo_(true), cc_(false),
fc_(false), act_(true), cnb_(10), co_(controls) {
init();
buffer_ = buffer;
id_ = id;
if (act_) init();
}
@@ -182,14 +174,16 @@ PICout::~PICout() {
if (fc_) applyFormat(PICoutManipulators::Default);
if (cc_) return;
newLine();
if ((co_ & NoLock) != NoLock)
if ((co_ & NoLock) != NoLock) {
PICout::__mutex__().unlock();
if (buffer_)
}
if (buffer_) {
((NotifierObject*)Notifier::object())->finished(id_, buffer_);
}
}
PICout PICout::operator <<(const PICoutAction v) {
PICout & PICout::operator <<(PICoutAction v) {
if (!act_) return *this;
#ifdef WINDOWS
CONSOLE_SCREEN_BUFFER_INFO sbi;
@@ -198,8 +192,9 @@ PICout PICout::operator <<(const PICoutAction v) {
#endif
switch (v) {
case PICoutManipulators::Flush:
if (!buffer_ && isOutputDeviceActive(StdOut))
if (!buffer_ && isOutputDeviceActive(StdOut)) {
std::cout << std::flush;
}
break;
case PICoutManipulators::Backspace:
if (isOutputDeviceActive(StdOut)) {
@@ -267,15 +262,15 @@ PICout PICout::operator <<(const PICoutAction v) {
#endif
}
break;
case PICoutManipulators::SaveContol: saveControl(); break;
case PICoutManipulators::RestoreControl: restoreControl(); break;
case PICoutManipulators::SaveContol: saveControls(); break;
case PICoutManipulators::RestoreControl: restoreControls(); break;
default: break;
};
return *this;
}
PICout PICout::operator <<(const PICoutManipulators::PICoutFormat v) {
PICout & PICout::operator <<(PICoutManipulators::PICoutFormat v) {
switch (v) {
case PICoutManipulators::Bin: cnb_ = 2; break;
case PICoutManipulators::Oct: cnb_ = 8; break;
@@ -287,7 +282,7 @@ PICout PICout::operator <<(const PICoutManipulators::PICoutFormat v) {
}
PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) {
PICout & PICout::operator <<(PIFlags<PICoutManipulators::PICoutFormat> v) {
if (v[PICoutManipulators::Bin]) cnb_ = 2;
if (v[PICoutManipulators::Oct]) cnb_ = 8;
if (v[PICoutManipulators::Dec]) cnb_ = 10;
@@ -317,121 +312,155 @@ PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v)
return *this;
}
#define PICOUTTOTARGET(v) { \
if (buffer_) {\
(*buffer_) << (v);\
} else {\
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
}\
}
#define PINUMERICCOUT(v) { \
#define PIINTCOUT(v) { \
if (!act_) return *this; \
space(); \
if (cnb_ == 10) PICOUTTOTARGET(v) \
else write(PIString::fromNumber(v, cnb_)); \
if (cnb_ == 10) {\
if (buffer_) {\
(*buffer_) += PIString::fromNumber(v);\
} else {\
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v);\
}\
} else write(PIString::fromNumber(v, cnb_)); \
return *this; \
}
#define PIFLOATCOUT(v) { \
if (buffer_) {\
(*buffer_) += PIString::fromNumber(v, 'g');\
} else {\
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g');\
}\
}\
return *this;
PICout PICout::operator <<(const char * v) {if (!act_ || !v) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
PICout & PICout::operator <<(const PIString & v) {
space();
quote();
write(v);
quote();
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_ || !v) return *this;
if (v[0] == '\0') return *this;
space();
quote();
write(v);
quote();
return *this;
}
PICout PICout::operator <<(const uchar v) {PINUMERICCOUT(ushort(v))}
PICout PICout::operator <<(const short int v) {PINUMERICCOUT(v)}
PICout PICout::operator <<(const ushort v) {PINUMERICCOUT(v)}
PICout PICout::operator <<(const int v) {PINUMERICCOUT(v)}
PICout PICout::operator <<(const uint v) {PINUMERICCOUT(v)}
PICout PICout::operator <<(const long v) {PINUMERICCOUT(v)}
PICout PICout::operator <<(const ulong v) {PINUMERICCOUT(v)}
PICout PICout::operator <<(const llong v) {PINUMERICCOUT(v)}
PICout PICout::operator <<(const ullong v) {PINUMERICCOUT(v)}
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 void * v) {if (!act_) return *this; space(); PICOUTTOTARGET("0x") write(PIString::fromNumber(ullong(v), 16)); return *this;}
PICout PICout::operator <<(const PIObject * v) {
PICout & PICout::operator <<(bool v) {
if (!act_) return *this;
space();
if (v == 0) PICOUTTOTARGET("PIObject*(0x0)")
if (v) write("true");
else write("false");
return *this;
}
PICout & PICout::operator <<(char v) {
if (!act_) return *this;
space();
write(v);
return *this;
}
PICout & PICout::operator <<(uchar v) {PIINTCOUT(ushort(v))}
PICout & PICout::operator <<(short int v) {PIINTCOUT(v)}
PICout & PICout::operator <<(ushort v) {PIINTCOUT(v)}
PICout & PICout::operator <<(int v) {PIINTCOUT(v)}
PICout & PICout::operator <<(uint v) {PIINTCOUT(v)}
PICout & PICout::operator <<(long v) {PIINTCOUT(v)}
PICout & PICout::operator <<(ulong v) {PIINTCOUT(v)}
PICout & PICout::operator <<(llong v) {PIINTCOUT(v)}
PICout & PICout::operator <<(ullong v) {PIINTCOUT(v)}
PICout & PICout::operator <<(float v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
PICout & PICout::operator <<(double v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
PICout & PICout::operator <<(const void * v) {
if (!act_) return *this;
space();
write("0x" + PIString::fromNumber(ullong(v), 16));
return *this;
}
PICout & PICout::operator <<(const PIObject * v) {
if (!act_) return *this;
space();
if (v == 0) write("PIObject*(0x0)");
else {
PICOUTTOTARGET(v->className())
PICOUTTOTARGET("*(0x")
write(PIString::fromNumber(ullong(v), 16));
PICOUTTOTARGET(", \"")
write(v->name());
PICOUTTOTARGET("\")")
write(v->className());
write("*(0x" + PIString::fromNumber(ullong(v), 16) + ", \"" + v->name() + "\")");
}
return *this;
}
PICout PICout::operator <<(const PICoutSpecialChar v) {
PICout & PICout::operator <<(PICoutSpecialChar v) {
if (!act_) return *this;
switch (v) {
case Null:
if (buffer_) {
(*buffer_) << PIChar();
(*buffer_) += PIChar();
} else {
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar();
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar();
}
break;
case NewLine:
if (buffer_) {
(*buffer_) << "\n";
(*buffer_) += "\n";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '\n';
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
}
fo_ = true;
break;
case Tab:
if (buffer_) {
(*buffer_) << "\t";
(*buffer_) += "\t";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '\t';
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\t";
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\t";
}
break;
case Esc:
#ifdef CC_VC
if (buffer_) {
(*buffer_) << PIChar(27);
(*buffer_) += PIChar(27);
} else {
if (isOutputDeviceActive(StdOut)) std::cout << char(27);
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar(27);
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar(27);
}
#else
if (buffer_) {
(*buffer_) << "\e";
(*buffer_) += "\e";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '\e';
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\e";
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\e";
}
#endif
break;
case Quote:
if (buffer_) {
(*buffer_) << "\"";
(*buffer_) += "\"";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '"';
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
}
break;
};
@@ -439,14 +468,14 @@ PICout PICout::operator <<(const PICoutSpecialChar v) {
}
PICout & PICout::saveControl() {
PICout & PICout::saveControls() {
if (!act_) return *this;
PRIVATE->cos_.push(co_);
return *this;
}
PICout & PICout::restoreControl() {
PICout & PICout::restoreControls() {
if (!act_) return *this;
if (!PRIVATE->cos_.isEmpty()) {
co_ = PRIVATE->cos_.top();
@@ -456,8 +485,6 @@ PICout & PICout::restoreControl() {
}
#undef PICOUTTOTARGET
#undef PINUMERICCOUT
//! \details
//! \~english
@@ -469,10 +496,10 @@ PICout & PICout::space() {
if (!act_) return *this;
if (!fo_ && co_[AddSpaces]) {
if (buffer_) {
(*buffer_) << " ";
(*buffer_) += " ";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << ' ';
if (isOutputDeviceActive(Buffer)) PICout::__string__() << " ";
if (isOutputDeviceActive(Buffer)) PICout::__string__() += " ";
}
}
fo_ = false;
@@ -489,10 +516,10 @@ PICout & PICout::quote() {
if (!act_) return *this;
if (co_[AddQuotes]) {
if (buffer_) {
(*buffer_) << "\"";
(*buffer_) += "\"";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << '"';
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
}
}
fo_ = false;
@@ -509,10 +536,10 @@ PICout & PICout::newLine() {
if (!act_) return *this;
if (co_[AddNewLine]) {
if (buffer_) {
(*buffer_) << "\n";
(*buffer_) += "\n";
} else {
if (isOutputDeviceActive(StdOut)) std::cout << std::endl;
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
}
}
fo_ = false;
@@ -520,6 +547,18 @@ PICout & PICout::newLine() {
}
PICout & PICout::write(char c) {
if (!act_) return *this;
if (buffer_) {
buffer_->append(c);
} else {
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << c;
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(c);
}
return *this;
}
PICout & PICout::write(const char * str) {
if (!act_ || !str) return *this;
return write(str, strlen(str));
@@ -543,8 +582,7 @@ PICout & PICout::write(const PIString & s) {
if (buffer_) {
buffer_->append(s);
} else {
if (PICout::isOutputDeviceActive(PICout::StdOut))
stdoutPIString(s);
if (PICout::isOutputDeviceActive(PICout::StdOut)) stdoutPIString(s);
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s);
}
return *this;
@@ -571,10 +609,10 @@ void PICout::init() {
}
attr_ = __Private__::dattr;
#endif
buffer_ = nullptr;
id_ = 0;
if ((co_ & NoLock) != NoLock)
if ((co_ & NoLock) != NoLock) {
PICout::__mutex__().lock();
}
}
@@ -640,24 +678,17 @@ void PICout::applyFormat(PICoutFormat f) {
}
bool PICout::setBufferActive(bool on, bool clear) {
PIString PICout::getBuffer() {
PIMutexLocker ml(PICout::__mutex__());
bool ret = isBufferActive();
if (clear) PICout::__string__().clear();
setOutputDevice(Buffer, on);
PIString ret = PICout::__string__();
return ret;
}
bool PICout::isBufferActive() {
return isOutputDeviceActive(Buffer);
}
PIString PICout::buffer(bool clear) {
PIString PICout::getBufferAndClear() {
PIMutexLocker ml(PICout::__mutex__());
PIString ret = PICout::__string__();
if (clear) PICout::__string__().clear();
PICout::__string__().clear();
return ret;
}
@@ -683,3 +714,11 @@ void PICout::setOutputDevices(PICout::OutputDevices d) {
bool PICout::isOutputDeviceActive(PICout::OutputDevice d) {
return devs[d];
}
PICout PICout::withExternalBuffer(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls) {
PICout c(controls);
c.buffer_ = buffer;
c.id_ = id;
return c;
}

View File

@@ -140,10 +140,6 @@ public:
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine), но если не \"active\" то будет неактивным
PICout(bool active);
//! \~english Construct with external buffer and ID "id". See \a Notifier for details
//! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier
PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
PICout(const PICout & other);
~PICout();
@@ -176,104 +172,109 @@ public:
//! \~english Output operator for strings with <tt>"const char * "</tt> type
//! \~russian Оператор вывода для строк <tt>"const char * "</tt>
PICout operator <<(const char * v);
PICout & operator <<(const char * v);
// ! Output operator for strings with <tt>"std::string"</tt> type
//PICout operator <<(const std::string & v);
//! \~english Output operator for \a PIString
//! \~russian Оператор вывода для \a PIString
PICout & operator <<(const PIString & v);
//! \~english Output operator for boolean values
//! \~russian Оператор вывода для логических значений
PICout operator <<(const bool v);
PICout & operator <<(bool v);
//! \~english Output operator for <tt>"char"</tt> values
//! \~russian Оператор вывода для <tt>"char"</tt> значений
PICout operator <<(const char v);
PICout & operator <<(char v);
//! \~english Output operator for <tt>"unsigned char"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned char"</tt> значений
PICout operator <<(const uchar v);
PICout & operator <<(uchar v);
//! \~english Output operator for <tt>"short"</tt> values
//! \~russian Оператор вывода для <tt>"short"</tt> значений
PICout operator <<(const short v);
PICout & operator <<(short v);
//! \~english Output operator for <tt>"unsigned short"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned short"</tt> значений
PICout operator <<(const ushort v);
PICout & operator <<(ushort v);
//! \~english Output operator for <tt>"int"</tt> values
//! \~russian Оператор вывода для <tt>"int"</tt> значений
PICout operator <<(const int v);
PICout & operator <<(int v);
//! \~english Output operator for <tt>"unsigned int"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned int"</tt> значений
PICout operator <<(const uint v);
PICout & operator <<(uint v);
//! \~english Output operator for <tt>"long"</tt> values
//! \~russian Оператор вывода для <tt>"long"</tt> значений
PICout operator <<(const long v);
PICout & operator <<(long v);
//! \~english Output operator for <tt>"unsigned long"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned long"</tt> значений
PICout operator <<(const ulong v);
PICout & operator <<(ulong v);
//! \~english Output operator for <tt>"long long"</tt> values
//! \~russian Оператор вывода для <tt>"long long"</tt> значений
PICout operator <<(const llong v);
PICout & operator <<(llong v);
//! \~english Output operator for <tt>"unsigned long long"</tt> values
//! \~russian Оператор вывода для <tt>"unsigned long long"</tt> значений
PICout operator <<(const ullong v);
PICout & operator <<(ullong v);
//! \~english Output operator for <tt>"float"</tt> values
//! \~russian Оператор вывода для <tt>"float"</tt> значений
PICout operator <<(const float v);
PICout & operator <<(float v);
//! \~english Output operator for <tt>"double"</tt> values
//! \~russian Оператор вывода для <tt>"double"</tt> значений
PICout operator <<(const double v);
PICout & operator <<(double v);
//! \~english Output operator for pointers
//! \~russian Оператор вывода для указателей
PICout operator <<(const void * v);
PICout & operator <<(const void * v);
//! \~english Output operator for PIObject and ancestors
//! \~russian Оператор вывода для PIObject и наследников
PICout operator <<(const PIObject * v);
PICout & operator <<(const PIObject * v);
//! \~english Output operator for \a PICoutSpecialChar values
//! \~russian Оператор вывода для \a PICoutSpecialChar
PICout operator <<(const PICoutManipulators::PICoutSpecialChar v);
PICout & operator <<(PICoutManipulators::PICoutSpecialChar v);
//! \~english Output operator for \a PIFlags<PICoutFormat> values
//! \~russian Оператор вывода для \a PIFlags<PICoutFormat>
PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v);
PICout & operator <<(PIFlags<PICoutManipulators::PICoutFormat> v);
//! \~english Output operator for \a PICoutFormat values
//! \~russian Оператор вывода для \a PICoutFormat
PICout operator <<(const PICoutManipulators::PICoutFormat v);
PICout & operator <<(PICoutManipulators::PICoutFormat v);
//! \~english Do some action
//! \~russian Делает действие
PICout operator <<(const PICoutManipulators::PICoutAction v);
PICout & operator <<(PICoutManipulators::PICoutAction v);
//! \~english Set control flag "c" is "on" state
//! \~russian Установить флаг "c" в "on" состояние
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
//! \~english Set control flags "c" and if "save" exec \a saveControl()
//! \~russian Установить флаг "c" и если "save" то выполнить \a saveControl()
PICout & setControl(PICoutManipulators::PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;}
//! \~english Set control flags "c"
//! \~russian Установить флаги "c"
PICout & setControls(PICoutManipulators::PICoutControls c) {co_ = c; return *this;}
//! \~english Exec \a saveControls() and set control flags to "c"
//! \~russian Иыполнить \a saveControls() и Установить флаги "c"
PICout & saveAndSetControls(PICoutManipulators::PICoutControls c) {saveControls(); co_ = c; return *this;}
//! \~english Save control flags to internal stack
//! \~russian Сохраняет состояние флагов во внутренний стек
//! \~\sa \a restoreControl()
PICout & saveControl();
PICout & saveControls();
//! \~english Restore control flags from internal stack
//! \~russian Восстанавливает состояние флагов из внутреннего стека
//! \~\sa \a saveControl()
PICout & restoreControl();
PICout & restoreControls();
//! \~english Conditional put space character to output
//! \~russian Условно добавляет пробел
@@ -287,6 +288,10 @@ public:
//! \~russian Условно добавляет новую строку
PICout & newLine();
//! \~english Write char
//! \~russian Пишет символ
PICout & write(char c);
//! \~english Write raw data
//! \~russian Пишет сырые символы
PICout & write(const char * str);
@@ -303,17 +308,13 @@ public:
//! \~russian Вывод \a PIString в stdout
static void stdoutPIString(const PIString & s);
//! \~english Set output device to \a PICout::Buffer and if "clear" clear it
//! \~russian Устанавливает устройство вывода на \a PICout::Buffer и если "clear" то очищает его
static bool setBufferActive(bool on, bool clear = false);
//! \~english Returns internal PIString buffer
//! \~russian Возвращает внутренний PIString буфер
static PIString getBuffer();
//! \~english Equivalent to \a isOutputDeviceActive(OutputDevice)
//! \~russian Аналог \a isOutputDeviceActive(OutputDevice)
static bool isBufferActive();
//! \~english Returns internal PIString buffer and if "clear" clear it
//! \~russian Возвращает внутренний PIString буфер и если "clear" то очищает его
static PIString buffer(bool clear = false);
//! \~english Returns internal PIString buffer and clear it
//! \~russian Возвращает внутренний PIString буфер и очищает его
static PIString getBufferAndClear();
//! \~english Clear internal PIString buffer
//! \~russian Очищает внутренний PIString буфер
@@ -324,14 +325,31 @@ public:
//! \~russian Устройство вывода "d" устанавливается в "on". Возвращает было ли устройство активно
static bool setOutputDevice(OutputDevice d, bool on = true);
//! \~english Turn on output device "d". Returns if it was enabled
//! \~russian Включает устройство вывода "d". Возвращает было ли устройство активно
static bool enableOutputDevice(OutputDevice d) {return setOutputDevice(d, true);}
//! \~english Turn off output device "d". Returns if it was enabled
//! \~russian Выключает устройство вывода "d". Возвращает было ли устройство активно
static bool disableOutputDevice(OutputDevice d) {return setOutputDevice(d, false);}
//! \~english Set output to devices to "d"
//! \~russian Устанавливает устройства вывода "d"
static void setOutputDevices(OutputDevices d);
//! \~english Returns current output devices
//! \~russian Возвращает текущие устройства вывода
static OutputDevices currentOutputDevices() {return devs;}
//! \~english Returns if output device "d" is active
//! \~russian Возвращает активно ли устройство вывода "d"
static bool isOutputDeviceActive(OutputDevice d);
//! \~english Construct with external buffer and ID "id". See \a Notifier for details
//! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier
static PICout withExternalBuffer(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
static PIMutex & __mutex__();
static PIString & __string__();

View File

@@ -312,30 +312,30 @@ PIString datetime2string(const PIDateTime & date, const PIString & format) {
PICout operator <<(PICout s, const PITime & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "PITime(" << v.hours << ":";
s << PIString::fromNumber(v.minutes).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.seconds).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.milliseconds).expandLeftTo(3, '0') << ")";
s.restoreControl();
s.restoreControls();
return s;
}
PICout operator <<(PICout s, const PIDate & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "PIDate(" << v.day << "-";
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
s << v.year << ")";
s.restoreControl();
s.restoreControls();
return s;
}
PICout operator <<(PICout s, const PIDateTime & v) {
s.space();
s.setControl(0, true);
s.saveAndSetControls(0);
s << "PIDateTime(";
s << v.day << "-";
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
@@ -344,7 +344,7 @@ PICout operator <<(PICout s, const PIDateTime & v) {
s << PIString::fromNumber(v.minutes).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.seconds).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.milliseconds).expandLeftTo(3, '0') << ")";
s.restoreControl();
s.restoreControls();
return s;
}

View File

@@ -311,16 +311,6 @@ inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(
//! \~russian Оператор сравнения
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;}
//! \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;}
//! \relatesalso PICout
//! \~english \brief Output operator to PICout
//! \~russian \brief Оператор вывода в PICout

View File

@@ -38,6 +38,7 @@ class PIMutexLocker;
class PIObject;
class PIString;
class PIByteArray;
template <typename P> class PIBinaryStream;
#ifndef MICRO_PIP
class PIInit;
#endif

View File

@@ -0,0 +1,73 @@
/*! \file pimemoryblock.h
* \ingroup Core
* \~\brief
* \~english Base types and functions
* \~russian Базовые типы и методы
*/
/*
PIP - Platform Independent Primitives
Base types and functions
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIMEMORYBLOCK_H
#define PIMEMORYBLOCK_H
//! \ingroup Core
//! \include pimemoryblock.h
//! \brief
//! \~english Help struct to store/restore custom blocks of data to/from PIBinaryStream
//! \~russian Вспомогательная структура для сохранения/извлечения произвольного блока данных в/из PIBinaryStream
struct PIMemoryBlock {
public:
//! \~english Constructs data block
//! \~russian Создает блок данных
PIMemoryBlock(void * data_ = 0, int size_ = 0) {d = data_; s = size_;}
//! \~english Constructs data block
//! \~russian Создает блок данных
PIMemoryBlock(const void * data_, const int size_) {d = const_cast<void * >(data_); s = size_;}
PIMemoryBlock(const PIMemoryBlock & o) {d = o.d; s = o.s;}
PIMemoryBlock & operator =(const PIMemoryBlock & o) {d = o.d; s = o.s; return *this;}
//! \~english Pointer to data
//! \~russian Указатель на данные
void * data() {return d;}
//! \~english Pointer to data
//! \~russian Указатель на данные
const void * data() const {return d;}
//! \~english Size of data in bytes
//! \~russian Размер данных в байтах
int size() const {return s;}
private:
void * d;
int s;
};
//! \~english Returns PIMemoryBlock from pointer to variable "ptr" with type "T"
//! \~russian Возвращает PIMemoryBlock из указателя "ptr" типа "T"
template<typename T>
PIMemoryBlock createMemoryBlock(const T * ptr) {return PIMemoryBlock(ptr, sizeof(T));}
#endif // PIMEMORYBLOCK_H

View File

@@ -23,6 +23,7 @@
#ifndef MICRO_PIP
# include "pisysteminfo.h"
# include "pifile.h"
# include "piiostream.h"
#endif
@@ -249,7 +250,7 @@ PIStringList PIObject::methodsEH() const {
PIMutexLocker ml(__meta_mutex());
PIStringList ret;
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.begin(); eh != ehd.eh_func.end(); eh++)
ret << eh.value().fullFormat();
return ret;
}
@@ -259,7 +260,7 @@ bool PIObject::isMethodEHContains(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex());
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.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
return true;
}
@@ -271,7 +272,7 @@ PIString PIObject::methodEHArguments(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex());
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.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
return eh.value().arguments();
}
@@ -283,7 +284,7 @@ PIString PIObject::methodEHFullFormat(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex());
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.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
return eh.value().fullFormat();
}
@@ -300,7 +301,7 @@ PIVector<PIObject::__MetaFunc> PIObject::findEH(const PIString & name) const {
uint search_id = name.hash();
PIVector<__MetaFunc> ret;
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.begin(); eh != ehd.eh_func.end(); eh++) {
if (eh.value().func_name_id == search_id)
ret << eh.value();
}
@@ -686,7 +687,7 @@ void PIObject::dump(const PIString & line_prefix) const {
const __MetaData & ehd(__meta_data()[classNameID()]);
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << ehd.eh_func.size_s();
//printf("dump %d methods\n", ehd.eh_func.size());
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
for (auto eh = ehd.eh_func.begin(); eh != ehd.eh_func.end(); eh++) {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << eh.value().fullFormat();
}
//printf("dump %d methods ok\n", ehd.eh_func.size());
@@ -750,12 +751,14 @@ bool dumpApplicationToFile(const PIString & path, bool with_objects) {
f.setName("__S__DumpFile");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) return false;
bool ba = PICout::isBufferActive();
PICout::setBufferActive(true, true);
auto out_devs = PICout::currentOutputDevices();
PICout::setOutputDevices(PICout::Buffer);
PICout::clearBuffer();
dumpApplication(with_objects);
f << PICout::buffer();
PIIOTextStream ts(&f);
ts << PICout::getBuffer();
f.close();
PICout::setBufferActive(ba, true);
PICout::setOutputDevices(out_devs);
PIFile::rename(path + "_tmp", path);
return true;
}

View File

@@ -34,8 +34,6 @@
#include "piqueue.h"
#include "piobject_macros.h"
typedef void (*Handler)(void * );
//! \ingroup Core
//! \~\brief
//! \~english This is base class for any classes which use events -> handlers mechanism.
@@ -49,7 +47,7 @@ class PIP_EXPORT PIObject {
typedef PIObject __PIObject__;
typedef void __Parent__;
public:
NO_COPY_CLASS(PIObject)
NO_COPY_CLASS(PIObject);
//! \~english Contructs %PIObject with name "name"
//! \~russian Создает %PIObject с именем "name"
@@ -518,7 +516,7 @@ protected:
//! \~russian Виртуальная функция, вызывается после изменения любого свойства.
virtual void propertyChanged(const char * name) {}
EVENT1(deleted, PIObject *, o)
EVENT1(deleted, PIObject *, o);
//! \events
//! \{

View File

@@ -390,32 +390,32 @@
#define PIOBJECT(name) \
protected: \
typedef name __PIObject__; \
typedef name __PIObject__; \
public: \
static const char * __classNameCC() {return #name;} \
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
virtual const char * className() const {return #name;} \
virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \
static const char * __classNameCC() {return #name;} \
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
const char * className() const override {return #name;} \
uint classNameID() const override {static uint ret = PIStringAscii(#name).hash(); return ret;} \
private: \
virtual int ptrOffset() const {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \
class __BaseInitializer__ { \
public: \
__BaseInitializer__() { \
uint pid = PIObject::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
if (__meta_data().contains(id)) return; \
__meta_data()[pid]; \
__meta_data()[id]; \
__MetaData & ehp(__meta_data()[pid]); \
__MetaData & eh(__meta_data()[id]); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.addScope(__classNameCC(), id); \
} \
}; \
__BaseInitializer__ __base_init__;
int ptrOffset() const override {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \
class __BaseInitializer__ { \
public: \
__BaseInitializer__() { \
uint pid = PIObject::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
if (__meta_data().contains(id)) return; \
__meta_data()[pid]; \
__meta_data()[id]; \
__MetaData & ehp(__meta_data()[pid]); \
__MetaData & eh(__meta_data()[id]); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.addScope(__classNameCC(), id); \
} \
}; \
__BaseInitializer__ __base_init__;
#define PIOBJECT_PARENT(name) \
class __ParentInitializer__ { \
@@ -437,8 +437,8 @@
}; \
__ParentInitializer__ __parent_init__; \
public: \
virtual const char * parentClassName() const {return #name;} \
typedef name __Parent__; \
const char * parentClassName() const override {return #name;} \
typedef name __Parent__; \
private:
#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)

View File

@@ -271,10 +271,26 @@ protected:
};
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage::Property & v) {s << v.name << v.value << v.comment << v.flags; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage::Property & v) {s >> v.name >> v.value >> v.comment >> v.flags; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIPropertyStorage::Property) {s << v.name << v.value << v.comment << v.flags; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIPropertyStorage::Property) {s >> v.name >> v.value >> v.comment >> v.flags; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIPropertyStorage) {s << v.properties(); return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIPropertyStorage) {s >> v.properties(); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage & v) {s << v.properties(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage & v) {s >> v.properties(); return s;}
#endif // PIPROPERTYSTORAGE_H

View File

@@ -56,22 +56,22 @@ const char PIString::toBaseN[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'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,
-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,
-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,
-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, -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, -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};
const char PIString::fromBaseN[] = {(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char) 0, (char) 1, (char) 2, (char) 3, (char) 4, (char) 5, (char) 6, (char) 7, (char) 8, (char) 9, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, (char)21, (char)22, (char)23, (char)24,
(char)25, (char)26, (char)27, (char)28, (char)29, (char)30, (char)31, (char)32, (char)33, (char)34, (char)35, (char)36, (char)37, (char)38, (char)39, (char)-1,
(char)-1, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, (char)21, (char)22, (char)23, (char)24,
(char)25, (char)26, (char)27, (char)28, (char)29, (char)30, (char)31, (char)32, (char)33, (char)34, (char)35, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1};
const float PIString::ElideLeft = 0.f;
const float PIString::ElideCenter = .5f;
@@ -215,6 +215,13 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) {
}
PIString PIString::fromConsole(const PIByteArray & ba) {
PIString ret;
if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __sysoemname__);
return ret;
}
PIString PIString::fromConsole(const char * s) {
PIString ret;
if (!s) return ret;
@@ -224,6 +231,13 @@ PIString PIString::fromConsole(const char * s) {
}
PIString PIString::fromSystem(const PIByteArray & ba) {
PIString ret;
if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __syslocname__);
return ret;
}
PIString PIString::fromSystem(const char * s) {
PIString ret;
if (!s) return ret;
@@ -361,6 +375,13 @@ uint PIString::hash() const {
}
PIByteArray PIString::toSystem() const {
if (isEmpty()) return PIByteArray();
buildData(__syslocname__);
return PIByteArray(data_, strlen(data_));
}
PIByteArray PIString::toUTF8() const {
if (isEmpty()) return PIByteArray();
buildData(__utf8name__);
@@ -390,6 +411,12 @@ PIString & PIString::operator +=(const char * str) {
}
PIString & PIString::operator +=(const PIByteArray & ba) {
appendFromChars((const char * )ba.data(), ba.size_s(), __utf8name__);
return *this;
}
PIString::~PIString() {
deleteData();
}
@@ -462,59 +489,65 @@ bool PIString::operator >(const PIString & str) const {
//! \~\details
//! \~english
//! If "len" < 0 then returns substring from symbol "start" to end.
//! "start" should be >= 0.
//! \~russian
//! Если "len" < 0 тогда возвращается подстрока от символа "start" и до конца.
//! "start" должен быть >= 0.
//! \~\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(0, -1); // s = "0123456789"
//! piCout << s.mid(0, 2); // s = "01"
//! piCout << s.mid(3); // s = "3456789"
//! piCout << s.mid(3, 4); // s = "3456"
//! piCout << s.mid(7, 1); // s = "7"
//! piCout << s.mid(7, 4); // s = "789"
//! piCout << s.mid(-1); // s = ""
//! \endcode
//! \~\sa \a left(), \a right()
PIString PIString::mid(const int start, const int len) const {
//PIString str;
int s = start, l = len;
if (l == 0 || s >= length()) return PIString();
if (s < 0) {
l += s;
s = 0;
PIString PIString::mid(int start, int len) const {
if (len == 0 || start >= length()) return PIString();
if (start < 0) {
return PIString();
}
if (l < 0) {
return PIString(d.data(s), size_s() - s);
if (len < 0) {
return PIString(d.data(start), size_s() - start);
} else {
if (l > length() - s) l = length() - s;
return PIString(d.data(s), l);
if (len > length() - start) len = length() - start;
return PIString(d.data(start), len);
}
return PIString();
}
//! \~\details
//! \~english
//! If "len" < 0 then remove substring from symbol "start" to end.
//! "start" should be >= 0.
//! \~russian
//! Если "len" < 0 тогда удаляется подстрока от символа "start" и до конца.
//! "start" должен быть >= 0.
//! \~\code
//! PIString s("0123456789");
//! s.cutMid(1, 3);
//! piCout << s; // s = "0456789"
//! s.cutMid(-1, 3);
//! s.cutMid(0, 2);
//! piCout << s; // s = "56789"
//! s.cutMid(3, -1);
//! piCout << s; // s = "567"
//! s.cutMid(-1, -1);
//! piCout << s; // s = "567"
//! \endcode
//! \~\sa \a cutLeft(), \a cutRight()
PIString & PIString::cutMid(const int start, const int len) {
int s = start, l = len;
if (l == 0) return *this;
if (s < 0) {
l += s;
s = 0;
PIString & PIString::cutMid(int start, int len) {
if (len == 0) return *this;
if (start < 0) {
return *this;
}
if (l < 0) {
d.remove(s, size() - s);
if (len < 0) {
d.remove(start, size() - start);
} else {
if (l > length() - s) l = length() - s;
d.remove(s, l);
if (len > length() - start) len = length() - start;
d.remove(start, len);
}
return *this;
}
@@ -1658,11 +1691,3 @@ PIString versionNormalize(const PIString & v) {
return ret;
}
PICout operator <<(PICout s, const PIString & v) {
s.space();
s.quote();
s.write(v);
s.quote();
return s;
}

View File

@@ -40,8 +40,7 @@ class PIStringList;
//! \~russian Класс строки.
class PIP_EXPORT PIString
{
friend PIByteArray & operator >>(PIByteArray & s, PIString & v);
friend PIByteArray & operator <<(PIByteArray & s, const PIString & v);
BINARY_STREAM_FRIEND(PIString);
public:
typedef PIDeque<PIChar>::iterator iterator;
typedef PIDeque<PIChar>::const_iterator const_iterator;
@@ -74,10 +73,30 @@ public:
PIString & operator +=(const char c) {d.push_back(PIChar(c)); return *this;}
PIString & operator +=(const char * 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);
PIString & operator +=(const PIString & str);
PIString & operator +=(const PIConstChars & str);
PIString(uchar ) = delete;
PIString( short) = delete;
PIString(ushort) = delete;
PIString( int ) = delete;
PIString(uint ) = delete;
PIString( long ) = delete;
PIString(ulong ) = delete;
PIString( llong) = delete;
PIString(ullong) = delete;
PIString & operator +=(uchar ) = delete;
PIString & operator +=( short) = delete;
PIString & operator +=(ushort) = delete;
PIString & operator +=( int ) = delete;
PIString & operator +=(uint ) = delete;
PIString & operator +=( long ) = delete;
PIString & operator +=(ulong ) = delete;
PIString & operator +=( llong) = delete;
PIString & operator +=(ullong) = delete;
//! \~english Contructs a copy of string.
//! \~russian Создает копию строки.
PIString(const PIString & o) {d = o.d;}
@@ -88,11 +107,11 @@ public:
//! \~english Contructs string with single character "c".
//! \~russian Создает строку из одного символа "c".
PIString(const PIChar c) {*this += c;}
PIString(const PIChar c) {d.push_back(c);}
//! \~english Contructs string with single character "c".
//! \~russian Создает строку из одного символа "c".
PIString(const char c) {*this += PIChar(c);}
PIString(const char c) {d.push_back(PIChar(c));}
//! \~english Contructs string from C-string "str" (system codepage).
//! \~russian Создает строку из C-строки "str" (кодировка системы).
@@ -242,94 +261,6 @@ public:
//! \~russian Оператор сравнения.
bool operator >=(const char * str) const {return *this >= PIString(str);}
//! \~english Append string "str" at the end of string.
//! \~russian Добавляет в конец строку "str".
//! \~\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;}
//! \~english Append character "c" at the end of string.
//! \~russian Добавляет в конец символ "c".
//! \~\details
//! \~\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.
//! \~russian Добавляет в конец символ `c`.
//! \~\details
//! \~\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.
//! \~russian Добавляет в конец C-строку "str".
//! \~\details
//! \~\code
//! PIString s("this");
//! s << " is" << " string"; // s = "this is string"
//! \endcode
PIString & operator <<(const char * str) {*this += str; return *this;}
//! \~english Append \c wchar_t C-string "str" at the end of string.
//! \~russian Добавляет в конец \c wchar_t C-строку "str".
//! \~\details
//! \~\code
//! PIString s;
//! s << L"№ -" << " number"; // s = "№ - number"
//! \endcode
PIString & operator <<(const wchar_t * str) {*this += str; return *this;}
PIString & operator <<(const PIConstChars & str) {*this += str; return *this;}
//! \~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 uint & num) {*this += PIString::fromNumber(num); return *this;}
//! \~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 long & 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 ullong & num) {*this += PIString::fromNumber(num); return *this;}
//! \~english Append string representation of "num" at the end of string.
//! \~russian Добавляет в конец строковое представление "num".
//! \~\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;}
//! \~english Append string representation of "num" at the end of string.
//! \~russian Добавляет в конец строковое представление "num".
//! \~\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;}
//! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент.
//! \~\details
@@ -502,11 +433,11 @@ public:
//! \~english Returns part of string from character at index "start" and maximum length "len".
//! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len".
PIString mid(const int start, const int len = -1) const;
PIString mid(int start, int len = -1) const;
//! \~english Synonym of \a mid().
//! \~russian Аналог \a mid().
PIString subString(const int start, const int len = -1) const {return mid(start, len);}
PIString subString(int start, int len = -1) const {return mid(start, len);}
//! \~english Returns part of string from start and maximum length "len".
//! \~russian Возвращает подстроку от начала и максимальной длиной "len".
@@ -519,7 +450,7 @@ public:
//! 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(int len) const {return len <= 0 ? PIString() : mid(0, len);}
//! \~english Returns part of string at end and maximum length "len".
//! \~russian Возвращает подстроку максимальной длиной "len" и до конца.
@@ -532,11 +463,11 @@ public:
//! 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(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.
//! \~russian Удаляет часть строки от символа "start" и максимальной длины "len", возвращает эту строку.
PIString & cutMid(const int start, const int len);
PIString & cutMid(int start, int len);
//! \~english Remove part of string from start and maximum length "len" and return this string.
//! \~russian Удаляет часть строки от начала и максимальной длины "len", возвращает эту строку.
@@ -551,7 +482,7 @@ public:
//! piCout << s; // s = ""
//! \endcode
//! \~\sa \a cutMid(), \a cutRight()
PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);}
PIString & cutLeft(int len) {return len <= 0 ? *this : cutMid(0, len);}
//! \~english Remove part of string at end and maximum length "len" and return this string.
//! \~russian Удаляет часть строки максимальной длины "len" от конца, возвращает эту строку.
@@ -566,7 +497,7 @@ public:
//! piCout << s; // s = ""
//! \endcode
//! \~\sa \a cutMid(), \a cutLeft()
PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);}
PIString & cutRight(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.
//! \~russian Удаляет пробельные символы с начала и конца строки и возвращает эту строку.
@@ -909,6 +840,10 @@ public:
//! \~russian Тоже самое, что \a toUTF8().
PIByteArray toByteArray() const {return toUTF8();}
//! \~english Returns \a PIByteArray contains \a data() of this string without terminating null-char.
//! \~russian Возвращает \a PIByteArray содержащий \a data() строки без завершающего нулевого байта.
PIByteArray toSystem() const;
//! \~english Returns \a PIByteArray contains \a dataUTF8() of this string without terminating null-char.
//! \~russian Возвращает \a PIByteArray содержащий \a dataUTF8() строки без завершающего нулевого байта.
PIByteArray toUTF8() const;
@@ -1507,10 +1442,18 @@ public:
//! \~english Returns "true" or "false"
//! \~russian Возвращает "true" или "false"
static PIString fromBool(const bool value) {return PIString(value ? PIStringAscii("true") : PIStringAscii("false"));}
//! \~english Returns string constructed from terminal codepage.
//! \~russian Возвращает строку созданную из кодировки консоли.
static PIString fromConsole(const PIByteArray & s);
//! \~english Returns string constructed from terminal codepage.
//! \~russian Возвращает строку созданную из кодировки консоли.
static PIString fromConsole(const char * s);
//! \~english Returns string constructed from system codepage.
//! \~russian Возвращает строку созданную из кодировки системы.
static PIString fromSystem(const PIByteArray & s);
//! \~english Returns string constructed from system codepage.
//! \~russian Возвращает строку созданную из кодировки системы.
@@ -1574,21 +1517,15 @@ private:
mutable char * data_ = nullptr;
};
//! \relatesalso PICout
//! \~english Output operator to \a PICout.
//! \~russian Оператор вывода в \a PICout.
PIP_EXPORT PICout operator <<(PICout s, const PIString & v);
//! \relatesalso PIByteArray
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.d; return s;}
BINARY_STREAM_WRITE(PIString) {s << v.d; return s;}
//! \relatesalso PIByteArray
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {v.d.clear(); s >> v.d; return s;}
BINARY_STREAM_READ(PIString) {s >> v.d; return s;}
//! \~english Returns concatenated string.
@@ -1605,11 +1542,11 @@ inline PIString operator +(const char * str, const PIString & f) {return PIStrin
//! \~english Returns 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 PIString(c) + f;}
//! \~english Returns 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) {PIString s(f); s.push_back(c); return s;}
//! \relatesalso PIString

View File

@@ -126,19 +126,26 @@ public:
};
//! \relatesalso PIByteArray
//! \~english Store operator
//! \~russian Оператор сохранения
inline PIByteArray & operator <<(PIByteArray & s, const PIStringList & v) {s << int(v.size_s()); for (int i = 0; i < v.size_s(); ++i) s << v[i]; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIStringList) {
s << static_cast<const PIDeque<PIString> &>(v);
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIStringList) {
s >> static_cast<PIDeque<PIString> &>(v);
return s;
}
//! \relatesalso PIByteArray
//! \~english Restore operator
//! \~russian Оператор извлечения
inline PIByteArray & operator >>(PIByteArray & s, PIStringList & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIStringList & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << "\"" << v[i] << "\""; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
inline PICout operator <<(PICout s, const PIStringList & v) {s.space(); s.saveAndSetControls(0); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << "\"" << v[i] << "\""; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControls(); return s;}
#endif // PISTRINGLIST_H

View File

@@ -186,7 +186,7 @@ private:
//! \relatesalso PICout
//! \~english \brief Output operator to PICout
//! \~russian \brief Оператор вывода в PICout
inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.setControl(0, true); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControl(); return s;}
inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.saveAndSetControls(0); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControls(); return s;}

View File

@@ -0,0 +1,341 @@
/*! \file pitextstream.h
* \ingroup Core
* \~\brief
* \~english Text serialization functionality over PIBinaryStream
* \~russian Функциональность текстовой сериализации поверх PIBinaryStream
*/
/*
PIP - Platform Independent Primitives
Text serialization functionality over PIBinaryStream
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PITEXTSTREAM_H
#define PITEXTSTREAM_H
#include "pistring.h"
//! \ingroup Core
//! \~\brief
//! \~english Text serialization functionality over PIBinaryStream.
//! \~russian Функциональность текстовой сериализации поверх PIBinaryStream.
template<typename P>
class PITextStream {
public:
//! \~english Floating-point numbers write format
//! \~russian Формат записи чисел с плавающей точкой
enum FloatFormat {
DecimalFormat /** \~english Decimal format, "*.*" \~russian Десятичный формат, "*.*" */ = 'f',
ExponentFormat /** \~english Exponential format, "*e+-<E>" \~russian Экспонентный формат, "*e+-<E>" */ = 'e'
};
//! \~english String encoding
//! \~russian Кодировка строк
enum Encoding {
System /** \~english System encoding \~russian Системная кодировка */,
UTF8 /** \~english UTF-8 encoding \~russian Кодировка UTF-8 */,
};
//! \~english Construct text stream binded to "stream_"
//! \~russian Возвращает привязанный к "stream_" текстовый поток
PITextStream(PIBinaryStream<P> * stream_) {setStream(stream_);}
//! \~english Returns binded PIBinaryStream
//! \~russian Возвращает привязанный PIBinaryStream
PIBinaryStream<P> * stream() const {return s;}
void setStream(PIBinaryStream<P> * stream_) {
s = stream_;
is_end = false;
}
//! \~english Returns if end of stream reached
//! \~russian Возвращает достигнут ли конец потока
bool isEnd() const {return is_end;}
//! \~english Returns read/write encoding
//! \~russian Возвращает кодировку чтения/записи
Encoding encoding() const {return enc;}
//! \~english Set read/write encoding, default UTF8
//! \~russian Устанавливает кодировку чтения/записи, по умолчанию UTF8
void setEncoding(Encoding e) {enc = e;}
//! \~english Returns float numbers write format
//! \~russian Возвращает формат записи чисел с плавающей точкой
FloatFormat floatFormat() const {return format_;}
//! \~english Set float numbers write format, default DecimalFormat
//! \~russian Устанавливает формат записи чисел с плавающей точкой, по умолчанию DecimalFormat
void setFloatFormat(FloatFormat format) {format_ = format;}
//! \~english Returns float numbers write precision
//! \~russian Возвращает точность записи чисел с плавающей точкой
int floatPrecision() const {return prec_;}
//! \~english Set float numbers write precision to "prec_" digits, default 5
//! \~russian Устанавливает точность записи чисел с плавающей точкой, по умолчанию 5
void setFloatPrecision(int prec) {prec_ = prec;}
//! \~english Append space
//! \~russian Добавляет пробел
PITextStream<P> & space() {s->binaryStreamAppend(' '); return *this;}
//! \~english Append new line
//! \~russian Добавляет новую строку
PITextStream<P> & newLine() {s->binaryStreamAppend('\n'); return *this;}
//! \~english Append "v" string
//! \~russian Добавляет строку "v"
void append(const PIString & v) {
if (v.isEmpty()) return;
PIByteArray d;
switch (enc) {
case System: d = v.toSystem(); break;
case UTF8 : d = v.toUTF8(); break;
}
s->binaryStreamAppend(d.data(), d.size());
}
//! \~english Append "v" as ASCII
//! \~russian Добавляет "v" как ASCII
void append(const PIConstChars & v) {if (!v.isEmpty()) s->binaryStreamAppend(v.data(), v.size());}
//! \~english Append "v" char as character
//! \~russian Добавляет "v" как символ
void append(char v) {s->binaryStreamAppend(v);}
//! \~english Append "v" as ASCII
//! \~russian Добавляет "v" как ASCII
void append(const char * v) {append(PIConstChars(v));}
//! \~english Append boolean, "true" of "false"
//! \~russian Добавляет логическое, "true" of "false"
void append(bool v) {append(v ? "true" : "false");}
//! \~english Append integer
//! \~russian Добавляет целое
void append(int v) {append(PIString::fromNumber(v));}
//! \~english Append integer
//! \~russian Добавляет целое
void append(llong v) {append(PIString::fromNumber(v));}
//! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision()
//! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision()
void append(float v) {append(PIString::fromNumber(v, (char)format_, prec_));}
//! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision()
//! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision()
void append(double v) {append(PIString::fromNumber(v, (char)format_, prec_));}
//! \~english Read character
//! \~russian Читает символ
char readChar(bool * rok) {
char ret;
bool ok = s->binaryStreamTake(&ret, sizeof(ret));
if (!ok) is_end = true;
if (rok) *rok = ok;
return ret;
}
//! \~english Read line
//! \~russian Читает строку
PIString readLine() {
PIByteArray ret;
bool ok = true;
for (;;) {
char b = readChar(&ok);
if (!ok || b == '\n') break;
if (b != '\r')
ret.append((uchar)b);
}
return fromBytes(ret);
}
//! \~english Read word, skip leading whitespaces, until next whitespace
//! \~russian Читает слово, пропуская начальные пробельные символы, до следующего пробельного символа
PIString readWord() {
static PIConstChars spaces(" \t\n\r");
return readUntil(spaces);
}
//! \~english Read C-word, skip leading and until non C-identifier
//! \~russian Читает C-слово, пропуская начальные и до следующих символов, не являющихся C-идентификаторами
PIString readCWord() {
static PIConstChars chars(" \t\n\r:;%$&#@!?~/*-+=.,\\\"'`[](){}<>");
return readUntil(chars);
}
private:
PIString fromBytes(const PIByteArray & ba) {
switch (enc) {
case System: return PIString::fromSystem(ba);
case UTF8 : return PIString::fromUTF8(ba);
}
return PIString();
}
PIString readUntil(const PIConstChars & chars) {
//static PIConstChars spaces(" \t\n\r");
bool ok = true;
char c = skipWhile(chars, &ok);
if (!ok) return PIString();
PIByteArray ret;
ret.append((uchar)c);
for (;;) {
c = readChar(&ok);
if (!ok || chars.contains(c)) break;
ret.append((uchar)c);
}
return fromBytes(ret);
}
// returns first non-"chars" char
char skipWhile(const PIConstChars & chars, bool * rok) {
bool ok = true;
char c = 0;
for (;;) {
c = readChar(&ok);
if (!ok || !chars.contains(c)) break;
}
if (rok) *rok = ok;
return c;
}
PIBinaryStream<P> * s;
Encoding enc = UTF8;
FloatFormat format_ = DecimalFormat;
bool is_end = false;
int prec_ = 5;
};
//! \~english Returns PITextStream for binary stream "stream"
//! \~russian Возвращает PITextStream для бинарного потока "stream"
template<typename P>
inline PITextStream<P> createPITextStream(PIBinaryStream<P> * stream) {return PITextStream<P>(stream);}
//! \~english Append boolean
//! \~russian Добавляет логическое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, bool v) {s.append(v); return s;}
//! \~english Append character
//! \~russian Добавляет символ
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, char v) {s.append(v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, uchar v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, short v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, ushort v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, int v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, uint v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, llong v) {s.append((llong)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, ullong v) {s.append((llong)v); return s;}
//! \~english Append floating-point number
//! \~russian Добавляет число с плавающей точкой
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, float v) {s.append(v); return s;}
//! \~english Append floating-point number
//! \~russian Добавляет число с плавающей точкой
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, double v) {s.append(v); return s;}
//! \~english Append string
//! \~russian Добавляет строку
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const char * v) {s.append(v); return s;}
//! \~english Append string
//! \~russian Добавляет строку
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const PIConstChars & v) {s.append(v); return s;}
//! \~english Append string
//! \~russian Добавляет строку
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const PIString & v) {s.append(v); return s;}
//! \~english Read word as bool
//! \~russian Читает слово как логическое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, bool & v) {v = s.readWord().toBool(); return s;}
//! \~english Read character
//! \~russian Читает символ
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, char & v) {v = s.readChar(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, uchar & v) {v = s.readWord().toUInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, short & v) {v = s.readWord().toInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, ushort & v) {v = s.readWord().toUInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, int & v) {v = s.readWord().toInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, uint & v) {v = s.readWord().toUInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, llong & v) {v = s.readWord().toLLong(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, ullong & v) {v = s.readWord().toULLong(); return s;}
//! \~english Read word as floating-point number
//! \~russian Читает слово как число с плавающей точкой
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, float & v) {v = s.readWord().toFloat(); return s;}
//! \~english Read word as floating-point number
//! \~russian Читает слово как число с плавающей точкой
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, double & v) {v = s.readWord().toDouble(); return s;}
//! \~english Read word
//! \~russian Читает слово
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, PIString & v) {v = s.readWord(); return s;}
#endif

View File

@@ -20,32 +20,49 @@
#include "pivariant.h"
/** \class PIVariant
* \details
* \section PIVariant_sec0 Synopsis
* This class provides general type that can contains all standard types, some
* PIP types or custom type. In case of standard types this class also provides
* convertions between them.
*
* \section PIVariant_sec1 Usage
* %PIVariant useful if you want pass many variables with different types in
* single array, e.g.:
* \code{cpp}
* PIVector<PIVariant> array;
* array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF");
* piCout << array;
* piForeachC (PIVariant & i, array)
* piCout << i.toInt();
* \endcode
* Result:
* \code{cpp}
* {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)}
* 10
* 1
* 1
* 255
* \endcode
* */
//! \class PIVariant pivariant.h
//! \details
//! \~english \section PIVariant_sec0 Synopsis
//! \~russian \section PIVariant_sec0 Краткий обзор
//! \~english
//! This class provides general type that can contains all standard types, some
//! PIP types or custom type. In case of standard types this class also provides
//! convertions between them.
//!
//! \~russian
//! Этот класс предоставляет некий общий тип, который может содержать все стандартные тип,
//! некоторые типы PIP, а также любой свой тип. В случае стандартных типов предоставляется
//! автоматическое преобразование между ними.
//!
//! \~english \section PIVariant_sec1 Usage
//! \~russian \section PIVariant_sec1 Использование
//! \~english
//! %PIVariant useful if you want pass many variables with different types in
//! single array, or type may vary from case to case, e.g.:
//!
//! \~russian
//! %PIVariant полезен когда надо передать несколько разнотипных значений
//! одним массивом, или тип заранее неизвестен, например:
//!
//! \~\code{cpp}
//! PIVector<PIVariant> array;
//! array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF");
//! piCout << array;
//! for (auto i: array)
//! piCout << i.toInt();
//! \endcode
//!
//! \~english Result:
//! \~russian Результат:
//! \~\code{cpp}
//! {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)}
//! 10
//! 1
//! 1
//! 255
//! \endcode
//!
#ifdef CUSTOM_PIVARIANT
PIMap<PIString, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = 0;
@@ -158,6 +175,8 @@ PIVariant::Type PIVariant::typeFromName(const PIString & tname) {
if (s == "rect") return PIVariant::pivRect;
if (s == "vector") return PIVariant::pivMathVector;
if (s == "matrix") return PIVariant::pivMathMatrix;
if (s == "line") return PIVariant::pivLine;
if (s == "device" || s == "iodevice") return PIVariant::pivIODevice;
return PIVariant::pivInvalid;
}
@@ -219,12 +238,25 @@ PIString PIVariant::typeName(PIVariant::Type type) {
}
/** \brief Returns variant content as boolean
* \details In case of numeric types returns \b true if value != 0. \n
* In case of String type returns \a PIString::toBool(). \n
* In case of StringList type returns \b false if string list is empty,
* otherwise returns \a PIString::toBool() of first string. \n
* In case of other types returns \b false. */
//! \~\brief
//! \~english Returns variant content as boolean
//! \~russian Возвращает содержимое как boolean
//!
//! \~\details
//! \~english
//! In case of numeric types returns \b true if value != 0. \n
//! In case of String type returns \a PIString::toBool(). \n
//! In case of StringList type returns \b false if string list is empty,
//! otherwise returns \a PIString::toBool() of first string. \n
//! In case of other types returns \b false.
//!
//! \~russian
//! Для численных типов возвращает \b true если значение != 0. \n
//! Для типа String возвращает \a PIString::toBool(). \n
//! Для типа StringList возвращает \b false если массив пустой, \n
//! иначе возвращает \a PIString::toBool() первой строки. \n
//! Для остальных типов возвращает \b false.
//!
bool PIVariant::toBool() const {
PIByteArray ba(_content);
switch (_type) {
@@ -250,12 +282,25 @@ bool PIVariant::toBool() const {
/** \brief Returns variant content as int
* \details In case of numeric types returns integer value. \n
* In case of String type returns \a PIString::toInt(). \n
* In case of StringList type returns \b 0 if string list is empty,
* otherwise returns \a PIString::toInt() of first string. \n
* In case of other types returns \b 0. */
//! \~\brief
//! \~english Returns variant content as int
//! \~russian Возвращает содержимое как int
//!
//! \~\details
//! \~english
//! In case of numeric types returns integer value. \n
//! In case of String type returns \a PIString::toInt(). \n
//! In case of StringList type returns \b 0 if string list is empty,
//! otherwise returns \a PIString::toInt() of first string. \n
//! In case of other types returns \b 0.
//!
//! \~russian
//! Для численных типов возвращает целочисленное значение. \n
//! Для типа String возвращает \a PIString::toInt(). \n
//! Для типа StringList возвращает \b 0 если массив пустой, \n
//! иначе возвращает \a PIString::toInt() первой строки. \n
//! Для остальных типов возвращает \b 0.
//!
int PIVariant::toInt() const {
PIByteArray ba(_content);
switch (_type) {
@@ -282,12 +327,25 @@ int PIVariant::toInt() const {
}
/** \brief Returns variant content as long long
* \details In case of numeric types returns integer value. \n
* In case of String type returns \a PIString::toLLong(). \n
* In case of StringList type returns \b 0L if string list is empty,
* otherwise returns \a PIString::toLLong() of first string. \n
* In case of other types returns \b 0L. */
//! \~\brief
//! \~english Returns variant content as long long
//! \~russian Возвращает содержимое как long long
//!
//! \~\details
//! \~english
//! In case of numeric types returns integer value. \n
//! In case of String type returns \a PIString::toLLong(). \n
//! In case of StringList type returns \b 0L if string list is empty,
//! otherwise returns \a PIString::toLLong() of first string. \n
//! In case of other types returns \b 0L.
//!
//! \~russian
//! Для численных типов возвращает целочисленное значение. \n
//! Для типа String возвращает \a PIString::toLLong(). \n
//! Для типа StringList возвращает \b 0L если массив пустой, \n
//! иначе возвращает \a PIString::toLLong() первой строки. \n
//! Для остальных типов возвращает \b 0L.
//!
llong PIVariant::toLLong() const {
PIByteArray ba(_content);
switch (_type) {
@@ -313,12 +371,25 @@ llong PIVariant::toLLong() const {
}
/** \brief Returns variant content as float
* \details In case of numeric types returns float value. \n
* In case of String type returns \a PIString::toFloat(). \n
* In case of StringList type returns \b 0.f if string list is empty,
* otherwise returns \a PIString::toFloat() of first string. \n
* In case of other types returns \b 0.f. */
//! \~\brief
//! \~english Returns variant content as float
//! \~russian Возвращает содержимое как float
//!
//! \~\details
//! \~english
//! In case of numeric types returns float value. \n
//! In case of String type returns \a PIString::toFloat(). \n
//! In case of StringList type returns \b 0.f if string list is empty,
//! otherwise returns \a PIString::toFloat() of first string. \n
//! In case of other types returns \b 0.f .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toFloat(). \n
//! Для типа StringList возвращает \b 0.f если массив пустой, \n
//! иначе возвращает \a PIString::toFloat() первой строки. \n
//! Для остальных типов возвращает \b 0.f .
//!
float PIVariant::toFloat() const {
PIByteArray ba(_content);
switch (_type) {
@@ -344,12 +415,25 @@ float PIVariant::toFloat() const {
}
/** \brief Returns variant content as double
* \details In case of numeric types returns double value. \n
* In case of String type returns \a PIString::toDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toDouble() of first string. \n
* In case of other types returns \b 0.. */
//! \~\brief
//! \~english Returns variant content as double
//! \~russian Возвращает содержимое как double
//!
//! \~\details
//! \~english
//! In case of numeric types returns double value. \n
//! In case of String type returns \a PIString::toDouble(). \n
//! In case of StringList type returns \b 0. if string list is empty,
//! otherwise returns \a PIString::toDouble() of first string. \n
//! In case of other types returns \b 0. .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toDouble(). \n
//! Для типа StringList возвращает \b 0. если массив пустой, \n
//! иначе возвращает \a PIString::toDouble() первой строки. \n
//! Для остальных типов возвращает \b 0. .
//!
double PIVariant::toDouble() const {
PIByteArray ba(_content);
switch (_type) {
@@ -375,12 +459,25 @@ double PIVariant::toDouble() const {
}
/** \brief Returns variant content as long double
* \details In case of numeric types returns long double value. \n
* In case of String type returns \a PIString::toLDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toLDouble() of first string. \n
* In case of other types returns \b 0.. */
//! \~\brief
//! \~english Returns variant content as long double
//! \~russian Возвращает содержимое как long double
//!
//! \~\details
//! \~english
//! In case of numeric types returns long double value. \n
//! In case of String type returns \a PIString::toLDouble(). \n
//! In case of StringList type returns \b 0. if string list is empty,
//! otherwise returns \a PIString::toLDouble() of first string. \n
//! In case of other types returns \b 0. .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toLDouble(). \n
//! Для типа StringList возвращает \b 0. если массив пустой, \n
//! иначе возвращает \a PIString::toLDouble() первой строки. \n
//! Для остальных типов возвращает \b 0. .
//!
ldouble PIVariant::toLDouble() const {
PIByteArray ba(_content);
switch (_type) {
@@ -406,10 +503,21 @@ ldouble PIVariant::toLDouble() const {
}
/** \brief Returns variant content as time
* \details In case of Time type returns time value. \n
* In case of DateTime type returns time part of value. \n
* In case of other types returns \a PITime(). */
//! \~\brief
//! \~english Returns variant content as time
//! \~russian Возвращает содержимое как время
//!
//! \~\details
//! \~english
//! In case of Time type returns time value. \n
//! In case of DateTime type returns time part of value. \n
//! In case of other types returns \a PITime().
//!
//! \~russian
//! Для типа Time возвращает время. \n
//! Для типа DateTime возвращает часть времени. \n
//! Для остальных типов возвращает \a PITime().
//!
PITime PIVariant::toTime() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivTime) {PITime r; ba >> r; return r;}
@@ -419,10 +527,21 @@ PITime PIVariant::toTime() const {
}
/** \brief Returns variant content as date
* \details In case of Date type returns date value. \n
* In case of DateTime type returns date part of value. \n
* In case of other types returns \a PIDate(). */
//! \~\brief
//! \~english Returns variant content as date
//! \~russian Возвращает содержимое как дата
//!
//! \~\details
//! \~english
//! In case of Date type returns date value. \n
//! In case of DateTime type returns date part of value. \n
//! In case of other types returns \a PIDate().
//!
//! \~russian
//! Для типа Date возвращает дату. \n
//! Для типа DateTime возвращает часть даты. \n
//! Для остальных типов возвращает \a PIDate().
//!
PIDate PIVariant::toDate() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivDate) {PIDate r; ba >> r; return r;}
@@ -432,11 +551,23 @@ PIDate PIVariant::toDate() const {
}
/** \brief Returns variant content as date and time
* \details In case of Time type returns time value with null date. \n
* In case of Date type returns date value with null time. \n
* In case of DateTime type returns date and time. \n
* In case of other types returns \a PIDateTime(). */
//! \~\brief
//! \~english Returns variant content as date and time
//! \~russian Возвращает содержимое как дата и время
//!
//! \~\details
//! \~english
//! In case of Time type returns time value with null date. \n
//! In case of Date type returns date value with null time. \n
//! In case of DateTime type returns date and time. \n
//! In case of other types returns \a PIDateTime().
//!
//! \~russian
//! Для типа Time возвращает время без даты. \n
//! Для типа Date возвращает дату без времени. \n
//! Для типа DateTime возвращает время и дату. \n
//! Для остальных типов возвращает \a PIDateTime().
//!
PIDateTime PIVariant::toDateTime() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivTime) {PITime r; ba >> r; return PIDateTime(r);}
@@ -447,10 +578,19 @@ PIDateTime PIVariant::toDateTime() const {
}
/** \brief Returns variant content as system time
* \details In case of SystemTime type returns system time. \n
* In case of other types returns \a PISystemTime::fromSeconds() from
* double value of variant content. */
//! \~\brief
//! \~english Returns variant content as system time
//! \~russian Возвращает содержимое как системное время
//!
//! \~\details
//! \~english
//! In case of SystemTime type returns system time. \n
//! In case of other types returns \a PISystemTime::fromSeconds() from \a toDouble().
//!
//! \~russian
//! Для типа SystemTime возвращает системное время. \n
//! Для остальных типов возвращает \a PISystemTime::fromSeconds() от \a toDouble().
//!
PISystemTime PIVariant::toSystemTime() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivSystemTime) {PISystemTime r; ba >> r; return r;}
@@ -459,15 +599,30 @@ PISystemTime PIVariant::toSystemTime() const {
}
/** \brief Returns variant content as string
* \details In case of numeric types returns \a PIString::fromNumber(). \n
* In case of String type returns string value. \n
* In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n
* In case of BitArray or ByteArray types returns number of bits/bytes. \n
* In case of Time, Date or DateTime types returns toString() of this values. \n
* In case of SystemTime types returns second and nanoseconds of time
* ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n
* In case of other types returns \b "". */
//! \~\brief
//! \~english Returns variant content as string
//! \~russian Возвращает содержимое как строка
//!
//! \~\details
//! \~english
//! In case of numeric types returns \a PIString::fromNumber(). \n
//! In case of String type returns string value. \n
//! In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n
//! In case of BitArray or ByteArray types returns number of bits/bytes. \n
//! In case of Time, Date or DateTime types returns toString() of this values. \n
//! In case of SystemTime types returns second and nanoseconds of time
//! ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n
//! In case of other types returns \b "".
//!
//! \~russian
//! Для численных типов возвращает \a PIString::fromNumber(). \n
//! Для типа String возвращает строку. \n
//! Для типа StringList возвращает объединенную строку ("(" + PIStringList::join("; ") + ")"). \n
//! Для типов BitArray или ByteArray возвращает количество бит/байт. \n
//! Для типов Time, Date или DateTime возвращает toString(). \n
//! Для типов SystemTime возвращает секунды и наносекунды в формате "(s, ns)".
//! Для остальных типов возвращает \b "".
//!
PIString PIVariant::toString() const {
PIByteArray ba(_content);
switch (_type) {
@@ -500,9 +655,19 @@ PIString PIVariant::toString() const {
}
/** \brief Returns variant content as strings list
* \details In case of StringList type returns strings list value. \n
* In case of other types returns \a PIStringList with one string value of variant content. */
//! \~\brief
//! \~english Returns variant content as strings list
//! \~russian Возвращает содержимое как массив строк
//!
//! \~\details
//! \~english
//! In case of StringList type returns strings list value. \n
//! In case of other types returns \a PIStringList with one string \a toString().
//!
//! \~russian
//! Для типа StringList возвращает массив строк. \n
//! Для остальных типов возвращает \a PIStringList с одной строкой \a toString().
//!
PIStringList PIVariant::toStringList() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivStringList) {PIStringList r; ba >> r; return r;}
@@ -512,9 +677,19 @@ PIStringList PIVariant::toStringList() const {
}
/** \brief Returns variant content as bit array
* \details In case of BitArray type returns bit array value. \n
* In case of other types returns \a PIBitArray from \a toLLong() value. */
//! \~\brief
//! \~english Returns variant content as bit array
//! \~russian Возвращает содержимое как массив битов
//!
//! \~\details
//! \~english
//! In case of BitArray type returns bit array value. \n
//! In case of other types returns \a PIBitArray from \a toLLong() value.
//!
//! \~russian
//! Для типа BitArray возвращает массив битов. \n
//! Для остальных типов возвращает \a PIBitArray от значения \a toLLong().
//!
PIBitArray PIVariant::toBitArray() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivBitArray) {PIBitArray r; ba >> r; return r;}
@@ -523,9 +698,19 @@ PIBitArray PIVariant::toBitArray() const {
}
/** \brief Returns variant content as byte array
* \details In case of ByteArray type returns byte array value. \n
* In case of other types returns empty \a PIByteArray. */
//! \~\brief
//! \~english Returns variant content as byte array
//! \~russian Возвращает содержимое как массив байтов
//!
//! \~\details
//! \~english
//! In case of ByteArray type returns byte array value. \n
//! In case of other types returns empty \a PIByteArray.
//!
//! \~russian
//! Для типа ByteArray возвращает массив байтов. \n
//! Для остальных типов возвращает пустой \a PIByteArray.
//!
PIByteArray PIVariant::toByteArray() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivByteArray) {PIByteArray r; ba >> r; return r;}
@@ -534,11 +719,23 @@ PIByteArray PIVariant::toByteArray() const {
}
/** \brief Returns variant content as enum
* \details In case of Enum type returns enum value. \n
* In case of String returns Enum with one member. \n
* In case of StringList returns Enum with corresponding members. \n
* In case of other types returns empty Enum. */
//! \~\brief
//! \~english Returns variant content as enum
//! \~russian Возвращает содержимое как перечисление
//!
//! \~\details
//! \~english
//! In case of Enum type returns enum value. \n
//! In case of String returns Enum with one member. \n
//! In case of StringList returns Enum with corresponding members. \n
//! In case of other types returns empty Enum.
//!
//! \~russian
//! Для типа Enum возвращает перечисление. \n
//! Для типа String возвращает Enum с одним членом. \n
//! Для типа StringList возвращает Enum с членами по строкам. \n
//! Для остальных типов возвращает пустой Enum.
//!
PIVariantTypes::Enum PIVariant::toEnum() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivEnum) {PIVariantTypes::Enum r; ba >> r; return r;}
@@ -549,10 +746,21 @@ PIVariantTypes::Enum PIVariant::toEnum() const {
}
/** \brief Returns variant content as file
* \details In case of File type returns file value. \n
* In case of String returns File with string value path. \n
* In case of other types returns empty File. */
//! \~\brief
//! \~english Returns variant content as file
//! \~russian Возвращает содержимое как файл
//!
//! \~\details
//! \~english
//! In case of File type returns file value. \n
//! In case of String returns File with string value path. \n
//! In case of other types returns empty File.
//!
//! \~russian
//! Для типа File возвращает файл. \n
//! Для типа String возвращает File с путем значения строки. \n
//! Для остальных типов возвращает пустой File.
//!
PIVariantTypes::File PIVariant::toFile() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivFile) {PIVariantTypes::File r; ba >> r; return r;}
@@ -562,10 +770,21 @@ PIVariantTypes::File PIVariant::toFile() const {
}
/** \brief Returns variant content as dir
* \details In case of Dir type returns dir value. \n
* In case of String returns Dir with string value path. \n
* In case of other types returns empty Dir. */
//! \~\brief
//! \~english Returns variant content as dir
//! \~russian Возвращает содержимое как директория
//!
//! \~\details
//! \~english
//! In case of Dir type returns dir value. \n
//! In case of String returns Dir with string value path. \n
//! In case of other types returns empty Dir.
//!
//! \~russian
//! Для типа Dir возвращает директорию. \n
//! Для типа String возвращает Dir с путем значения строки. \n
//! Для остальных типов возвращает пустой Dir.
//!
PIVariantTypes::Dir PIVariant::toDir() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivDir) {PIVariantTypes::Dir r; ba >> r; return r;}
@@ -575,10 +794,21 @@ PIVariantTypes::Dir PIVariant::toDir() const {
}
/** \brief Returns variant content as color
* \details In case of Color type returns color value. \n
* In case of int returns color with int value. \n
* In case of other types returns empty Color. */
//! \~\brief
//! \~english Returns variant content as color
//! \~russian Возвращает содержимое как цвет
//!
//! \~\details
//! \~english
//! In case of Color type returns color value. \n
//! In case of Int returns color with int value. \n
//! In case of other types returns empty Color.
//!
//! \~russian
//! Для типа Color возвращает цвет. \n
//! Для типа Int возвращает цвет с целочисленным значением. \n
//! Для остальных типов возвращает пустой Color.
//!
PIVariantTypes::Color PIVariant::toColor() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivColor) {PIVariantTypes::Color r; ba >> r; return r;}
@@ -588,9 +818,19 @@ PIVariantTypes::Color PIVariant::toColor() const {
}
/** \brief Returns variant content as IODevice
* \details In case of IODevice type returns IODevice value. \n
* In case of other types returns empty IODevice. */
//! \~\brief
//! \~english Returns variant content as IODevice
//! \~russian Возвращает содержимое как IODevice
//!
//! \~\details
//! \~english
//! In case of IODevice type returns IODevice value. \n
//! In case of other types returns empty IODevice.
//!
//! \~russian
//! Для типа IODevice возвращает IODevice. \n
//! Для остальных типов возвращает пустой IODevice.
//!
PIVariantTypes::IODevice PIVariant::toIODevice() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivIODevice) {PIVariantTypes::IODevice r; ba >> r; return r;}
@@ -598,9 +838,19 @@ PIVariantTypes::IODevice PIVariant::toIODevice() const {
}
/** \brief Returns variant content as point
* \details In case of PIPointd type returns point value. \n
* In case of other types returns empty PIPointd. */
//! \~\brief
//! \~english Returns variant content as point
//! \~russian Возвращает содержимое как точка
//!
//! \~\details
//! \~english
//! In case of Point type returns point value. \n
//! In case of other types returns empty PIPointd.
//!
//! \~russian
//! Для типа Point возвращает точку. \n
//! Для остальных типов возвращает пустую PIPointd.
//!
PIPointd PIVariant::toPoint() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivPoint) {PIPointd r; ba >> r; return r;}
@@ -608,9 +858,19 @@ PIPointd PIVariant::toPoint() const {
}
/** \brief Returns variant content as rect
* \details In case of PIRectd type returns rect value. \n
* In case of other types returns empty PIRectd. */
//! \~\brief
//! \~english Returns variant content as rect
//! \~russian Возвращает содержимое как прямоугольник
//!
//! \~\details
//! \~english
//! In case of Rect type returns rect value. \n
//! In case of other types returns empty PIRectd.
//!
//! \~russian
//! Для типа Rect возвращает прямоугольник. \n
//! Для остальных типов возвращает пустой PIRectd.
//!
PIRectd PIVariant::toRect() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivRect) {PIRectd r; ba >> r; return r;}
@@ -618,9 +878,19 @@ PIRectd PIVariant::toRect() const {
}
/** \brief Returns variant content as line
* \details In case of PILined type returns line value. \n
* In case of other types returns empty PILined. */
//! \~\brief
//! \~english Returns variant content as line
//! \~russian Возвращает содержимое как линия
//!
//! \~\details
//! \~english
//! In case of Line type returns line value. \n
//! In case of other types returns empty PILined.
//!
//! \~russian
//! Для типа Line возвращает линию. \n
//! Для остальных типов возвращает пустую PILined.
//!
PILined PIVariant::toLine() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivLine) {PILined r; ba >> r; return r;}
@@ -628,9 +898,19 @@ PILined PIVariant::toLine() const {
}
/** \brief Returns variant content as math vector
* \details In case of PIMathVectord type returns rect value. \n
* In case of other types returns empty PIMathVectord. */
//! \~\brief
//! \~english Returns variant content as math vector
//! \~russian Возвращает содержимое как вектор
//!
//! \~\details
//! \~english
//! In case of MathVector type returns rect value. \n
//! In case of other types returns empty PIMathVectord.
//!
//! \~russian
//! Для типа MathVector возвращает вектор. \n
//! Для остальных типов возвращает пустой PIMathVectord.
//!
PIMathVectord PIVariant::toMathVector() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivMathVector) {PIMathVectord r; ba >> r; return r;}
@@ -638,9 +918,19 @@ PIMathVectord PIVariant::toMathVector() const {
}
/** \brief Returns variant content as math matrix
* \details In case of PIMathMatrixd type returns rect value. \n
* In case of other types returns empty PIMathMatrixd. */
//! \~\brief
//! \~english Returns variant content as math matrix
//! \~russian Возвращает содержимое как матрица
//!
//! \~\details
//! \~english
//! In case of MathMatrix type returns rect value. \n
//! In case of other types returns empty PIMathMatrixd.
//!
//! \~russian
//! Для типа MathMatrix возвращает матрицу. \n
//! Для остальных типов возвращает пустую PIMathMatrixd.
//!
PIMathMatrixd PIVariant::toMathMatrix() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivMathMatrix) {PIMathMatrixd r; ba >> r; return r;}

View File

@@ -33,6 +33,23 @@
#include "pimathmatrix.h"
#ifdef DOXYGEN
//! \relatesalso PIVariant
//! \~\brief
//! \~english Macro to register type for using in %PIVariant
//! \~russian Макрос для регистрации типа для использования в %PIVariant
# define REGISTER_VARIANT(Typename)
//! \relatesalso PIVariant
//! \~\brief
//! \~english Macro to register type with namespace for using in %PIVariant
//! \~russian Макрос для регистрации типа с пространством имен для использования в %PIVariant
# define REGISTER_NS_VARIANT(Namespace, Typename)
#endif
#ifndef QNX
# define CUSTOM_PIVARIANT
#endif
@@ -204,246 +221,316 @@ classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(c
//! \ingroup Core
//! \~\brief
//! \~english Variant type.
//! \~russian Вариантный тип.
class PIP_EXPORT PIVariant {
friend PICout operator <<(PICout s, const PIVariant & v);
friend PIByteArray & operator <<(PIByteArray & s, const PIVariant & v);
friend PIByteArray & operator >>(PIByteArray & s, PIVariant & v);
BINARY_STREAM_FRIEND(PIVariant);
public:
//! Type of %PIVariant content
//! \~english Type of %PIVariant content
//! \~russian Тип содержимого %PIVariant
enum Type {
pivInvalid /** Invalid type , default type of empty contructor */ = 0 ,
pivBool /** bool */ ,
pivChar /** char */ ,
pivUChar /** uchar */ ,
pivShort /** short */ ,
pivUShort /** ushort */ ,
pivInt /** int */ ,
pivUInt /** uint */ ,
pivLLong /** llong */ ,
pivULLong /** ullong */ ,
pivFloat /** float */ ,
pivDouble /** double */ ,
pivLDouble /** ldouble */ ,
pivComplexd /** complexd */ ,
pivComplexld /** complexld */ ,
pivBitArray /** PIBitArray */ ,
pivByteArray /** PIByteArray */ ,
pivString /** PIString */ ,
pivInvalid /** \~english Invalid type, default type of empty contructor \~russian Недействительный тип, также конструированный по умолчанию */ = 0 ,
pivBool /** bool */ ,
pivChar /** char */ ,
pivUChar /** uchar */ ,
pivShort /** short */ ,
pivUShort /** ushort */ ,
pivInt /** int */ ,
pivUInt /** uint */ ,
pivLLong /** llong */ ,
pivULLong /** ullong */ ,
pivFloat /** float */ ,
pivDouble /** double */ ,
pivLDouble /** ldouble */ ,
pivComplexd /** complexd */ ,
pivComplexld /** complexld */ ,
pivBitArray /** PIBitArray */ ,
pivByteArray /** PIByteArray */ ,
pivString /** PIString */ ,
pivStringList /** PIStringList */ ,
pivTime /** PITime */ ,
pivDate /** PIDate */ ,
pivDateTime /** PIDateTime */ ,
pivTime /** PITime */ ,
pivDate /** PIDate */ ,
pivDateTime /** PIDateTime */ ,
pivSystemTime /** PISystemTime */ ,
pivEnum /** PIVariantTypes::Enum */ ,
pivFile /** PIVariantTypes::File */ ,
pivDir /** PIVariantTypes::Dir */ ,
pivColor /** PIVariantTypes::Color */ ,
pivPoint /** PIPoint<double> */ ,
pivRect /** PIRect<double> */ ,
pivIODevice /** PIVariantTypes::IODevice */ ,
pivEnum /** PIVariantTypes::Enum */ ,
pivFile /** PIVariantTypes::File */ ,
pivDir /** PIVariantTypes::Dir */ ,
pivColor /** PIVariantTypes::Color */ ,
pivPoint /** PIPoint<double> */ ,
pivRect /** PIRect<double> */ ,
pivIODevice /** PIVariantTypes::IODevice */ ,
pivMathVector /** PIMathVector<double> */ ,
pivMathMatrix /** PIMathMatrix<double> */ ,
pivLine /** PILine<double> */ ,
pivCustom /** Custom */ = 0xFF
pivLine /** PILine<double> */ ,
pivCustom /** \~english Custom \~russian Свой тип */ = 0xFF
};
//! Construct \a pivInvalid %PIVariant
//! \~english Construct \a pivInvalid %PIVariant
//! \~russian Создает \a pivInvalid %PIVariant
PIVariant();
//! \~english Contructs a copy of %PIVariant.
//! \~russian Создает копию %PIVariant.
PIVariant(const PIVariant & v);
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
PIVariant(PIVariant && v);
//! Constructs %PIVariant from string
//! \~english Constructs %PIVariant from string
//! \~russian Создает %PIVariant из строки.
PIVariant(const char * v) {initType(PIString(v));}
//! Constructs %PIVariant from boolean
//! \~english Constructs %PIVariant from boolean
//! \~russian Создает %PIVariant из логического значения.
PIVariant(const bool v) {initType(v);}
//! Constructs %PIVariant from char
//! \~english Constructs %PIVariant from char
//! \~russian Создает %PIVariant из символа.
PIVariant(const char v) {initType(v);}
//! Constructs %PIVariant from integer
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const uchar v) {initType(v);}
//! Constructs %PIVariant from integer
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const short v) {initType(v);}
//! Constructs %PIVariant from integer
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const ushort v) {initType(v);}
//! Constructs %PIVariant from integer
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const int & v) {initType(v);}
//! Constructs %PIVariant from integer
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const uint & v) {initType(v);}
//! Constructs %PIVariant from integer
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const llong & v) {initType(v);}
//! Constructs %PIVariant from integer
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const ullong & v) {initType(v);}
//! Constructs %PIVariant from float
//! \~english Constructs %PIVariant from float
//! \~russian Создает %PIVariant из вещественного числа.
PIVariant(const float & v) {initType(v);}
//! Constructs %PIVariant from double
//! \~english Constructs %PIVariant from double
//! \~russian Создает %PIVariant из вещественного числа.
PIVariant(const double & v) {initType(v);}
//! Constructs %PIVariant from long double
//! \~english Constructs %PIVariant from long double
//! \~russian Создает %PIVariant из вещественного числа.
PIVariant(const ldouble & v) {initType(v);}
//! Constructs %PIVariant from bit array
//! \~english Constructs %PIVariant from bit array
//! \~russian Создает %PIVariant из массива битов.
PIVariant(const PIBitArray & v) {initType(v);}
//! Constructs %PIVariant from byte array
//! \~english Constructs %PIVariant from byte array
//! \~russian Создает %PIVariant из массива байтов.
PIVariant(const PIByteArray & v) {initType(v);}
//! Constructs %PIVariant from string
//! \~english Constructs %PIVariant from string
//! \~russian Создает %PIVariant из строки.
PIVariant(const PIString & v) {initType(v);}
//! Constructs %PIVariant from strings list
//! \~english Constructs %PIVariant from strings list
//! \~russian Создает %PIVariant из массива строк.
PIVariant(const PIStringList & v) {initType(v);}
//! Constructs %PIVariant from time
//! \~english Constructs %PIVariant from time
//! \~russian Создает %PIVariant из времени.
PIVariant(const PITime & v) {initType(v);}
//! Constructs %PIVariant from date
//! \~english Constructs %PIVariant from date
//! \~russian Создает %PIVariant из даты.
PIVariant(const PIDate & v) {initType(v);}
//! Constructs %PIVariant from date and time
//! \~english Constructs %PIVariant from date and time
//! \~russian Создает %PIVariant из даты и времени.
PIVariant(const PIDateTime & v) {initType(v);}
//! Constructs %PIVariant from system time
//! \~english Constructs %PIVariant from system time
//! \~russian Создает %PIVariant из системного времени.
PIVariant(const PISystemTime & v) {initType(v);}
//! Constructs %PIVariant from enum
//! \~english Constructs %PIVariant from enum
//! \~russian Создает %PIVariant из перечисления.
PIVariant(const PIVariantTypes::Enum & v) {initType(v);}
//! Constructs %PIVariant from file
//! \~english Constructs %PIVariant from file
//! \~russian Создает %PIVariant из файла.
PIVariant(const PIVariantTypes::File & v) {initType(v);}
//! Constructs %PIVariant from dir
//! \~english Constructs %PIVariant from dir
//! \~russian Создает %PIVariant из директории.
PIVariant(const PIVariantTypes::Dir & v) {initType(v);}
//! Constructs %PIVariant from color
//! \~english Constructs %PIVariant from color
//! \~russian Создает %PIVariant из цвета.
PIVariant(const PIVariantTypes::Color & v) {initType(v);}
//! Constructs %PIVariant from IODevice
//! \~english Constructs %PIVariant from IODevice
//! \~russian Создает %PIVariant из IODevice.
PIVariant(const PIVariantTypes::IODevice & v) {initType(v);}
//! Constructs %PIVariant from point
//! \~english Constructs %PIVariant from point
//! \~russian Создает %PIVariant из точки.
PIVariant(const PIPointd & v) {initType(v);}
//! Constructs %PIVariant from rect
//! \~english Constructs %PIVariant from rect
//! \~russian Создает %PIVariant из прямоугольника.
PIVariant(const PIRectd & v) {initType(v);}
//! Constructs %PIVariant from line
//! \~english Constructs %PIVariant from line
//! \~russian Создает %PIVariant из линии.
PIVariant(const PILined & v) {initType(v);}
//! Constructs %PIVariant from MathVector
//! \~english Constructs %PIVariant from MathVector
//! \~russian Создает %PIVariant из MathVector.
PIVariant(const PIMathVectord & v) {initType(v);}
//! Constructs %PIVariant from MathMatrix
//! \~english Constructs %PIVariant from MathMatrix
//! \~russian Создает %PIVariant из MathMatrix.
PIVariant(const PIMathMatrixd & v) {initType(v);}
//! Set variant content and type to string
//! \~english Set variant content and type to string
//! \~russian Устанавливает значение и тип из строки
void setValue(const char * v) {setValue(PIString(v));}
//! Set variant content and type to boolean
//! \~english Set variant content and type to boolean
//! \~russian Устанавливает значение и тип из
void setValue(const bool v) {initType(v);}
//! Set variant content and type to char
//! \~english Set variant content and type to char
//! \~russian Устанавливает значение и тип из символа
void setValue(const char v) {initType(v);}
//! Set variant content and type to integer
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const uchar v) {initType(v);}
//! Set variant content and type to integer
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const short v) {initType(v);}
//! Set variant content and type to integer
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const ushort v) {initType(v);}
//! Set variant content and type to integer
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const int & v) {initType(v);}
//! Set variant content and type to integer
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const uint & v) {initType(v);}
//! Set variant content and type to integer
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const llong & v) {initType(v);}
//! Set variant content and type to integer
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const ullong & v) {initType(v);}
//! Set variant content and type to float
//! \~english Set variant content and type to float
//! \~russian Устанавливает значение и тип из вещественного числа
void setValue(const float & v) {initType(v);}
//! Set variant content and type to double
//! \~english Set variant content and type to double
//! \~russian Устанавливает значение и тип из вещественного числа
void setValue(const double & v) {initType(v);}
//! Set variant content and type to long double
//! \~english Set variant content and type to long double
//! \~russian Устанавливает значение и тип из вещественного числа
void setValue(const ldouble & v) {initType(v);}
//! Set variant content and type to bit array
//! \~english Set variant content and type to bit array
//! \~russian Устанавливает значение и тип из массива битов
void setValue(const PIBitArray & v) {initType(v);}
//! Set variant content and type to byte array
//! \~english Set variant content and type to byte array
//! \~russian Устанавливает значение и тип из массива байтов
void setValue(const PIByteArray & v) {initType(v);}
//! Set variant content and type to string
//! \~english Set variant content and type to string
//! \~russian Устанавливает значение и тип из строки
void setValue(const PIString & v) {initType(v);}
//! Set variant content and type to strings list
//! \~english Set variant content and type to strings list
//! \~russian Устанавливает значение и тип из массива строк
void setValue(const PIStringList & v) {initType(v);}
//! Set variant content and type to time
//! \~english Set variant content and type to time
//! \~russian Устанавливает значение и тип из времени
void setValue(const PITime & v) {initType(v);}
//! Set variant content and type to date
//! \~english Set variant content and type to date
//! \~russian Устанавливает значение и тип из даты
void setValue(const PIDate & v) {initType(v);}
//! Set variant content and type to date and time
//!
//! \~english Set variant content and type to date and time
//! \~russian Устанавливает значение и тип из даты и времени
void setValue(const PIDateTime & v) {initType(v);}
//! Set variant content and type to system time
//! \~english Set variant content and type to system time
//! \~russian Устанавливает значение и тип из системного времени
void setValue(const PISystemTime & v) {initType(v);}
//! Set variant content and type to enum
//! \~english Set variant content and type to enum
//! \~russian Устанавливает значение и тип из перечисления
void setValue(const PIVariantTypes::Enum & v) {initType(v);}
//! Set variant content and type to file
//! \~english Set variant content and type to file
//! \~russian Устанавливает значение и тип из файла
void setValue(const PIVariantTypes::File & v) {initType(v);}
//! Set variant content and type to dir
//! \~english Set variant content and type to dir
//! \~russian Устанавливает значение и тип из директории
void setValue(const PIVariantTypes::Dir & v) {initType(v);}
//! Set variant content and type to color
//! \~english Set variant content and type to color
//! \~russian Устанавливает значение и тип из цвета
void setValue(const PIVariantTypes::Color & v) {initType(v);}
//! Set variant content and type to IODevice
//! \~english Set variant content and type to IODevice
//! \~russian Устанавливает значение и тип из IODevice
void setValue(const PIVariantTypes::IODevice & v) {initType(v);}
//! Set variant content and type to point
//! \~english Set variant content and type to point
//! \~russian Устанавливает значение и тип из точки
void setValue(const PIPointd & v) {initType(v);}
//! Set variant content and type to rect
//! \~english Set variant content and type to rect
//! \~russian Устанавливает значение и тип из прямоугольника
void setValue(const PIRectd & v) {initType(v);}
//! Set variant content and type to line
//! \~english Set variant content and type to line
//! \~russian Устанавливает значение и тип из линии
void setValue(const PILined & v) {initType(v);}
//! Set variant content and type to math vector
//! \~english Set variant content and type to math vector
//! \~russian Устанавливает значение и тип из вектора
void setValue(const PIMathVectord & v) {initType(v);}
//! Set variant content and type to math matrix
//! \~english Set variant content and type to math matrix
//! \~russian Устанавливает значение и тип из матрицы
void setValue(const PIMathMatrixd & v) {initType(v);}
//! Set current value from string without change type
//! \~english Set current value from string without change type
//! \~russian Устанавливает текущее значение из строки без изменения типа
void setValueFromString(const PIString & v);
@@ -473,102 +560,189 @@ public:
PIMathMatrixd toMathMatrix() const;
/** \brief Returns variant content as custom type
* \details In case of known types this function equivalent \a to<Type> function. \n
* Otherwise returns content as type T. */
//! \~\brief
//! \~english Returns variant content as custom type
//! \~russian Возвращает содержимое в качестве своего типа
//! \~\details
//! \~english
//! In case of known types this function equivalent \a to<Type> function. \n
//! Otherwise returns content as type T only if this type was set earlier.
//! \~russian
//! Для стандартных типов эквиваленстно методу \a to<Type>. \n
//! Для других возвращает тип T только если он был установлен ранее.
template<typename T>
T value() const {return getAsValue<T>(*this);}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariant & v);
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(PIVariant && v);
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const char * v) {setValue(PIString(v)); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const bool v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const char v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const uchar v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const short v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const ushort v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const int & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const uint & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const llong & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const ullong & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const float & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const double & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const ldouble & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIBitArray & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIByteArray & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIString & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIStringList & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PITime & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIDate & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIDateTime & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PISystemTime & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::Enum & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::File & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::Dir & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::Color & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::IODevice & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIPointd & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIRectd & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PILined & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIMathVectord & v) {setValue(v); return *this;}
//! Assign operator
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIMathMatrixd & v) {setValue(v); return *this;}
//! Compare operator
//! \~english Compare operator. Check type and content.
//! \~russian Оператор сравнения. Сравнивает тип и содержимое.
bool operator ==(const PIVariant & v) const;
//! Compare operator
//! \~english Compare operator. Check type and content.
//! \~russian Оператор сравнения. Сравнивает тип и содержимое.
bool operator !=(const PIVariant & v) const {return !(*this == v);}
//! Returns type of variant content
//! \~english Returns type of variant content.
//! \~russian Возвращает тип значения.
PIVariant::Type type() const {return _type;}
//! Returns type name of variant content
//! \~english Returns type name of variant content.
//! \~russian Возвращает имя типа значения.
PIString typeName() const;
//! Returns \b true if type is not Invalid
//! \~english Returns if type is not \a pivInvalid.
//! \~russian Возвращает не является ли тип \a pivInvalid.
bool isValid() const {return _type != PIVariant::pivInvalid;}
//! \~english Swaps with other %PIVariant.
//! \~russian Меняет с другим %PIVariant.
void swap(PIVariant & v);
/** \brief Returns new variant from custom type
* \details In case of known types this function equivalent \a PIVariant(T) constructors. \n
* Otherwise returns variant with content \a v and type Custom. */
//! \~\brief
//! \~english Returns new %PIVariant from custom type value.
//! \~russian Возвращает новый %PIVariant из значения своего типа.
//! \~\details
//! \~english
//! In case of known types this function equivalent \a PIVariant() constructors. \n
//! Otherwise returns variant with content "v" and type \a pivCustom.
//! \~russian
//! Для стандартных типов эквиваленстно конструктору \a PIVariant(). \n
//! Для других устанавливает содержимое из "v" и тип \a pivCustom.
template <typename T>
static PIVariant fromValue(const T & v) {
PIVariant ret;
@@ -597,10 +771,12 @@ public:
}
//! Returns type from name
//! \~english Returns type from its name.
//! \~russian Возвращает тип из его названия.
static PIVariant::Type typeFromName(const PIString & tname);
//! Returns type name
//! \~english Returns type name.
//! \~russian Возвращает имя типа.
static PIString typeName(PIVariant::Type type);
private:
@@ -773,8 +949,12 @@ REGISTER_VARIANT(PILined)
REGISTER_VARIANT(PIMathVectord)
REGISTER_VARIANT(PIMathMatrixd)
inline PIByteArray & operator <<(PIByteArray & s, const PIVariant & v) {
s << v._content << int(v._type);
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariant) {
s << v._content << v._type;
if (v._type == PIVariant::pivCustom) {
#ifdef CUSTOM_PIVARIANT
if (v._info) {
@@ -788,10 +968,12 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVariant & v) {
}
return s;
}
inline PIByteArray & operator >>(PIByteArray & s, PIVariant & v) {
int t(0);
s >> v._content >> t;
v._type = (PIVariant::Type)t;
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIVariant) {
s >> v._content >> v._type;
if (v._type == PIVariant::pivCustom) {
PIString tn;
s >> tn;
@@ -803,13 +985,16 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVariant & v) {
return s;
}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariant & v) {
s.space(); s.setControl(0, true);
s.space(); s.saveAndSetControls(0);
s << "PIVariant(" << v.typeName();
if (v.isValid())
s << ", " << v.toString();
s << ")";
s.restoreControl(); return s;
s.restoreControls(); return s;
}

View File

@@ -1,7 +1,7 @@
/*! \file pivariantsimple.h
* \ingroup Core
* \brief
* \~english Variant simple type
* \~english Simple variant type
* \~russian Простой вариативный тип
*/
/*
@@ -62,9 +62,28 @@ public:
};
//! \addtogroup Core
//! \{
//! \~\class PIVariantSimple pivariantsimple.h
//! \~\brief
//! \~english Simple variant type.
//! \~russian Простой вариативный тип.
//!
//! \~\details
//! \~english
//!
//! \~russian
//!
//! \}
class PIVariantSimple {
public:
//! \~english Construct null %PIVariantSimple
//! \~russian Создает пустой %PIVariantSimple
PIVariantSimple() {ptr = 0; f = 0;}
//! \~english Contructs a copy of %PIVariantSimple.
//! \~russian Создает копию %PIVariantSimple.
PIVariantSimple(const PIVariantSimple & v) {
ptr = 0;
f = v.f;
@@ -73,6 +92,8 @@ public:
}
~PIVariantSimple() {destroy();}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariantSimple & operator=(const PIVariantSimple & v) {
destroy();
f = v.f;
@@ -81,6 +102,8 @@ public:
return *this;
}
//! \~english Set value to "v".
//! \~russian Устанавливает значение в "v".
template <typename T>
void setValue(const T & v) {
if (f) {
@@ -94,6 +117,18 @@ public:
f->newT(ptr, (const void *)&v);
}
//! \~\brief
//! \~english Returns value as type "T".
//! \~russian Возвращает значение как тип "T".
//! \~\details
//! \~english
//! In contrast of PIVariant this class has strong check of type.
//! Returns value only if this type was set before.
//!
//! \~russian
//! В отличии от PIVariant этот класс строго проверяет типы.
//! Возвращает значение только если этот же тип был установлен ранее.
//!
template <typename T>
T value() const {
if (!f) return T();
@@ -102,6 +137,8 @@ public:
return *(T*)(ptr);
}
//! \~english Returns %PIVariantSimple with value "v".
//! \~russian Возвращает %PIVariantSimple со значением "v".
template <typename T>
static PIVariantSimple fromValue(const T & v) {
PIVariantSimple ret;

View File

@@ -23,8 +23,9 @@
# include "piiodevice.h"
#endif
int PIVariantTypes::Enum::selectedValue() const {
piForeachC (Enumerator & e, enum_list)
for (const auto & e: enum_list)
if (e.name == selected)
return e.value;
return 0;
@@ -32,7 +33,7 @@ int PIVariantTypes::Enum::selectedValue() const {
bool PIVariantTypes::Enum::selectValue(int v) {
piForeachC (Enumerator & e, enum_list)
for (const auto & e: enum_list)
if (e.value == v) {
selected = e.name;
return true;
@@ -42,7 +43,7 @@ bool PIVariantTypes::Enum::selectValue(int v) {
bool PIVariantTypes::Enum::selectName(const PIString & n) {
piForeachC (Enumerator & e, enum_list)
for (const auto & e: enum_list)
if (e.name == n) {
selected = e.name;
return true;
@@ -52,7 +53,7 @@ bool PIVariantTypes::Enum::selectName(const PIString & n) {
int PIVariantTypes::Enum::value(const PIString & n) const {
piForeachC (Enumerator & e, enum_list)
for (const auto & e: enum_list)
if (e.name == n)
return e.value;
return 0;
@@ -60,7 +61,7 @@ int PIVariantTypes::Enum::value(const PIString & n) const {
PIString PIVariantTypes::Enum::name(int v) const {
piForeachC (Enumerator & e, enum_list)
for (const auto & e: enum_list)
if (e.value == v)
return e.name;
return PIString();
@@ -69,7 +70,7 @@ PIString PIVariantTypes::Enum::name(int v) const {
PIVector<int> PIVariantTypes::Enum::values() const {
PIVector<int> ret;
piForeachC (Enumerator & e, enum_list)
for (const auto & e: enum_list)
ret << e.value;
return ret;
}
@@ -77,7 +78,7 @@ PIVector<int> PIVariantTypes::Enum::values() const {
PIStringList PIVariantTypes::Enum::names() const {
PIStringList ret;
piForeachC (Enumerator & e, enum_list)
for (const auto & e: enum_list)
ret << e.name;
return ret;
}
@@ -110,25 +111,25 @@ PIPropertyStorage PIVariantTypes::IODevice::get() const {
PIString PIVariantTypes::IODevice::toPICout() const {
PIString s;
s << "IODevice(" << prefix << ", mode=";
s += "IODevice(" + prefix + ", mode=";
int rwc = 0;
if (mode & 1) {s << "r"; ++rwc;}
if (mode & 2) {s << "w"; ++rwc;}
if (rwc == 1) s << "o";
s << ", flags=";
if (mode & 1) {s += "r"; ++rwc;}
if (mode & 2) {s += "w"; ++rwc;}
if (rwc == 1) s += "o";
s += ", flags=";
#ifndef MICRO_PIP // TODO: PIIODevice for MICRO PIP
if (options != 0) {
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingRead])
s << " br";
s += " br";
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite])
s << " bw";
s += " bw";
}
#endif // MICRO_PIP
PIPropertyStorage ps = get();
piForeachC (PIPropertyStorage::Property & p, ps) {
s << ", " << p.name << "=\"" << p.value.toString() << "\"";
s += ", " + p.name + "=\"" + p.value.toString() + "\"";
}
s << ")";
s += ")";
return s;
}
@@ -144,14 +145,14 @@ PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIString & v) {
if (enum_list.isEmpty()) {
enum_list << Enumerator(0, v);
} else {
enum_list << Enumerator(enum_list.back().value+1, v);
enum_list << Enumerator(enum_list.back().value + 1, v);
}
return *this;
}
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIStringList & v) {
piForeachC (PIString & s, v)
for (const auto & s: v)
(*this) << s;
return *this;
}

View File

@@ -32,160 +32,348 @@
class PIPropertyStorage;
//! \ingroup Core
//! \relatesalso PIVariant
//! \~english Namespace contains several types for PIVariant
//! \~russian Пространство имен содержит некоторые типы для PIVariant
namespace PIVariantTypes {
/**
* \brief name-value pair
*/
//! \addtogroup Core
//! \{
//! \~\struct Enumerator pivarianttypes.h
//! \~\brief
//! \~english Name-value pair.
//! \~russian Пара имя-значение.
//! \}
struct PIP_EXPORT Enumerator {
Enumerator(int v = 0, const PIString & n = PIString()): value(v), name(n) {}
//! \~english Value.
//! \~russian Значение.
int value;
//! \~english Name.
//! \~russian Имя.
PIString name;
};
/**
* \brief Collection of PIVariantTypes::Enumerator. It's replace classic c-style enum.
* Contains elements with unique name and not uniqueue values.
*/
//! \addtogroup Core
//! \{
//! \~\struct Enum pivarianttypes.h
//! \~\brief
//! \~english Collection of PIVariantTypes::Enumerator.
//! \~russian Набор PIVariantTypes::Enumerator.
//! \~\details
//! \~english
//! This class represents classic c-style enum.
//! Contains elements with unique names and not uniqueue values, also
//! name of enum and selected member.
//!
//! \~russian
//! Этот класс представляет классический c-style enum.
//! Содержит элементы с уникальными именами и неуникальными значениями,
//! а также имя перечисления и выбранного элемента.
//!
//! \}
struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()): enum_name(n) {}
/**
* \brief Find selected value.
* @return selected value, otherwrise 0
*/
//! \~english Returns selected value, or 0 if there is no name in members.
//! \~russian Возвращает выбранное значение, или 0, если выбранного имени нет в элементах.
int selectedValue() const;
/**
* \brief Get selected name
* @return selected name, otherwrise empty PIString
*/
//! \~english Returns selected name.
//! \~russian Возвращает выбранное имя.
PIString selectedName() const {return selected;}
/**
* \brief Select value if exists in Enum. If Enum contains several PIVariantTypes::Enumerator with same values,
* first PIVariantTypes::Enumerator will selected
* @param v value for selection
* @return true if value exists in Enum, false otherwrise
*/
//! \~\brief
//! \~english Select value if exists in Enum.
//! \~russian Выбирает значение, если оно существует в Enum.
//!
//! \~\details
//! \~english
//! If Enum contains several PIVariantTypes::Enumerator with same values,
//! first PIVariantTypes::Enumerator will selected.
//! Returns if value exists in Enum.
//!
//! \~russian
//! Если Enum содержит несколько PIVariantTypes::Enumerator с этим значением,
//! то будет выбран первый.
//! Возвращает существовал ли такой Enum.
//!
bool selectValue(int v);
/**
* \brief Select name if exists in enum
* @param n name for selection
* @return true if name exists in Enum, false otherwrise
*/
//! \~\brief
//! \~english Select name if exists in Enum.
//! \~russian Выбирает имя, если оно существует в Enum.
//!
//! \~\details
//! \~english
//! Returns if name exists in Enum.
//!
//! \~russian
//! Возвращает существовал ли такой Enum.
//!
bool selectName(const PIString & n);
/**
* \brief Find PIVariantTypes::Enumerator with specific name and return it value
* @param n name for search
* @return value of founded PIVariantTypes::Enumerator, 0 otherwrise
*/
//! \~english Find PIVariantTypes::Enumerator with name "n" and return it value, otherwise 0.
//! \~russian Ищет PIVariantTypes::Enumerator с именем "n" и возвращает его значение, иначе 0.
int value(const PIString & n) const;
/**
* \brief Find first PIVariantTypes::Enumerator with specific value and return it name
* @param v value for search
* @return name of founded PIVariantTypes::Enumerator, empty string otherwrise
*/
//! \~english Find PIVariantTypes::Enumerator with value "v" and return it name, otherwise empty string.
//! \~russian Ищет PIVariantTypes::Enumerator со значением "v" и возвращает его имя, иначе пустую строку.
PIString name(int v) const;
/**
* \brief Make vector of Enum values
*/
//! \~english Returns all members values.
//! \~russian Возвращает все значения членов.
PIVector<int> values() const;
/**
* \brief Make vector of Enum names
*/
//! \~english Returns all members names.
//! \~russian Возвращает все имена членов.
PIStringList names() const;
/**
* \brief Add PIVariantTypes::Enumerator to Enum
*/
//! \~english Add PIVariantTypes::Enumerator to Enum.
//! \~russian Добавляет в Enum PIVariantTypes::Enumerator.
Enum & operator <<(const Enumerator & v);
/**
* \brief Add PIVariantTypes::Enumerator element to Enum. Element contains specific name and value more per
* unit then last element. If the is no elements, contains zero value.
* @param v name for new PIVariantTypes::Enumerator element
*/
//! \~english Add PIVariantTypes::Enumerator with name "v" and value of last element + 1, otherwise 0.
//! \~russian Добавляет PIVariantTypes::Enumerator с именем "v" и значением последнего элемента + 1, иначе 0.
Enum & operator <<(const PIString & v);
/**
* \brief Add PIVariantTypes::Enumerator element for each name in vector
*/
//! \~english Add PIVariantTypes::Enumerator element for each name of vector.
//! \~russian Добавляет PIVariantTypes::Enumerator для каждой строки из массива.
Enum & operator <<(const PIStringList & v);
/**
* \brief Return true if Enum is empty
*/
//! \~english Returns if Enum is empty.
//! \~russian Возвращает пустой ли Enum.
bool isEmpty() const {return enum_list.isEmpty();}
//! \~english Name of Enum.
//! \~russian Имя Enum.
PIString enum_name;
//! \~english Name of selected element.
//! \~russian Имя выбранного элемента.
PIString selected;
//! \~english Members.
//! \~russian Элементы.
PIVector<Enumerator> enum_list;
};
//! \addtogroup Core
//! \{
//! \~\struct File pivarianttypes.h
//! \~\brief
//! \~english File location description.
//! \~russian Описание положения файла.
//! \}
struct PIP_EXPORT File {
File(const PIString & p = PIString(), const PIString & f = PIString(), bool abs = false, bool save_mode = false):
file(p), filter(f), is_abs(abs), is_save(save_mode) {}
//! \~english Returns path.
//! \~russian Возвращает путь.
PIString toString() const {return file;}
//! \~english Path.
//! \~russian Путь.
PIString file;
//! \~english Name filter.
//! \~russian Фильтр имени.
PIString filter;
//! \~english If path is absolute.
//! \~russian Абсолютный ли путь.
bool is_abs;
//! \~english If save is available.
//! \~russian Доступно ли сохранение.
bool is_save;
};
//! \addtogroup Core
//! \{
//! \~\struct Dir pivarianttypes.h
//! \~\brief
//! \~english Directory description.
//! \~russian Описание директории.
//! \}
struct PIP_EXPORT Dir {
Dir(const PIString & d = PIString(), bool abs = false):
dir(d), is_abs(abs) {}
//! \~english Returns path.
//! \~russian Возвращает путь.
PIString toString() const {return dir;}
//! \~english Path.
//! \~russian Путь.
PIString dir;
//! \~english If path is absolute.
//! \~russian Абсолютный ли путь.
bool is_abs;
};
//! \addtogroup Core
//! \{
//! \~\struct Color pivarianttypes.h
//! \~\brief
//! \~english 32-bits color.
//! \~russian 32-битный цвет.
//! \}
struct PIP_EXPORT Color {
Color(uint v = 0) {rgba = v;}
//! \~english Integer color.
//! \~russian Целочисленный цвет.
uint rgba;
};
//! \addtogroup Core
//! \{
//! \~\struct IODevice pivarianttypes.h
//! \~\brief
//! \~english Input/output device description.
//! \~russian Описание устройства ввода/вывода.
//! \}
struct PIP_EXPORT IODevice {
IODevice();
//! \~english Serialize "ps" and set it to "props".
//! \~russian Сериализует "ps" и устанавливает "props".
void set(const PIPropertyStorage & ps);
//! \~english Deserialize "props" and returns it.
//! \~russian Десериализует "props" и возвращает свойства.
PIPropertyStorage get() const;
//! \~english Returns string for PICout.
//! \~russian Возвращает строку для PICout.
PIString toPICout() const;
//! \~english PIIODevice prefix, see \ref PIIODevice_sec7.
//! \~russian Префикс PIIODevice, см. \ref PIIODevice_sec7.
PIString prefix;
int mode; // PIIODevice::DeviceMode
int options; // PIIODevice::DeviceOptions
//! PIIODevice::DeviceMode.
int mode;
//! PIIODevice::DeviceOptions.
int options;
//! \~english Serialized properties.
//! \~russian Сериализованные свойства.
PIByteArray props;
};
}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Enumerator & v) {s << v.value << v.name; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Enumerator & v) {s >> v.value >> v.name; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Enumerator & v) {s << v.name << "(" << v.value << ")"; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Enum & v) {s << v.enum_name << v.selected << v.enum_list; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Enum & v) {s >> v.enum_name >> v.selected >> v.enum_list; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Enum & v) {s << "Enum(" << v.selectedValue() << "=" << v.selectedName() << ")"; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::File & v) {s << v.file << v.filter << uchar((v.is_abs ? 1 : 0) + (v.is_save ? 2 : 0)); return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::File & v) {uchar f(0); s >> v.file >> v.filter >> f; v.is_abs = ((f & 1) == 1); v.is_save = ((f & 2) == 2); return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::File & v) {s << "File(\"" << v.file << "\")"; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Dir & v) {s << v.dir << v.is_abs; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Dir & v) {s >> v.dir >> v.is_abs; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Dir & v) {s << "Dir(\"" << v.dir << "\")"; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Color & v) {s << v.rgba; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Color & v) {s >> v.rgba; return s;}
inline PICout operator <<(PICout s, const PIVariantTypes::Color & v) {s.saveControl(); s << PICoutManipulators::Hex << "Color(#" << v.rgba << ")"; s.restoreControl(); return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Color & v) {s.saveControls(); s << PICoutManipulators::Hex << "Color(#" << v.rgba << ")"; s.restoreControls(); return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::IODevice & v) {s << v.prefix << v.mode << v.options << v.props; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::IODevice & v) {s >> v.prefix >> v.mode >> v.options >> v.props; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::IODevice & v) {s << v.toPICout(); return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Enumerator) {s << v.value << v.name; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Enumerator) {s >> v.value >> v.name; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Enum) {s << v.enum_name << v.selected << v.enum_list; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Enum) {s >> v.enum_name >> v.selected >> v.enum_list; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::File) {s << v.file << v.filter << uchar((v.is_abs ? 1 : 0) + (v.is_save ? 2 : 0)); return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::File) {uchar f(0); s >> v.file >> v.filter >> f; v.is_abs = ((f & 1) == 1); v.is_save = ((f & 2) == 2); return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Dir) {s << v.dir << v.is_abs; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Dir) {s >> v.dir >> v.is_abs; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Color) {s << v.rgba; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Color) {s >> v.rgba; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::IODevice) {s << v.prefix << v.mode << v.options << v.props; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::IODevice) {s >> v.prefix >> v.mode >> v.options >> v.props; return s;}
#endif // PIVARIANTYPES_H

View File

@@ -76,19 +76,19 @@ public:
//! Disconneted event
EVENT1(disconnected, PIString, reason)
EVENT1(disconnected, PIString, reason);
//! Conneted event
EVENT1(connected, PIString, info)
EVENT1(connected, PIString, info);
//! Client event for authorize new server
EVENT2(authorize, PIByteArray, info, bool *, ok)
EVENT2(authorize, PIByteArray, info, bool *, ok);
//! Client event for input server password
EVENT1(passwordRequest, PIString *, pass)
EVENT1(passwordRequest, PIString *, pass);
//! Server event on check client password
EVENT1(passwordCheck, bool, result)
EVENT1(passwordCheck, bool, result);
private:
enum Role {Client, Server};

View File

@@ -96,15 +96,3 @@ PIVector<PIIntrospectionContainers::TypeInfo> PIIntrospectionContainers::getInfo
}
return ret;
}
PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v) {
s << PIByteArray::RawData(&v, sizeof(PIIntrospectionContainers::_Type)) << v.name;
return s;
}
PIByteArray & operator >>(PIByteArray & s, PIIntrospectionContainers::TypeInfo & v) {
s >> PIByteArray::RawData(&v, sizeof(PIIntrospectionContainers::_Type)) >> v.name;
return s;
}

View File

@@ -65,7 +65,14 @@ public:
mutable PISpinlock mutex;
};
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIIntrospectionContainers::TypeInfo & v);
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIIntrospectionContainers::TypeInfo & v);
BINARY_STREAM_WRITE(PIIntrospectionContainers::TypeInfo) {
s << PIMemoryBlock(&v, sizeof(PIIntrospectionContainers::_Type)) << v.name;
return s;
}
BINARY_STREAM_READ(PIIntrospectionContainers::TypeInfo) {
s >> PIMemoryBlock(&v, sizeof(PIIntrospectionContainers::_Type)) >> v.name;
return s;
}
#endif // PIINTROSPECTION_CONTAINERS_P_H

View File

@@ -56,7 +56,7 @@ void PIIntrospectionServer::start(const PIString & server_name) {
sysmon = PISystemMonitor::Pool::instance()->getByPID(PIProcess::currentPID());
if (sysmon) {
piCoutObj << "using existing sysmon";
CONNECTU(sysmon, deleted, this, sysmonDeleted);
CONNECT1(void, PIObject *, sysmon, deleted, this, sysmonDeleted);
} else {
piCoutObj << "create own sysmon";
sysmon = new PISystemMonitor();

View File

@@ -46,7 +46,7 @@ class PISystemMonitor;
# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer)
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer);
public:
static PIIntrospectionServer * instance();
@@ -55,7 +55,7 @@ public:
private:
PIIntrospectionServer();
~PIIntrospectionServer();
NO_COPY_CLASS(PIIntrospectionServer)
NO_COPY_CLASS(PIIntrospectionServer);
PIString genName();
virtual void dataReceived(const PIString & from, const PIByteArray & data);

View File

@@ -77,82 +77,6 @@ PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() {
}
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v) {
PIChunkStream cs;
cs.add(1, v.types);
b << cs.data();
return b;
}
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v) {
PIByteArray csba; b >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(v.types); break;
default: break;
}
}
return b;
}
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v) {
PIChunkStream cs;
cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name)
.add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options);
b << cs.data();
return b;
}
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v) {
PIByteArray csba; b >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(v.architecture); break;
case 2: cs.get(v.execCommand); break;
case 3: cs.get(v.execDateTime); break;
case 4: cs.get(v.hostname); break;
case 5: cs.get(v.OS_name); break;
case 6: cs.get(v.OS_version); break;
case 7: cs.get(v.processorsCount); break;
case 8: cs.get(v.user); break;
case 9: cs.get(v.build_options); break;
default: break;
}
}
return b;
}
PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v) {
PIChunkStream cs;
cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events);
b << cs.data();
return b;
}
PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v) {
PIByteArray csba; b >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(v.classname); break;
case 2: cs.get(v.name); break;
case 3: cs.get(v.parents); break;
case 4: cs.get(v.properties); break;
case 5: cs.get(v.queued_events); break;
default: break;
}
}
return b;
}
PIByteArray PIIntrospection::packInfo() {
@@ -216,8 +140,8 @@ PIByteArray PIIntrospection::packThreads() {
PIMap<PIThread*, PIIntrospectionThreads::ThreadInfo> & tm(p->threads);
auto it = tm.makeIterator();
while (it.next()) {
it.valueRef().classname = PIStringAscii(it.key()->className());
it.valueRef().name = it.key()->name();
it.value().classname = PIStringAscii(it.key()->className());
it.value().name = it.key()->name();
}
ret << tm.values();
p->mutex.unlock();

View File

@@ -24,6 +24,7 @@
#include "piintrospection_containers_p.h"
#include "piintrospection_threads.h"
#include "piintrospection_threads_p.h"
#include "pichunkstream.h"
#include "pisystemmonitor.h"
@@ -91,13 +92,72 @@ public:
};
PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::RequiredInfo & v);
PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::RequiredInfo & v);
PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ProcessInfo & v);
PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ProcessInfo & v);
BINARY_STREAM_WRITE(PIIntrospection::RequiredInfo) {
PIChunkStream cs;
cs.add(1, v.types);
s << cs.data();
return s;
}
BINARY_STREAM_READ(PIIntrospection::RequiredInfo) {
PIByteArray csba; s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(v.types); break;
default: break;
}
}
return s;
}
PIP_EXPORT PIByteArray & operator <<(PIByteArray & b, const PIIntrospection::ObjectInfo & v);
PIP_EXPORT PIByteArray & operator >>(PIByteArray & b, PIIntrospection::ObjectInfo & v);
BINARY_STREAM_WRITE(PIIntrospection::ProcessInfo) {
PIChunkStream cs;
cs.add(1, v.architecture).add(2, v.execCommand).add(3, v.execDateTime).add(4, v.hostname).add(5, v.OS_name)
.add(6, v.OS_version).add(7, v.processorsCount).add(8, v.user).add(9, v.build_options);
s << cs.data();
return s;
}
BINARY_STREAM_READ(PIIntrospection::ProcessInfo) {
PIByteArray csba; s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(v.architecture); break;
case 2: cs.get(v.execCommand); break;
case 3: cs.get(v.execDateTime); break;
case 4: cs.get(v.hostname); break;
case 5: cs.get(v.OS_name); break;
case 6: cs.get(v.OS_version); break;
case 7: cs.get(v.processorsCount); break;
case 8: cs.get(v.user); break;
case 9: cs.get(v.build_options); break;
default: break;
}
}
return s;
}
BINARY_STREAM_WRITE(PIIntrospection::ObjectInfo) {
PIChunkStream cs;
cs.add(1, v.classname).add(2, v.name).add(3, v.parents).add(4, v.properties).add(5, v.queued_events);
s << cs.data();
return s;
}
BINARY_STREAM_READ(PIIntrospection::ObjectInfo) {
PIByteArray csba; s >> csba;
PIChunkStream cs(csba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(v.classname); break;
case 2: cs.get(v.name); break;
case 3: cs.get(v.parents); break;
case 4: cs.get(v.properties); break;
case 5: cs.get(v.queued_events); break;
default: break;
}
}
return s;
}
#endif // PIINTROSPECTION_SERVER_P_H

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