Compare commits
125 Commits
zmq
...
e96b399da7
| Author | SHA1 | Date | |
|---|---|---|---|
| e96b399da7 | |||
| 33eefd7453 | |||
| 831f202536 | |||
| 81b749caa2 | |||
| a50953ae7c | |||
| 08c5d15e6a | |||
| ff70bf6a0e | |||
| a315f7af25 | |||
|
|
4c7df57e66 | ||
|
|
7dee8f6313 | ||
|
|
0ad6ca6602 | ||
|
|
649850a1ba | ||
|
|
8bb1af8d2a | ||
| 7a0adf5e28 | |||
|
|
6241795b60 | ||
|
|
9d0451455a | ||
|
|
9a8b9c7141 | ||
| 866f71edb5 | |||
|
|
4bae04feec | ||
|
|
415160387b | ||
|
|
3dd0d0b6cf | ||
|
|
2596b119ac | ||
| 20e0771331 | |||
| 7a26ae7292 | |||
| cc4e1f48aa | |||
|
|
6e6305d2ec | ||
|
|
3e9cb2481c | ||
|
|
ea624f1223 | ||
|
|
e4aec3f95e | ||
| 7d83c6fe19 | |||
| 7ef4321a3d | |||
| 54b5372356 | |||
|
|
9bf1a11701 | ||
|
|
99280a40ef | ||
|
|
99061f6e24 | ||
|
|
2fd139b1e3 | ||
| ae29b4514c | |||
| 58de1ceafc | |||
| 20e6d1be99 | |||
| 2a877fbb6b | |||
| 2a6ebc9d8d | |||
|
|
c3c98b9d78 | ||
|
|
443e8b46a6 | ||
|
|
fff2aa468a | ||
| 1918e55a97 | |||
| eb6d378de2 | |||
| b1b174ba64 | |||
|
|
4921a3b0fd | ||
|
|
8296e9a32b | ||
|
|
7403ee67be | ||
|
|
cde2341c1f | ||
|
|
542f180d9d | ||
| 86130d7105 | |||
|
|
c9e329d27d | ||
|
|
d4c6c410da | ||
|
|
a7df53fbfe | ||
|
|
0504fa187e | ||
| 1d9a39f792 | |||
| cbdaabee4a | |||
| 3c8ccf357b | |||
|
|
92b20f6f46 | ||
| 04d7ed77d9 | |||
| a2a205cfd2 | |||
| d3b6597042 | |||
|
|
48c885e12a | ||
|
|
6e5a5a6ade | ||
| 21e03fc8cb | |||
| b85de0d704 | |||
|
|
f781cc3846 | ||
|
|
1cb3d4ffe9 | ||
|
|
9293706634 | ||
|
|
fde6bdf17f | ||
|
|
a1c1fd8339 | ||
|
|
01b39dc75f | ||
| 07ec32c969 | |||
| 042366e19e | |||
| 948a90fcd9 | |||
| c404688bbd | |||
| aa76a15f40 | |||
|
|
ca20785b53 | ||
|
|
13d0b2f960 | ||
|
|
46571ac39f | ||
| 36d770ea2e | |||
|
|
bc7d129a9e | ||
| 8accc28804 | |||
|
|
62e130f91b | ||
| a009221092 | |||
| dedc35b466 | |||
| 5e33587703 | |||
| 950f6830da | |||
|
|
19a8ca84e6 | ||
|
|
ece3fb1536 | ||
| 0d119502a8 | |||
| cc5951cfc3 | |||
| 61d42e0ac5 | |||
| 127935086c | |||
| 76ed60edf3 | |||
| 3b0a1c70fe | |||
| 186e07e45d | |||
| 047cff7d6e | |||
| 305275e3ac | |||
| efb0d5f4f9 | |||
| 991a074538 | |||
| f82b6c12ee | |||
| 00edfa4ef0 | |||
| 35a3ce6402 | |||
| be3ce454a0 | |||
| 4c85206cfa | |||
| 5ecdcbe46e | |||
| c937d7251a | |||
| 1cc46468c1 | |||
| 5cc8ef1eb0 | |||
| 99e135caa2 | |||
| 9de7045d63 | |||
| 0e65151e9f | |||
| 3c20728210 | |||
| 4c0530d89a | |||
| f5af8a1da9 | |||
| 44b9c37391 | |||
| 97b0b6fc0c | |||
| 1a2e9afaef | |||
| 39a3a23a24 | |||
| ee131921a0 | |||
| f8818c8537 | |||
| b07242226e |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,4 +2,5 @@
|
||||
/.svn
|
||||
/doc/rtf
|
||||
_unsused
|
||||
CMakeLists.txt.user*
|
||||
CMakeLists.txt.user*
|
||||
/include
|
||||
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
|
||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||
project(pip)
|
||||
set(pip_MAJOR 2)
|
||||
set(pip_MINOR 28)
|
||||
set(pip_MINOR 34)
|
||||
set(pip_REVISION 1)
|
||||
set(pip_SUFFIX )
|
||||
set(pip_COMPANY SHS)
|
||||
@@ -284,7 +284,7 @@ endif()
|
||||
if(APPLE)
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
|
||||
endif()
|
||||
if ((NOT DEFINED LIBPROJECT) AND (DEFINED ANDROID_PLATFORM))
|
||||
if ((NOT DEFINED SHSTKPROJECT) AND (DEFINED ANDROID_PLATFORM))
|
||||
include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include)
|
||||
#message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include")
|
||||
#message("${ANDROID_NDK}/sysroot/usr/include")
|
||||
@@ -320,7 +320,7 @@ if(WIN32)
|
||||
set(CMAKE_CXX_FLAGS "/O2 /Ob2 /Ot /W0")
|
||||
endif()
|
||||
else()
|
||||
set(${CMAKE_CXX_FLAGS} "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
if(DEFINED ENV{QNX_HOST} OR PIP_FREERTOS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-32")
|
||||
endif()
|
||||
@@ -553,13 +553,21 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
|
||||
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_EXCLUDE "\"${CMAKE_CURRENT_SOURCE_DIR}/libs/lua/3rd\"")
|
||||
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")
|
||||
if ("x${DOC_LANG}" STREQUAL "x")
|
||||
set(DOXY_OUTPUT_LANGUAGE English)
|
||||
set(DOXY_OUTPUT_DIR en)
|
||||
else()
|
||||
set(DOXY_OUTPUT_LANGUAGE ${DOC_LANG})
|
||||
set(DOXY_OUTPUT_DIR ${DOC_DIR})
|
||||
endif()
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
string(REPLACE "\\" "" _DOT_PATH "${DOXYGEN_DOT_PATH}")
|
||||
string(REPLACE "\\" "/" _DOT_PATH "${DOXYGEN_DOT_PATH}")
|
||||
set(DOXY_DOT_PATH "\"${_DOT_PATH}\"")
|
||||
set(DOXY_MSCGEN_PATH "\"${_DOT_PATH}\"")
|
||||
set(DOXY_DIA_PATH "\"${_DOT_PATH}\"")
|
||||
endif()
|
||||
set(DOXY_INPUT)
|
||||
@@ -567,8 +575,8 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
|
||||
list(APPEND DOXY_INPUT "\"${F}\"")
|
||||
endforeach(F)
|
||||
string(REPLACE ";" " " DOXY_INPUT "\"${CMAKE_CURRENT_SOURCE_DIR}/libs\"")
|
||||
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${DOXY_INPUT}")
|
||||
string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS};DOXYGEN;PIOBJECT;PIOBJECT_SUBCLASS")
|
||||
string(REPLACE ";" " " DOXY_INCLUDE_PATH "${PIP_INCLUDES}")
|
||||
string(REPLACE ";" " " DOXY_DEFINES "${PIP_EXPORTS}")
|
||||
add_documentation(doc doc/Doxyfile.in)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/html DESTINATION ../share/doc/pip COMPONENT doc EXCLUDE_FROM_ALL OPTIONAL)
|
||||
endif()
|
||||
|
||||
@@ -33,4 +33,6 @@ You should add ${<out_var>} to your target.
|
||||
|
||||
## Documentation
|
||||
|
||||
[Online documentation](https://shs.tools/pip/html/index.html)
|
||||
[Online documentation 🇺🇸](https://shs.tools/pip/html/en/index.html)
|
||||
|
||||
[Онлайн документация 🇷🇺](https://shs.tools/pip/html/ru/index.html)
|
||||
|
||||
@@ -71,6 +71,10 @@ if (NOT BUILDING_pip)
|
||||
find_library(PTHREAD_LIBRARY pthread)
|
||||
find_library(UTIL_LIBRARY util)
|
||||
set(_PIP_ADD_LIBS_ ${PTHREAD_LIBRARY} ${UTIL_LIBRARY})
|
||||
if((NOT DEFINED ENV{QNX_HOST}) AND (NOT APPLE) AND (NOT PIP_FREERTOS))
|
||||
find_library(RT_LIBRARY rt)
|
||||
list(APPEND _PIP_ADD_LIBS_ ${RT_LIBRARY})
|
||||
endif()
|
||||
list(APPEND PIP_LIBRARY ${_PIP_ADD_LIBS_})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
macro(ADD_DOCUMENTATION TARGET DOXYGEN_CONFIG_FILE)
|
||||
if(DOXYGEN_FOUND)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/${DOXYGEN_CONFIG_FILE}" "${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${TARGET}")
|
||||
add_custom_target("genereate.${TARGET}" COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${TARGET})
|
||||
add_custom_target("genereate.${TARGET}" COMMAND "${CMAKE_COMMAND}" -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/doc/html" COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxyfile-${TARGET})
|
||||
add_custom_target("${TARGET}" COMMAND ${CMAKE_COMMAND} -D COMPONENT=doc -P cmake_install.cmake)
|
||||
add_dependencies("${TARGET}" "genereate.${TARGET}")
|
||||
else(DOXYGEN_FOUND)
|
||||
|
||||
351
doc/Doxyfile.in
351
doc/Doxyfile.in
@@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.8.15
|
||||
# Doxyfile 1.9.1
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
@@ -51,7 +51,7 @@ PROJECT_BRIEF = "Platform-Independent Primitives"
|
||||
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
|
||||
# the logo to the output directory.
|
||||
|
||||
PROJECT_LOGO =
|
||||
PROJECT_LOGO = ${DOXY_LOGO_PATH}
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
@@ -91,7 +91,7 @@ ALLOW_UNICODE_NAMES = NO
|
||||
# Ukrainian and Vietnamese.
|
||||
# The default value is: English.
|
||||
|
||||
OUTPUT_LANGUAGE = English
|
||||
OUTPUT_LANGUAGE = ${DOXY_OUTPUT_LANGUAGE}
|
||||
|
||||
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
@@ -158,7 +158,7 @@ INLINE_INHERITED_MEMB = NO
|
||||
# shortest path that makes the file name unique will be used
|
||||
# The default value is: YES.
|
||||
|
||||
FULL_PATH_NAMES = YES
|
||||
FULL_PATH_NAMES = NO
|
||||
|
||||
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
|
||||
# Stripping is only done if one of the specified strings matches the left-hand
|
||||
@@ -197,10 +197,20 @@ SHORT_NAMES = NO
|
||||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
|
||||
# such as
|
||||
# /***************
|
||||
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
|
||||
# Javadoc-style will behave just like regular comments and it will not be
|
||||
# interpreted by doxygen.
|
||||
# The default value is: NO.
|
||||
|
||||
JAVADOC_BANNER = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||
# requiring an explicit @brief command for a brief description.)
|
||||
# requiring an explicit \brief command for a brief description.)
|
||||
# The default value is: NO.
|
||||
|
||||
QT_AUTOBRIEF = NO
|
||||
@@ -215,7 +225,15 @@ QT_AUTOBRIEF = NO
|
||||
# not recognized any more.
|
||||
# The default value is: NO.
|
||||
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = YES
|
||||
|
||||
# By default Python docstrings are displayed as preformatted text and doxygen's
|
||||
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
|
||||
# doxygen's special commands can be used and the contents of the docstring
|
||||
# documentation blocks is shown as doxygen documentation.
|
||||
# The default value is: YES.
|
||||
|
||||
PYTHON_DOCSTRING = YES
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||
# documentation from any documented member that it re-implements.
|
||||
@@ -256,12 +274,6 @@ ALIASES = "handlers=\name Handlers" \
|
||||
"events=\name Events" \
|
||||
"ioparams=\name Configurable parameters"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
# will allow you to use the command class in the itcl::class meaning.
|
||||
|
||||
TCL_SUBST =
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C. For
|
||||
# instance, some of the names that are used will be different. The list of all
|
||||
@@ -302,19 +314,22 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
||||
# parses. With this tag you can assign which parser to use for a given
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
||||
# Fortran), use: inc=Fortran f=C.
|
||||
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||
# use: inc=Fortran f=C.
|
||||
#
|
||||
# Note: For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||
# the files are not read by doxygen.
|
||||
# the files are not read by doxygen. When specifying no_extension you should add
|
||||
# * to the FILE_PATTERNS.
|
||||
#
|
||||
# Note see also the list of default file extension mappings.
|
||||
|
||||
EXTENSION_MAPPING =
|
||||
|
||||
@@ -332,7 +347,7 @@ MARKDOWN_SUPPORT = YES
|
||||
# to that level are automatically included in the table of contents, even if
|
||||
# they do not have an id attribute.
|
||||
# Note: This feature currently applies only to Markdown headings.
|
||||
# Minimum value: 0, maximum value: 99, default value: 0.
|
||||
# Minimum value: 0, maximum value: 99, default value: 5.
|
||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
@@ -353,7 +368,7 @@ AUTOLINK_SUPPORT = YES
|
||||
# diagrams that involve STL classes more complete and accurate.
|
||||
# The default value is: NO.
|
||||
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
|
||||
# If you use Microsoft's C++/CLI language, you should set this option to YES to
|
||||
# enable parsing support.
|
||||
@@ -448,6 +463,19 @@ TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
|
||||
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
|
||||
# during processing. When set to 0 doxygen will based this on the number of
|
||||
# cores available in the system. You can set it explicitly to a value larger
|
||||
# than 0 to get more control over the balance between CPU load and processing
|
||||
# speed. At this moment only the input processing can be done using multiple
|
||||
# threads. Since this is still an experimental feature the default is set to 1,
|
||||
# which efficively disables parallel processing. Please report any issues you
|
||||
# encounter. Generating dot graphs in parallel is controlled by the
|
||||
# DOT_NUM_THREADS setting.
|
||||
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||
|
||||
NUM_PROC_THREADS = 1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -468,6 +496,12 @@ EXTRACT_ALL = NO
|
||||
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||
# methods of a class will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_PRIV_VIRTUAL = YES
|
||||
|
||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||
# scope will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
@@ -505,6 +539,13 @@ EXTRACT_LOCAL_METHODS = YES
|
||||
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
|
||||
# If this flag is set to YES, the name of an unnamed parameter in a declaration
|
||||
# will be determined by the corresponding definition. By default unnamed
|
||||
# parameters remain unnamed in the output.
|
||||
# The default value is: YES.
|
||||
|
||||
RESOLVE_UNNAMED_PARAMS = YES
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||
# undocumented members inside documented classes or files. If set to NO these
|
||||
# members will be included in the various overviews, but no documentation
|
||||
@@ -522,8 +563,8 @@ HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
|
||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
||||
# included in the documentation.
|
||||
# declarations. If set to NO, these declarations will be included in the
|
||||
# documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_FRIEND_COMPOUNDS = YES
|
||||
@@ -542,11 +583,18 @@ HIDE_IN_BODY_DOCS = NO
|
||||
|
||||
INTERNAL_DOCS = NO
|
||||
|
||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# and Mac users are advised to set this option to NO.
|
||||
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
|
||||
# able to match the capabilities of the underlying filesystem. In case the
|
||||
# filesystem is case sensitive (i.e. it supports files in the same directory
|
||||
# whose names only differ in casing), the option must be set to YES to properly
|
||||
# deal with such files in case they appear in the input. For filesystems that
|
||||
# are not case sensitive the option should be be set to NO to properly deal with
|
||||
# output files written for symbols that only differ in casing, such as for two
|
||||
# classes, one named CLASS and the other named Class, and to also support
|
||||
# references to files without having to specify the exact matching casing. On
|
||||
# Windows (including Cygwin) and MacOS, users should typically set this option
|
||||
# to NO, whereas on Linux or other Unix flavors it should typically be set to
|
||||
# YES.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
@@ -576,7 +624,7 @@ SHOW_INCLUDE_FILES = NO
|
||||
# which file to include in order to use the member.
|
||||
# The default value is: NO.
|
||||
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
SHOW_GROUPED_MEMB_INC = YES
|
||||
|
||||
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
|
||||
# files with double quotes in the documentation rather than with sharp brackets.
|
||||
@@ -785,7 +833,10 @@ WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# a warning is encountered.
|
||||
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = NO
|
||||
@@ -821,8 +872,8 @@ INPUT = ${DOXY_INPUT}
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
||||
# possible encodings.
|
||||
# documentation (see:
|
||||
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
INPUT_ENCODING = UTF-8
|
||||
@@ -835,46 +886,20 @@ INPUT_ENCODING = UTF-8
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# Note the list of default checked file patterns might differ from the list of
|
||||
# default file extension mappings.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
|
||||
# *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.d \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.idl \
|
||||
*.odl \
|
||||
*.cs \
|
||||
*.php \
|
||||
*.php3 \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.markdown \
|
||||
*.md \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.f90 \
|
||||
*.f \
|
||||
*.for \
|
||||
*.vhd \
|
||||
*.vhdl
|
||||
*.md
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
@@ -1087,16 +1112,22 @@ USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = NO
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
||||
# cost of reduced performance. This can be particularly helpful with template
|
||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
||||
# information.
|
||||
# clang parser (see:
|
||||
# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
|
||||
# performance. This can be particularly helpful with template rich C++ code for
|
||||
# which doxygen's built-in parser lacks the necessary type information.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to
|
||||
# YES then doxygen will add the directory of each input to the include path.
|
||||
# The default value is: YES.
|
||||
|
||||
CLANG_ADD_INC_PATHS = YES
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by doxygen for the files and directories
|
||||
@@ -1106,10 +1137,13 @@ CLANG_ASSISTED_PARSING = NO
|
||||
CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
|
||||
# were built. This is equivalent to specifying the "-p" option to a clang tool,
|
||||
# such as clang-check. These options will then be passed to the parser.
|
||||
# path to the directory containing a file called compile_commands.json. This
|
||||
# file is the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
|
||||
# options used when the source files were built. This is equivalent to
|
||||
# specifying the -p option to a clang tool, such as clang-check. These options
|
||||
# will then be passed to the parser. Any options specified with CLANG_OPTIONS
|
||||
# will be added as well.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
@@ -1126,13 +1160,6 @@ CLANG_DATABASE_PATH =
|
||||
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
||||
# which the alphabetical index list will be split.
|
||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
||||
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all classes will
|
||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||
@@ -1156,7 +1183,7 @@ GENERATE_HTML = YES
|
||||
# The default directory is: html.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_OUTPUT = html
|
||||
HTML_OUTPUT = html/${DOXY_OUTPUT_DIR}
|
||||
|
||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||
# generated HTML page (for example: .htm, .php, .asp).
|
||||
@@ -1239,7 +1266,7 @@ HTML_EXTRA_FILES =
|
||||
# Minimum value: 0, maximum value: 359, default value: 220.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COLORSTYLE_HUE = 246
|
||||
HTML_COLORSTYLE_HUE = 221
|
||||
|
||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
||||
# in the HTML output. For a value of 0 the output will use grayscales only. A
|
||||
@@ -1247,7 +1274,7 @@ HTML_COLORSTYLE_HUE = 246
|
||||
# Minimum value: 0, maximum value: 255, default value: 100.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COLORSTYLE_SAT = 79
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
|
||||
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
|
||||
# luminance component of the colors in the HTML output. Values below 100
|
||||
@@ -1271,9 +1298,9 @@ HTML_TIMESTAMP = YES
|
||||
|
||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||
# documentation will contain a main index with vertical navigation menus that
|
||||
# are dynamically created via Javascript. If disabled, the navigation index will
|
||||
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||
# page. Disable this option to support browsers that do not have Javascript,
|
||||
# page. Disable this option to support browsers that do not have JavaScript,
|
||||
# like the Qt help browser.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
@@ -1299,14 +1326,15 @@ HTML_DYNAMIC_SECTIONS = NO
|
||||
# Minimum value: 0, maximum value: 9999, default value: 100.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
HTML_INDEX_NUM_ENTRIES = 1
|
||||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
||||
# that directory and running make install will install the docset in
|
||||
# environment (see:
|
||||
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
|
||||
# create a documentation set, doxygen will generate a Makefile in the HTML
|
||||
# output directory. Running make will produce the docset in that directory and
|
||||
# running make install will install the docset in
|
||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||
# genXcode/_index.html for more information.
|
||||
@@ -1329,7 +1357,7 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_BUNDLE_ID = ${DOXY_DOMAIN}
|
||||
|
||||
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
|
||||
# the documentation publisher. This should be a reverse domain-name style
|
||||
@@ -1337,19 +1365,19 @@ DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
# The default value is: org.doxygen.Publisher.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_ID = ${DOXY_DOMAIN}
|
||||
|
||||
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
|
||||
# The default value is: Publisher.
|
||||
# This tag requires that the tag GENERATE_DOCSET is set to YES.
|
||||
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
DOCSET_PUBLISHER_NAME = PIP
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
# (see:
|
||||
# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||
@@ -1379,7 +1407,7 @@ CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
|
||||
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
||||
# (YES) or that it should be included in the master .chm file (NO).
|
||||
# (YES) or that it should be included in the main .chm file (NO).
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
@@ -1420,11 +1448,12 @@ GENERATE_QHP = YES
|
||||
# the HTML output folder.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QCH_FILE = pip.qch
|
||||
QCH_FILE = pip_${DOXY_OUTPUT_DIR}.qch
|
||||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@@ -1432,8 +1461,8 @@ QHP_NAMESPACE = PIP
|
||||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||
# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# Folders (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
@@ -1441,30 +1470,30 @@ QHP_VIRTUAL_FOLDER = PIP
|
||||
|
||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_NAME = PIP
|
||||
|
||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# Filters (see:
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_CUST_FILTER_ATTRS = ${DOXY_QHP_CUST_FILTER_ATTRS}
|
||||
|
||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_SECT_FILTER_ATTRS = ${DOXY_QHP_SECT_FILTER_ATTRS}
|
||||
|
||||
# The QHG_LOCATION tag can be used to specify the location of Qt's
|
||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
||||
# generated .qhp file.
|
||||
# The QHG_LOCATION tag can be used to specify the location (absolute path
|
||||
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
|
||||
# run qhelpgenerator on the generated .qhp file.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHG_LOCATION = qhelpgenerator
|
||||
@@ -1487,7 +1516,7 @@ GENERATE_ECLIPSEHELP = NO
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
|
||||
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
ECLIPSE_DOC_ID = PIP
|
||||
|
||||
# If you want full control over the layout of the generated HTML pages it might
|
||||
# be necessary to disable the index and replace it with your own. The
|
||||
@@ -1515,7 +1544,7 @@ DISABLE_INDEX = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = YES
|
||||
GENERATE_TREEVIEW = NO
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||
# doxygen will group on one line in the generated HTML documentation.
|
||||
@@ -1541,6 +1570,17 @@ TREEVIEW_WIDTH = 250
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||
# Possible values are: png (the default) and svg (looks nicer but requires the
|
||||
# pdf2svg or inkscape tool).
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_FORMULA_FORMAT = png
|
||||
|
||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||
# the HTML documentation. When you change the font size after a successful
|
||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||
@@ -1561,8 +1601,14 @@ FORMULA_FONTSIZE = 10
|
||||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||
# the section "Including formulas" for details.
|
||||
|
||||
FORMULA_MACROFILE =
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||
# https://www.mathjax.org) which uses client side Javascript for the rendering
|
||||
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||
# installed or if you want to formulas look prettier in the HTML output. When
|
||||
# enabled you may also need to install MathJax separately and configure the path
|
||||
@@ -1574,7 +1620,7 @@ USE_MATHJAX = NO
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
|
||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
||||
# The default value is: HTML-CSS.
|
||||
@@ -1590,7 +1636,7 @@ MATHJAX_FORMAT = HTML-CSS
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
||||
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
@@ -1604,7 +1650,8 @@ MATHJAX_EXTENSIONS =
|
||||
|
||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
||||
# (see:
|
||||
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
|
||||
# example see the documentation.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
@@ -1629,10 +1676,10 @@ MATHJAX_CODEFILE =
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
SEARCHENGINE = NO
|
||||
SEARCHENGINE = YES
|
||||
|
||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||
# implemented using a web server instead of a web client using Javascript. There
|
||||
# implemented using a web server instead of a web client using JavaScript. There
|
||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||
@@ -1651,7 +1698,8 @@ SERVER_BASED_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: https://xapian.org/).
|
||||
# Xapian (see:
|
||||
# https://xapian.org/).
|
||||
#
|
||||
# See the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
@@ -1664,8 +1712,9 @@ EXTERNAL_SEARCH = NO
|
||||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
||||
# Searching" for details.
|
||||
# Xapian (see:
|
||||
# https://xapian.org/). See the section "External Indexing and Searching" for
|
||||
# details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
SEARCHENGINE_URL =
|
||||
@@ -1736,13 +1785,14 @@ LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
||||
# generate index for LaTeX.
|
||||
# generate index for LaTeX. In case there is no backslash (\) as first character
|
||||
# it will be automatically added in the LaTeX code.
|
||||
# Note: This tag is used in the generated output file (.tex).
|
||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
||||
# The default value is: \makeindex.
|
||||
# The default value is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_MAKEINDEX_CMD = \makeindex
|
||||
LATEX_MAKEINDEX_CMD = makeindex
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
|
||||
# documents. This may be useful for small projects and may help to save some
|
||||
@@ -1828,9 +1878,11 @@ LATEX_EXTRA_FILES =
|
||||
|
||||
PDF_HYPERLINKS = YES
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
||||
# higher quality PDF documentation.
|
||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
|
||||
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
|
||||
# files. Set this option to YES, to get a higher quality PDF documentation.
|
||||
#
|
||||
# See also section LATEX_CMD_NAME for selecting the engine.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
@@ -2164,7 +2216,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED = ${DOXY_DEFINES}
|
||||
PREDEFINED = DOXYGEN PIOBJECT PIOBJECT_SUBCLASS PIIODEVICE NO_COPY_CLASS ${DOXY_DEFINES}
|
||||
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
@@ -2209,7 +2261,7 @@ TAGFILES =
|
||||
# tag file that is based on the input files it reads. See section "Linking to
|
||||
# external documentation" for more information about the usage of tag files.
|
||||
|
||||
GENERATE_TAGFILE = doc/pip.cfg
|
||||
GENERATE_TAGFILE = doc/html/${DOXY_OUTPUT_DIR}/pip.cfg
|
||||
|
||||
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
|
||||
# the class index. If set to NO, only the inherited external classes will be
|
||||
@@ -2232,12 +2284,6 @@ EXTERNAL_GROUPS = YES
|
||||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -2251,15 +2297,6 @@ PERL_PATH = /usr/bin/perl
|
||||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see:
|
||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH = ${DOXY_MSCGEN_PATH}
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
@@ -2357,10 +2394,32 @@ UML_LOOK = NO
|
||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||
# 10.
|
||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
UML_LIMIT_NUM_FIELDS = 12
|
||||
|
||||
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
|
||||
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
|
||||
# tag is set to YES, doxygen will add type and arguments for attributes and
|
||||
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
|
||||
# will not generate fields with class member information in the UML graphs. The
|
||||
# class diagrams will look similar to the default class diagrams but using UML
|
||||
# notation for the relationships.
|
||||
# Possible values are: NO, YES and NONE.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag UML_LOOK is set to YES.
|
||||
|
||||
DOT_UML_DETAILS = NO
|
||||
|
||||
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||
# to display on a single line. If the actual line length exceeds this threshold
|
||||
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||
# to avoid ugly line breaks.
|
||||
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_WRAP_THRESHOLD = 17
|
||||
|
||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||
# collaboration graphs will show the relations between templates and their
|
||||
# instances.
|
||||
@@ -2550,9 +2609,11 @@ DOT_MULTI_TARGETS = YES
|
||||
|
||||
GENERATE_LEGEND = YES
|
||||
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||
# files that are used to generate the various graphs.
|
||||
#
|
||||
# Note: This setting is not only used for dot files but also for msc and
|
||||
# plantuml temporary files.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
@@ -4,14 +4,17 @@ void _() {
|
||||
//! [foreach]
|
||||
PIVector<int> vec;
|
||||
vec << 1 << 2 << 3;
|
||||
piForeach (int & i, vec)
|
||||
cout << i << ", ";
|
||||
// 1, 2, 3,
|
||||
piForeach (int & i, vec)
|
||||
i++;
|
||||
piForeach (int & i, vec)
|
||||
cout << i << ", ";
|
||||
// 2, 3, 4,
|
||||
|
||||
piForeach (int & i, vec) piCout << i;
|
||||
// 1
|
||||
// 2
|
||||
// 3
|
||||
|
||||
piForeach (int & i, vec) i++;
|
||||
piForeach (int & i, vec) piCout << i;
|
||||
// 2
|
||||
// 3
|
||||
// 4
|
||||
//! [foreach]
|
||||
//! [foreachC]
|
||||
PIVector<int> vec;
|
||||
|
||||
@@ -5,8 +5,8 @@ class ObjectA: public PIObject {
|
||||
PIOBJECT(ObjectA)
|
||||
public:
|
||||
EVENT_HANDLER1(void, handlerA, const PIString & , str) {piCoutObj << "handler A:" << str;}
|
||||
EVENT2(eventA2, int, i, float, f);
|
||||
EVENT1(eventA1, const PIString & , str);
|
||||
EVENT2(eventA2, int, i, float, f);
|
||||
};
|
||||
|
||||
class ObjectB: public PIObject {
|
||||
@@ -26,7 +26,11 @@ int main(int argc, char * argv[]) {
|
||||
CONNECT1(void, PIString, &obj_b, eventB, &obj_a, handlerA);
|
||||
obj_b.eventB("event to handler");
|
||||
|
||||
CONNECT1(void, PIString, &obj_a, eventA1, &obj_b, eventB);
|
||||
CONNECTU(&obj_a, eventA1, &obj_b, eventB);
|
||||
obj_a.eventA1("event to event");
|
||||
|
||||
obj_a.piDisconnect("eventA1");
|
||||
CONNECTL(&obj_a, eventA1, ([](const PIString & str){piCout << str;}));
|
||||
obj_a.eventA1("event to lambda");
|
||||
};
|
||||
//! [main]
|
||||
|
||||
BIN
doc/images/pirect.png
Normal file
BIN
doc/images/pirect.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
BIN
doc/pip.png
Normal file
BIN
doc/pip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
29
library.json
Normal file
29
library.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "PIP",
|
||||
"keywords": "pip",
|
||||
"description": "Platform-Independent Primitives",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://git.shs.tools/SHS/pip.git"
|
||||
},
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
"dependencies": {
|
||||
"mike-matera/ArduinoSTL": "^1.3.2",
|
||||
"linlin-study/FreeRTOS-Kernel": ">=10.0.0"
|
||||
},
|
||||
"build":
|
||||
{
|
||||
"srcFilter": [
|
||||
"+<libs/main/core/*.cpp>",
|
||||
"+<libs/main/containers/*.cpp>",
|
||||
"+<libs/main/math/*.cpp>",
|
||||
"+<libs/main/thread/*.cpp>",
|
||||
"+<libs/main/io_uutils/*.cpp>",
|
||||
"+<libs/main/geo/*.cpp>"
|
||||
],
|
||||
"extraScript": "platformio_pre.py",
|
||||
"flags": "-DPIP_FREERTOS"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
PICloudBase::PICloudBase() : eth(PIEthernet::TCP_Client), streampacker(ð), tcp(&streampacker) {
|
||||
|
||||
eth.setDebug(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,29 +25,36 @@ PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode)
|
||||
tcp.setRole(PICloud::TCP::Client);
|
||||
setName("cloud_client");
|
||||
is_connected = false;
|
||||
CONNECTL(ð, connected, [this](){tcp.sendStart();});
|
||||
is_deleted = false;
|
||||
// setReopenEnabled(false);
|
||||
CONNECTL(ð, connected, [this](){opened_ = true; tcp.sendStart();});
|
||||
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
|
||||
CONNECTL(ð, disconnected, [this](bool){
|
||||
piCoutObj << "disconnected";
|
||||
if (is_deleted) return;
|
||||
bool need_disconn = is_connected;
|
||||
//piCoutObj << "eth disconnected";
|
||||
static_cast<PIThread*>(ð)->stop();
|
||||
opened_ = false;
|
||||
is_connected = false;
|
||||
cond_connect.notifyOne();
|
||||
cond_buff.notifyOne();
|
||||
piMSleep(100);
|
||||
internalDisconnect();
|
||||
if (need_disconn)
|
||||
disconnected();
|
||||
//piCoutObj << "eth disconnected done";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
PICloudClient::~PICloudClient() {
|
||||
eth.close();
|
||||
if (is_connected) {
|
||||
is_connected = false;
|
||||
disconnected();
|
||||
cond_buff.notifyOne();
|
||||
cond_connect.notifyOne();
|
||||
}
|
||||
//piCoutObj << "~PICloudClient()";
|
||||
PIThread::stop();
|
||||
//eth.close();
|
||||
//if (is_connected) disconnected();
|
||||
close();
|
||||
stop();
|
||||
//piCoutObj << "~PICloudClient() closed";
|
||||
internalDisconnect();
|
||||
// stop(false);
|
||||
is_deleted = true;
|
||||
internalDisconnect();
|
||||
//piCoutObj << "~PICloudClient() done";
|
||||
}
|
||||
|
||||
|
||||
@@ -63,80 +70,100 @@ void PICloudClient::setKeepConnection(bool on) {
|
||||
|
||||
|
||||
bool PICloudClient::openDevice() {
|
||||
// piCout << "PICloudClient open device" << path();
|
||||
//piCoutObj << "open";// << path();
|
||||
bool op = eth.connect(PIEthernet::Address::resolve(path()), false);
|
||||
if (op) {
|
||||
mutex_buff.lock();
|
||||
mutex_connect.lock();
|
||||
eth.startThreadedRead();
|
||||
bool conn_ok = cond_connect.waitFor(mutex_buff, (int)eth.readTimeout(), [this](){return isConnected();});
|
||||
piCoutObj << "conn_ok" << conn_ok;
|
||||
mutex_buff.unlock();
|
||||
//piCoutObj << "connecting...";
|
||||
bool conn_ok = cond_connect.waitFor(mutex_connect, (int)eth.readTimeout());
|
||||
//piCoutObj << "conn_ok" << conn_ok << is_connected;
|
||||
mutex_connect.unlock();
|
||||
if (!conn_ok) {
|
||||
mutex_connect.lock();
|
||||
eth.stop();
|
||||
eth.close();
|
||||
piMSleep(100);
|
||||
mutex_connect.unlock();
|
||||
}
|
||||
return isConnected();
|
||||
return is_connected;
|
||||
} else {
|
||||
eth.close();
|
||||
//eth.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PICloudClient::closeDevice() {
|
||||
//PIThread::stop();
|
||||
if (is_connected) {
|
||||
is_connected = false;
|
||||
disconnected();
|
||||
cond_buff.notifyOne();
|
||||
cond_connect.notifyOne();
|
||||
internalDisconnect();
|
||||
}
|
||||
eth.stop();
|
||||
if (eth.isOpened()) eth.close();
|
||||
eth.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int PICloudClient::readDevice(void * read_to, int max_size) {
|
||||
// piCoutObj << "readDevice";
|
||||
if (!is_connected) return -1;
|
||||
if (is_deleted) return -1;
|
||||
//piCoutObj << "readDevice";
|
||||
if (!is_connected && eth.isClosed()) openDevice();
|
||||
int sz = -1;
|
||||
mutex_buff.lock();
|
||||
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty();});
|
||||
int sz = piMini(max_size, buff.size());
|
||||
memcpy(read_to, buff.data(), sz);
|
||||
buff.remove(0, sz);
|
||||
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
|
||||
if (is_connected) {
|
||||
sz = piMini(max_size, buff.size());
|
||||
memcpy(read_to, buff.data(), sz);
|
||||
buff.remove(0, sz);
|
||||
}
|
||||
mutex_buff.unlock();
|
||||
if (!is_connected) opened_ = false;
|
||||
//piCoutObj << "readDevice done" << sz;
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
int PICloudClient::writeDevice(const void * data, int size) {
|
||||
if (is_deleted) return -1;
|
||||
// piCoutObj << "writeDevice";
|
||||
return tcp.sendData(PIByteArray(data, size));
|
||||
}
|
||||
|
||||
|
||||
void PICloudClient::internalDisconnect() {
|
||||
is_connected = false;
|
||||
cond_buff.notifyOne();
|
||||
cond_connect.notifyOne();
|
||||
streampacker.clear();
|
||||
buff.clear();
|
||||
}
|
||||
|
||||
|
||||
void PICloudClient::_readed(PIByteArray & ba) {
|
||||
mutex_buff.lock();
|
||||
if (is_deleted) return;
|
||||
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
|
||||
//piCoutObj << "_readed" << ba.size() << hdr.first << hdr.second;
|
||||
if (hdr.second == tcp.role()) {
|
||||
switch (hdr.first) {
|
||||
case PICloud::TCP::Connect:
|
||||
if (tcp.parseConnect(ba) == 1) {
|
||||
mutex_connect.lock();
|
||||
is_connected = true;
|
||||
connected();
|
||||
mutex_connect.unlock();
|
||||
cond_connect.notifyOne();
|
||||
connected();
|
||||
}
|
||||
break;
|
||||
case PICloud::TCP::Disconnect:
|
||||
is_connected = false;
|
||||
eth.stop();
|
||||
static_cast<PIThread*>(ð)->stop();
|
||||
opened_ = false;
|
||||
eth.close();
|
||||
disconnected();
|
||||
break;
|
||||
case PICloud::TCP::Data:
|
||||
if (is_connected) {
|
||||
mutex_buff.lock();
|
||||
buff.append(ba);
|
||||
mutex_buff.unlock();
|
||||
cond_buff.notifyOne();
|
||||
}
|
||||
break;
|
||||
@@ -145,7 +172,7 @@ void PICloudClient::_readed(PIByteArray & ba) {
|
||||
}
|
||||
//piCoutObj << "readed" << ba.toHex();
|
||||
}
|
||||
mutex_buff.unlock();
|
||||
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100);
|
||||
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); // FIXME: sleep here is bad
|
||||
//piCoutObj << "_readed done";
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,17 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode)
|
||||
tcp.setServerName(server_name);
|
||||
setName("cloud_server__" + server_name);
|
||||
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
|
||||
CONNECTL(ð, connected, [this](){tcp.sendStart();});
|
||||
CONNECTL(ð, connected, [this](){opened_ = true; piCoutObj << "connected"; tcp.sendStart();});
|
||||
CONNECTL(ð, disconnected, [this](bool){
|
||||
piCoutObj << "disconnected";
|
||||
static_cast<PIThread*>(ð)->stop();
|
||||
opened_ = false;
|
||||
ping_timer.stop(false);
|
||||
piMSleep(100);
|
||||
});
|
||||
CONNECTL(&ping_timer, tickEvent, [this] (void *, int){
|
||||
if (eth.isConnected()) tcp.sendPing();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -54,12 +59,14 @@ PIVector<PICloudServer::Client *> PICloudServer::clients() const {
|
||||
|
||||
|
||||
bool PICloudServer::openDevice() {
|
||||
piCout << "PICloudServer open device" << path();
|
||||
//piCout << "PICloudServer open device" << path();
|
||||
bool op = eth.connect(PIEthernet::Address::resolve(path()), false);
|
||||
if (op) {
|
||||
eth.startThreadedRead();
|
||||
ping_timer.start(5000);
|
||||
return true;
|
||||
}
|
||||
ping_timer.stop(false);
|
||||
eth.close();
|
||||
return false;
|
||||
}
|
||||
@@ -67,6 +74,7 @@ bool PICloudServer::openDevice() {
|
||||
|
||||
bool PICloudServer::closeDevice() {
|
||||
eth.stop();
|
||||
ping_timer.stop(false);
|
||||
clients_mutex.lock();
|
||||
for (auto c : clients_) {
|
||||
c->close();
|
||||
@@ -82,7 +90,8 @@ bool PICloudServer::closeDevice() {
|
||||
|
||||
int PICloudServer::readDevice(void * read_to, int max_size) {
|
||||
//piCoutObj << "readDevice";
|
||||
piMSleep(eth.readTimeout());
|
||||
if (!opened_) openDevice();
|
||||
else piMSleep(eth.readTimeout());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -126,22 +135,26 @@ bool PICloudServer::Client::openDevice() {
|
||||
|
||||
|
||||
bool PICloudServer::Client::closeDevice() {
|
||||
PIThread::stop(false);
|
||||
if (is_connected) {
|
||||
server->clientDisconnect(client_id);
|
||||
is_connected = false;
|
||||
cond_buff.notifyOne();
|
||||
}
|
||||
cond_buff.notifyOne();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int PICloudServer::Client::readDevice(void * read_to, int max_size) {
|
||||
if (!is_connected) return -1;
|
||||
int sz = -1;
|
||||
mutex_buff.lock();
|
||||
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty();});
|
||||
int sz = piMini(max_size, buff.size());
|
||||
memcpy(read_to, buff.data(), sz);
|
||||
buff.remove(0, sz);
|
||||
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
|
||||
if (is_connected) {
|
||||
sz = piMini(max_size, buff.size());
|
||||
memcpy(read_to, buff.data(), sz);
|
||||
buff.remove(0, sz);
|
||||
}
|
||||
mutex_buff.unlock();
|
||||
return sz;
|
||||
}
|
||||
@@ -158,7 +171,7 @@ void PICloudServer::Client::pushBuffer(const PIByteArray & ba) {
|
||||
buff.append(ba);
|
||||
cond_buff.notifyOne();
|
||||
mutex_buff.unlock();
|
||||
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100);
|
||||
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); // FIXME: sleep here is bad
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +187,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
|
||||
if (oc) {
|
||||
tcp.sendDisconnected(id);
|
||||
} else {
|
||||
piCoutObj << "new Client" << id;
|
||||
//piCoutObj << "new Client" << id;
|
||||
Client * c = new Client(this, id);
|
||||
CONNECTU(c, deleted, this, clientDeleted);
|
||||
clients_mutex.lock();
|
||||
@@ -186,7 +199,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
|
||||
} break;
|
||||
case PICloud::TCP::Disconnect: {
|
||||
uint id = tcp.parseDisconnect(ba);
|
||||
piCoutObj << "remove Client" << id;
|
||||
//piCoutObj << "remove Client" << id;
|
||||
clients_mutex.lock();
|
||||
Client * oc = index_clients.value(id, nullptr);
|
||||
clients_mutex.unlock();
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "pistreampacker.h"
|
||||
|
||||
|
||||
const char hash_def_key[] = "_picrypt_";
|
||||
const char hash_cloud_key[] = "_picloud_";
|
||||
|
||||
|
||||
PICloud::TCP::Header::Header() {
|
||||
@@ -33,7 +33,7 @@ PICloud::TCP::Header::Header() {
|
||||
|
||||
|
||||
PICloud::TCP::TCP(PIStreamPacker * s) : streampacker(s) {
|
||||
|
||||
streampacker->setMaxPacketSize(63*1024);
|
||||
}
|
||||
|
||||
void PICloud::TCP::setRole(PICloud::TCP::Role r) {
|
||||
@@ -43,7 +43,7 @@ void PICloud::TCP::setRole(PICloud::TCP::Role r) {
|
||||
|
||||
void PICloud::TCP::setServerName(const PIString & server_name_) {
|
||||
server_name = server_name_;
|
||||
suuid = PICrypt::hash(server_name_);
|
||||
suuid = PICrypt::hash(PIByteArray(server_name_.data(), server_name_.size()), (const unsigned char *)hash_cloud_key, sizeof(hash_cloud_key));
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,9 @@ void PICloud::TCP::sendStart() {
|
||||
PIByteArray ba;
|
||||
ba << header;
|
||||
ba.append(suuid);
|
||||
//mutex_send.lock();
|
||||
streampacker->send(ba);
|
||||
//mutex_send.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +72,9 @@ void PICloud::TCP::sendConnected(uint client_id) {
|
||||
header.type = PICloud::TCP::Connect;
|
||||
PIByteArray ba;
|
||||
ba << header << client_id;
|
||||
// mutex_send.lock();
|
||||
streampacker->send(ba);
|
||||
// mutex_send.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +82,9 @@ void PICloud::TCP::sendDisconnected(uint client_id) {
|
||||
header.type = PICloud::TCP::Disconnect;
|
||||
PIByteArray ba;
|
||||
ba << header << client_id;
|
||||
// mutex_send.lock();
|
||||
streampacker->send(ba);
|
||||
// mutex_send.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -87,8 +93,10 @@ int PICloud::TCP::sendData(const PIByteArray & data) {
|
||||
PIByteArray ba;
|
||||
ba << header;
|
||||
ba.append(data);
|
||||
// piCout << "sendData" << ba.toHex();
|
||||
// piCout << "[PICloud::TCP] sendData" << ba.toHex();
|
||||
mutex_send.lock();
|
||||
streampacker->send(ba);
|
||||
mutex_send.unlock();
|
||||
return data.size_s();
|
||||
}
|
||||
|
||||
@@ -98,11 +106,24 @@ int PICloud::TCP::sendData(const PIByteArray & data, uint client_id) {
|
||||
PIByteArray ba;
|
||||
ba << header << client_id;
|
||||
ba.append(data);
|
||||
mutex_send.lock();
|
||||
streampacker->send(ba);
|
||||
mutex_send.unlock();
|
||||
return data.size_s();
|
||||
}
|
||||
|
||||
|
||||
void PICloud::TCP::sendPing() {
|
||||
header.type = PICloud::TCP::Ping;
|
||||
PIByteArray ba;
|
||||
ba << header;
|
||||
ba.append(suuid);
|
||||
mutex_send.lock();
|
||||
streampacker->send(ba);
|
||||
mutex_send.unlock();
|
||||
}
|
||||
|
||||
|
||||
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteArray & ba) {
|
||||
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> ret;
|
||||
ret.first = InvalidType;
|
||||
@@ -120,11 +141,8 @@ PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteA
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PICloud::TCP::parseData(PIByteArray & ba) {
|
||||
if (header.role == Client) {
|
||||
return ba;
|
||||
}
|
||||
return PIByteArray();
|
||||
bool PICloud::TCP::canParseData(PIByteArray & ba) {
|
||||
return header.role == Client;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +151,7 @@ PIPair<uint, PIByteArray> PICloud::TCP::parseDataServer(PIByteArray & ba) {
|
||||
ret.first = 0;
|
||||
if (header.role == Server) {
|
||||
ba >> ret.first;
|
||||
ret.second = ba;
|
||||
ret.second.swap(ba);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "picompress.h"
|
||||
#ifdef PIP_COMPRESS
|
||||
# ifdef FREERTOS
|
||||
# ifdef ESP_PLATFORM
|
||||
# include "esp32/rom/miniz.h"
|
||||
# define compress2 mz_compress2
|
||||
# define Z_OK MZ_OK
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
# include <fcntl.h>
|
||||
# include <termios.h>
|
||||
#else
|
||||
# include <wingdi.h>
|
||||
# include <wincon.h>
|
||||
# ifndef COMMON_LVB_UNDERSCORE
|
||||
# define COMMON_LVB_UNDERSCORE 0x8000
|
||||
@@ -62,7 +63,7 @@ PIScreen::SystemConsole::SystemConsole() {
|
||||
GetConsoleMode(PRIVATE->hOut, &PRIVATE->smode);
|
||||
GetConsoleCursorInfo(PRIVATE->hOut, &PRIVATE->curinfo);
|
||||
#else
|
||||
# ifdef FREERTOS
|
||||
# ifdef MICRO_PIP
|
||||
w = 80;
|
||||
h = 24;
|
||||
# else
|
||||
@@ -108,16 +109,13 @@ void PIScreen::SystemConsole::end() {
|
||||
|
||||
|
||||
void PIScreen::SystemConsole::prepare() {
|
||||
int w, h;
|
||||
int w = 80, h = 24;
|
||||
#ifdef WINDOWS
|
||||
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->csbi);
|
||||
w = PRIVATE->csbi.srWindow.Right - PRIVATE->csbi.srWindow.Left + 1;
|
||||
h = PRIVATE->csbi.srWindow.Bottom - PRIVATE->csbi.srWindow.Top + 1;
|
||||
#else
|
||||
# ifdef FREERTOS
|
||||
w = 80;
|
||||
h = 24;
|
||||
# else
|
||||
# ifndef MICRO_PIP
|
||||
winsize ws;
|
||||
ioctl(0, TIOCGWINSZ, &ws);
|
||||
w = ws.ws_col;
|
||||
@@ -144,7 +142,7 @@ void PIScreen::SystemConsole::resize(int w, int h) {
|
||||
pcells.resize(height);
|
||||
for (int i = 0; i < height; ++i) {
|
||||
cells[i].resize(width);
|
||||
pcells[i].resize(width, Cell(0));
|
||||
pcells[i].resize(width, Cell(PIChar()));
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->sbi.srWindow = PRIVATE->csbi.srWindow;
|
||||
|
||||
@@ -691,7 +691,7 @@ bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
|
||||
default:
|
||||
PIChar tc
|
||||
#ifdef WINDOWS
|
||||
= PIChar(key.key);
|
||||
= PIChar((ushort)key.key);
|
||||
#else
|
||||
= PIChar::fromUTF8((char *)&(key.key));
|
||||
#endif
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
#include "piincludes_p.h"
|
||||
#include "piterminal.h"
|
||||
#include "pisharedmemory.h"
|
||||
#ifndef FREERTOS
|
||||
#ifndef MICRO_PIP
|
||||
#ifdef WINDOWS
|
||||
# include <windows.h>
|
||||
# include <wingdi.h>
|
||||
# include <wincon.h>
|
||||
# include <winuser.h>
|
||||
#else
|
||||
@@ -238,9 +239,9 @@ void PITerminal::write(PIKbdListener::KeyEvent ke) {
|
||||
else {
|
||||
PIByteArray ba;
|
||||
#ifdef WINDOWS
|
||||
ba << uchar(PIChar(ke.key).toConsole1Byte());
|
||||
ba << uchar(PIChar((ushort)ke.key).toConsole1Byte());
|
||||
#else
|
||||
ba = PIString(PIChar(ke.key)).toUTF8();
|
||||
ba = PIString(PIChar((ushort)ke.key)).toUTF8();
|
||||
#endif
|
||||
write(ba);
|
||||
}
|
||||
@@ -917,4 +918,4 @@ bool PITerminal::resize(int cols, int rows) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // FREERTOS
|
||||
#endif // MICRO_PIP
|
||||
|
||||
@@ -128,7 +128,7 @@ PIAuth::State PIAuth::receive(PIByteArray & ba) {
|
||||
passwordRequest(&ps);
|
||||
if (ps.isEmpty()) return disconnect(ba, "Canceled by user");
|
||||
ph = crypt.passwordHash(ps, PIString("PIAuth").toByteArray());
|
||||
ps.fill(PIChar(0));
|
||||
ps.fill(PIChar());
|
||||
tba.clear();
|
||||
tba << ph << auth_sign << sign_pk;
|
||||
tba = crypt.crypt(tba, box_pk, box_sk);
|
||||
|
||||
@@ -169,6 +169,19 @@ PIByteArray PICrypt::hash(const PIByteArray & data) {
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PICrypt::hash(const PIByteArray & data, const unsigned char *key, size_t keylen) {
|
||||
PIByteArray hash;
|
||||
#ifdef PIP_CRYPT
|
||||
if (!init()) return hash;
|
||||
hash.resize(crypto_generichash_BYTES);
|
||||
crypto_generichash(hash.data(), hash.size(), data.data(), data.size(), key, keylen);
|
||||
#else
|
||||
PICRYPT_DISABLED_WARNING
|
||||
#endif
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
size_t PICrypt::sizeHash() {
|
||||
#ifdef PIP_CRYPT
|
||||
return crypto_generichash_BYTES;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pifft_p.h
|
||||
* @brief Class for FFT, IFFT and Hilbert transformations
|
||||
/*! \file pifft_p.h
|
||||
* \brief Class for FFT, IFFT and Hilbert transformations
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "pibroadcast.h"
|
||||
|
||||
/** \class PIBroadcast
|
||||
* @brief Broadcast for all interfaces, including loopback
|
||||
* \brief Broadcast for all interfaces, including loopback
|
||||
*
|
||||
* \section PIBroadcast_synopsis Synopsis
|
||||
* %PIBroadcast used as multichannel IO device. It can use
|
||||
@@ -53,8 +53,6 @@ PIBroadcast::PIBroadcast(bool send_only): PIThread(), PIEthUtilBase() {
|
||||
_started = false;
|
||||
_send_only = send_only;
|
||||
_reinit = true;
|
||||
//initMcast(PIEthernet::allAddresses());
|
||||
PIThread::start(3000);
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +138,6 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
|
||||
piForeachC (PIEthernet::Address & a, al) {
|
||||
PIEthernet * ce = 0;
|
||||
//piCout << "mcast try" << a;
|
||||
|
||||
if (_channels[Multicast]) {
|
||||
ce = new PIEthernet();
|
||||
ce->setDebug(false);
|
||||
@@ -184,7 +181,6 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
|
||||
eth_mcast << ce;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (_channels[Loopback]) {
|
||||
@@ -207,11 +203,14 @@ void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
|
||||
|
||||
|
||||
void PIBroadcast::send(const PIByteArray & data) {
|
||||
if (!isRunning()) {
|
||||
reinit();
|
||||
PIThread::start(3000);
|
||||
}
|
||||
PIByteArray cd = cryptData(data);
|
||||
if (cd.isEmpty()) return;
|
||||
PIMutexLocker ml(mcast_mutex);
|
||||
piForeach (PIEthernet * e, eth_mcast)
|
||||
e->send(cd);
|
||||
piForeach (PIEthernet * e, eth_mcast) e->send(cd);
|
||||
if (eth_lo) {
|
||||
for (int i = 0; i < lo_pcnt; ++i) {
|
||||
eth_lo->send("127.0.0.1", lo_port + i, cd);
|
||||
@@ -221,30 +220,31 @@ void PIBroadcast::send(const PIByteArray & data) {
|
||||
|
||||
|
||||
void PIBroadcast::startRead() {
|
||||
if (!isRunning()) {
|
||||
_started = false;
|
||||
reinit();
|
||||
PIThread::start(3000);
|
||||
}
|
||||
if (_send_only) return;
|
||||
PIMutexLocker ml(mcast_mutex);
|
||||
piForeach (PIEthernet * e, eth_mcast)
|
||||
e->startThreadedRead();
|
||||
if (eth_lo)
|
||||
eth_lo->startThreadedRead();
|
||||
piForeach (PIEthernet * e, eth_mcast) e->startThreadedRead();
|
||||
if (eth_lo) eth_lo->startThreadedRead();
|
||||
_started = true;
|
||||
}
|
||||
|
||||
|
||||
void PIBroadcast::stopRead() {
|
||||
if (isRunning()) stop();
|
||||
PIMutexLocker ml(mcast_mutex);
|
||||
piForeach (PIEthernet * e, eth_mcast)
|
||||
e->stopThreadedRead();
|
||||
if (eth_lo)
|
||||
eth_lo->stopThreadedRead();
|
||||
piForeach (PIEthernet * e, eth_mcast) e->stopThreadedRead();
|
||||
if (eth_lo) eth_lo->stopThreadedRead();
|
||||
_started = false;
|
||||
}
|
||||
|
||||
|
||||
void PIBroadcast::reinit() {
|
||||
initAll(PIEthernet::allAddresses());
|
||||
if (_started)
|
||||
startRead();
|
||||
if (_started) startRead();
|
||||
}
|
||||
|
||||
|
||||
@@ -261,8 +261,6 @@ void PIBroadcast::run() {
|
||||
mcast_mutex.lock();
|
||||
bool r = _reinit, ac = (al != prev_al);
|
||||
mcast_mutex.unlock();
|
||||
if (ac || r)
|
||||
reinit();
|
||||
if (ac)
|
||||
addressesChanged();
|
||||
if (ac || r) reinit();
|
||||
if (ac) addressesChanged();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#endif
|
||||
|
||||
/** \class PIEthUtilBase
|
||||
* @brief Base class for ethernet utils
|
||||
* \brief Base class for ethernet utils
|
||||
*
|
||||
* \section PIEthUtilBase_synopsis Synopsis
|
||||
* %PIEthUtilBase provides crypt layer for derived classes:
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#endif
|
||||
|
||||
/** \class PIStreamPacker
|
||||
* @brief Simple packet wrap aroud any PIIODevice
|
||||
* \brief Simple packet wrap aroud any PIIODevice
|
||||
*
|
||||
* \section PIStreamPacker_synopsis Synopsis
|
||||
* %PIStreamPacker provides simple pack/unpack logic for any data packets.
|
||||
@@ -68,6 +68,13 @@ void PIStreamPacker::setCryptSizeEnabled(bool on) {
|
||||
}
|
||||
|
||||
|
||||
void PIStreamPacker::clear() {
|
||||
packet.clear();
|
||||
packet_size = -1;
|
||||
stream.clear();
|
||||
}
|
||||
|
||||
|
||||
void PIStreamPacker::send(const PIByteArray & data) {
|
||||
if (data.isEmpty()) return;
|
||||
PIByteArray cd;
|
||||
@@ -94,31 +101,12 @@ void PIStreamPacker::send(const PIByteArray & data) {
|
||||
hdr << int(cd.size_s());
|
||||
cd.insert(0, hdr);
|
||||
int pcnt = (cd.size_s() - 1) / max_packet_size + 1, pst = 0;
|
||||
if (pcnt > 1) {
|
||||
prog_s_mutex.lock();
|
||||
prog_s.active = true;
|
||||
prog_s.bytes_all = data.size_s();
|
||||
prog_s.bytes_current = 0;
|
||||
prog_s.progress = 0.;
|
||||
prog_s_mutex.unlock();
|
||||
}
|
||||
for (int i = 0; i < pcnt; ++i) {
|
||||
if (i == pcnt - 1) part = PIByteArray(cd.data(pst), cd.size_s() - pst);
|
||||
else part = PIByteArray(cd.data(pst), max_packet_size);
|
||||
//piCout << "send" << part.size();
|
||||
sendRequest(part);
|
||||
pst += max_packet_size;
|
||||
if (pcnt > 1) {
|
||||
prog_s_mutex.lock();
|
||||
prog_s.bytes_current += part.size_s();
|
||||
prog_s.progress = (double)prog_s.bytes_current / prog_s.bytes_all;
|
||||
prog_s_mutex.unlock();
|
||||
}
|
||||
}
|
||||
if (pcnt > 1) {
|
||||
prog_s_mutex.lock();
|
||||
prog_s.active = false;
|
||||
prog_s_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,22 +154,10 @@ void PIStreamPacker::received(const PIByteArray & data) {
|
||||
packet_size = sz;
|
||||
if (packet_size == 0)
|
||||
packet_size = -1;
|
||||
else {
|
||||
prog_r_mutex.lock();
|
||||
prog_r.active = true;
|
||||
prog_r.bytes_all = packet_size;
|
||||
prog_r.bytes_current = 0;
|
||||
prog_r.progress = 0.;
|
||||
prog_r_mutex.unlock();
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
int ps = piMini(stream.size_s(), packet_size - packet.size_s());
|
||||
packet.append(stream.data(), ps);
|
||||
prog_r_mutex.lock();
|
||||
prog_r.bytes_current = packet.size_s();
|
||||
prog_r.progress = (double)prog_r.bytes_current / piMaxi(1, prog_r.bytes_all);
|
||||
prog_r_mutex.unlock();
|
||||
stream.remove(0, ps);
|
||||
if (packet.size_s() == packet_size) {
|
||||
PIByteArray cd;
|
||||
@@ -211,9 +187,6 @@ void PIStreamPacker::received(const PIByteArray & data) {
|
||||
}
|
||||
packet.clear();
|
||||
packet_size = -1;
|
||||
prog_r_mutex.lock();
|
||||
prog_r.active = false;
|
||||
prog_r_mutex.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,30 +200,3 @@ void PIStreamPacker::assignDevice(PIIODevice * dev) {
|
||||
CONNECTU(dev, threadedReadEvent, this, received);
|
||||
CONNECTU(this, sendRequest, dev, write);
|
||||
}
|
||||
|
||||
|
||||
PIStreamPacker::Progress PIStreamPacker::progressSend() const {
|
||||
PIStreamPacker::Progress ret;
|
||||
prog_s_mutex.lock();
|
||||
ret = prog_s;
|
||||
prog_s_mutex.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIStreamPacker::Progress PIStreamPacker::progressReceive() const {
|
||||
PIStreamPacker::Progress ret;
|
||||
prog_r_mutex.lock();
|
||||
ret = prog_r;
|
||||
prog_r_mutex.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIStreamPacker::Progress::Progress() {
|
||||
active = false;
|
||||
bytes_all = bytes_current = 0;
|
||||
progress = 0.;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file picloudbase.h
|
||||
* @brief PICloud Base - Base class for PICloudClient and PICloud Server
|
||||
/*! \file picloudbase.h
|
||||
* \brief PICloud Base - Base class for PICloudClient and PICloud Server
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file picloudclient.h
|
||||
* @brief PICloud Client
|
||||
/*! \file picloudclient.h
|
||||
* \brief PICloud Client
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "piconditionvar.h"
|
||||
|
||||
|
||||
//! @brief PICloudClient
|
||||
//! \brief PICloudClient
|
||||
|
||||
class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase
|
||||
{
|
||||
@@ -52,12 +52,15 @@ protected:
|
||||
|
||||
private:
|
||||
EVENT_HANDLER1(void, _readed, PIByteArray &, data);
|
||||
void internalDisconnect();
|
||||
|
||||
PIByteArray buff;
|
||||
PIMutex mutex_buff;
|
||||
PIMutex mutex_connect;
|
||||
PIConditionVariable cond_buff;
|
||||
PIConditionVariable cond_connect;
|
||||
std::atomic_bool is_connected;
|
||||
std::atomic_bool is_deleted;
|
||||
};
|
||||
|
||||
#endif // PICLOUDCLIENT_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file picloudserver.h
|
||||
* @brief PICloud Server
|
||||
/*! \file picloudserver.h
|
||||
* \brief PICloud Server
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -78,6 +78,7 @@ private:
|
||||
|
||||
PIVector<Client *> clients_;
|
||||
PIMap<uint, Client *> index_clients;
|
||||
PITimer ping_timer;
|
||||
mutable PIMutex clients_mutex;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file picloudtcp.h
|
||||
* @brief PICloud TCP transport
|
||||
/*! \file picloudtcp.h
|
||||
* \brief PICloud TCP transport
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "pip_cloud_export.h"
|
||||
#include "pistring.h"
|
||||
#include "pimutex.h"
|
||||
|
||||
|
||||
class PIEthernet;
|
||||
@@ -52,6 +53,7 @@ public:
|
||||
Connect = 1,
|
||||
Disconnect = 2,
|
||||
Data = 3,
|
||||
Ping = 4,
|
||||
};
|
||||
|
||||
TCP(PIStreamPacker * s);
|
||||
@@ -65,8 +67,9 @@ public:
|
||||
void sendDisconnected(uint client_id);
|
||||
int sendData(const PIByteArray & data);
|
||||
int sendData(const PIByteArray & data, uint client_id);
|
||||
void sendPing();
|
||||
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba);
|
||||
PIByteArray parseData(PIByteArray & ba);
|
||||
bool canParseData(PIByteArray & ba);
|
||||
PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba);
|
||||
PIByteArray parseConnect_d(PIByteArray & ba);
|
||||
uint parseConnect(PIByteArray & ba);
|
||||
@@ -84,6 +87,8 @@ private:
|
||||
PIByteArray suuid;
|
||||
PIString server_name;
|
||||
PIStreamPacker * streampacker;
|
||||
PIMutex mutex_send;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,14 @@ int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const {
|
||||
}
|
||||
|
||||
|
||||
PIVariantTypes::Enum PICodeInfo::EnumInfo::toPIVariantEnum() {
|
||||
PIVariantTypes::Enum en(name);
|
||||
for (auto m: members) en << m.toPIVariantEnumerator();
|
||||
if (!en.isEmpty()) en.selectValue(members.front().value);
|
||||
return en;
|
||||
}
|
||||
|
||||
|
||||
PIMap<PIString, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
|
||||
PIMap<PIString, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;
|
||||
PIMap<PIString, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file picodeinfo.h
|
||||
* @brief C++ code info structs
|
||||
/*! \file picodeinfo.h
|
||||
* \brief C++ code info structs
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -25,6 +25,8 @@
|
||||
#define PICODEINFO_H
|
||||
|
||||
#include "pistringlist.h"
|
||||
#include "pivarianttypes.h"
|
||||
|
||||
|
||||
class PIVariant;
|
||||
|
||||
@@ -77,6 +79,7 @@ struct PIP_EXPORT ClassInfo {
|
||||
|
||||
struct PIP_EXPORT EnumeratorInfo {
|
||||
EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;}
|
||||
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name);}
|
||||
MetaMap meta;
|
||||
PIString name;
|
||||
int value;
|
||||
@@ -85,6 +88,7 @@ struct PIP_EXPORT EnumeratorInfo {
|
||||
struct PIP_EXPORT EnumInfo {
|
||||
PIString memberName(int value) const;
|
||||
int memberValue(const PIString & name) const;
|
||||
PIVariantTypes::Enum toPIVariantEnum();
|
||||
MetaMap meta;
|
||||
PIString name;
|
||||
PIVector<PICodeInfo::EnumeratorInfo> members;
|
||||
|
||||
@@ -51,7 +51,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
|
||||
const PIString & an(args[i]), av(arg_vals[i]);
|
||||
int ind(-1);
|
||||
while ((ind = ret.find(an, ind + 1)) >= 0) {
|
||||
PIChar ppc(0), pc(0), nc(0);
|
||||
PIChar ppc, pc, nc;
|
||||
if (ind > 1) ppc = ret[ind - 2];
|
||||
if (ind > 0) pc = ret[ind - 1];
|
||||
if (ind + an.size_s() < ret.size_s()) nc = ret.mid(ind + an.size_s(),1)[0];
|
||||
@@ -190,10 +190,39 @@ void PICodeParser::clear() {
|
||||
piForeachC (PIString & d, defs)
|
||||
defines << Define(d, "");
|
||||
defines << Define(PIStringAscii("PICODE"), "") << custom_defines;
|
||||
macros << Macro(PIStringAscii("PIOBJECT"), "", PIStringList() << "name")
|
||||
<< Macro(PIStringAscii("PIOBJECT_PARENT"), "", PIStringList() << "parent")
|
||||
<< Macro(PIStringAscii("PIOBJECT_SUBCLASS"), "", PIStringList() << "name" << "parent")
|
||||
<< Macro(PIStringAscii("PIIODEVICE"), "", PIStringList() << "name")
|
||||
<< Macro(PIStringAscii("NO_COPY_CLASS"), "", PIStringList() << "name")
|
||||
<< Macro(PIStringAscii("PRIVATE_DECLARATION"))
|
||||
|
||||
<< Macro(PIStringAscii("EVENT" ), "void name();", PIStringList() << "name")
|
||||
<< Macro(PIStringAscii("EVENT0"), "void name();", PIStringList() << "name")
|
||||
<< Macro(PIStringAscii("EVENT1"), "void name(a0 n0);", PIStringList() << "name" << "a0" << "n0")
|
||||
<< Macro(PIStringAscii("EVENT2"), "void name(a0 n0, a1 n1);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1")
|
||||
<< Macro(PIStringAscii("EVENT3"), "void name(a0 n0, a1 n1, a2 n2);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
|
||||
<< Macro(PIStringAscii("EVENT4"), "void name(a0 n0, a1 n1, a2 n2, a3 n3);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
|
||||
|
||||
<< Macro(PIStringAscii("EVENT_HANDLER" ), "ret name()", PIStringList() << "ret" << "name")
|
||||
<< Macro(PIStringAscii("EVENT_HANDLER0"), "ret name()", PIStringList() << "ret" << "name")
|
||||
<< Macro(PIStringAscii("EVENT_HANDLER1"), "ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
|
||||
<< Macro(PIStringAscii("EVENT_HANDLER2"), "ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
|
||||
<< Macro(PIStringAscii("EVENT_HANDLER3"), "ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
|
||||
<< Macro(PIStringAscii("EVENT_HANDLER4"), "ret name(a0 n0, a1 n1, a2 n2, a3 n3)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
|
||||
|
||||
<< Macro(PIStringAscii("EVENT_VHANDLER" ), "virtual ret name()", PIStringList() << "ret" << "name")
|
||||
<< Macro(PIStringAscii("EVENT_VHANDLER0"), "virtual ret name()", PIStringList() << "ret" << "name")
|
||||
<< Macro(PIStringAscii("EVENT_VHANDLER1"), "virtual ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
|
||||
<< Macro(PIStringAscii("EVENT_VHANDLER2"), "virtual ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
|
||||
<< Macro(PIStringAscii("EVENT_VHANDLER3"), "virtual ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
|
||||
<< Macro(PIStringAscii("EVENT_VHANDLER4"), "virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
||||
static const PIString s_ns = PIStringAscii("::");
|
||||
static const PIString s_bo = PIStringAscii("{\n");
|
||||
static const PIString s_bc = PIStringAscii("\n}\n");
|
||||
static const PIString s_class = PIStringAscii("class");
|
||||
@@ -250,7 +279,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
||||
piForeachC (Define & d, defines) {
|
||||
int ind(-1);
|
||||
while ((ind = pfc.find(d.first, ind + 1)) >= 0) {
|
||||
PIChar pc(0), nc(0);
|
||||
PIChar pc, nc;
|
||||
if (ind > 0) pc = pfc[ind - 1];
|
||||
if (ind + d.first.size_s() < pfc.size_s()) nc = pfc.mid(ind + d.first.size_s(),1)[0];
|
||||
if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue;
|
||||
@@ -262,7 +291,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
||||
piForeachC (Macro & m, macros) {
|
||||
int ind(-1);
|
||||
while ((ind = pfc.find(m.name, ind + 1)) >= 0) {
|
||||
PIChar pc(0), nc(0);
|
||||
PIChar pc, nc;
|
||||
if (ind > 0) pc = pfc[ind - 1];
|
||||
if (ind + m.name.size_s() < pfc.size_s()) nc = pfc.mid(ind + m.name.size_s(),1)[0];
|
||||
if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue;
|
||||
@@ -280,7 +309,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
||||
|
||||
replaceMeta(pfc);
|
||||
|
||||
//piCout << NewLine << "file" << cur_file << pfc;
|
||||
//piCout << PICoutManipulators::NewLine << "file" << cur_file << pfc;
|
||||
int pl = -1;
|
||||
while (!pfc.isEmpty()) {
|
||||
pfc.trim();
|
||||
@@ -288,7 +317,12 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
||||
if (pl == nl) break;
|
||||
pl = nl;
|
||||
if (pfc.left(9) == s_namespace) {
|
||||
pfc.cutLeft(pfc.find('{') + 1);
|
||||
pfc.cutLeft(9);
|
||||
PIString prev_namespace = cur_namespace, ccmn;
|
||||
cur_namespace += pfc.takeCWord() + s_ns;
|
||||
ccmn = pfc.takeRange('{', '}');
|
||||
parseClass(0, ccmn, true);
|
||||
cur_namespace = prev_namespace;
|
||||
continue;
|
||||
}
|
||||
if (pfc.left(8) == s_template) {
|
||||
@@ -306,7 +340,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
||||
if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;}
|
||||
ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
|
||||
pfc.remove(0, ccmn.size());
|
||||
parseClass(0, ccmn);
|
||||
parseClass(0, ccmn, false);
|
||||
continue;
|
||||
}
|
||||
if (pfc.left(4) == s_enum) {
|
||||
@@ -391,7 +425,7 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
|
||||
}
|
||||
|
||||
|
||||
PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
|
||||
void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace) {
|
||||
static const PIString s_ns = PIStringAscii("::");
|
||||
static const PIString s_public = PIStringAscii("public");
|
||||
static const PIString s_protected = PIStringAscii("protected");
|
||||
@@ -402,22 +436,31 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
|
||||
static const PIString s_enum = PIStringAscii("enum");
|
||||
static const PIString s_friend = PIStringAscii("friend");
|
||||
static const PIString s_typedef = PIStringAscii("typedef");
|
||||
static const PIString s_namespace = PIStringAscii("namespace");
|
||||
static const PIString s_template = PIStringAscii("template");
|
||||
Visibility prev_vis = cur_def_vis;
|
||||
int dind = fc.find('{'), find = fc.find(';'), end = 0;
|
||||
if (dind < 0 && find < 0) return PIString();
|
||||
if (dind < 0 || find < dind) return fc.left(find);
|
||||
//piCout << "parse class <****\n" << fc.left(20) << "\n****>";
|
||||
Entity * ce = parseClassDeclaration(fc.takeLeft(dind));
|
||||
fc.trim().cutLeft(1).cutRight(1).trim();
|
||||
if (dind < 0 && find < 0) return;
|
||||
if (dind < 0 || find < dind) {
|
||||
fc.left(find);
|
||||
return;
|
||||
}
|
||||
//piCout << "parse class <****\n" << fc << "\n****>";
|
||||
Entity * ce = parent;
|
||||
if (!is_namespace) {
|
||||
ce = parseClassDeclaration(fc.takeLeft(dind));
|
||||
fc.trim().cutLeft(1).cutRight(1).trim();
|
||||
}
|
||||
//piCout << "found class <****\n" << fc << "\n****>";
|
||||
if (!ce) return PIString();
|
||||
if (parent) parent->children << ce;
|
||||
ce->parent_scope = parent;
|
||||
///if (!ce) return PIString();
|
||||
if (ce) {
|
||||
if (parent) parent->children << ce;
|
||||
ce->parent_scope = parent;
|
||||
}
|
||||
int ps = -1;
|
||||
bool def = false;
|
||||
PIString prev_namespace = cur_namespace, stmp;
|
||||
cur_namespace = ce->name + s_ns;
|
||||
if (ce) cur_namespace += ce->name + s_ns;
|
||||
//piCout << "parse class" << ce->name << "namespace" << cur_namespace;
|
||||
//piCout << "\nparse class" << ce->name << "namespace" << cur_namespace;
|
||||
while (!fc.isEmpty()) {
|
||||
@@ -426,6 +469,14 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
|
||||
if (cw == s_public ) {cur_def_vis = Public; fc.cutLeft(1); continue;}
|
||||
if (cw == s_protected) {cur_def_vis = Protected; fc.cutLeft(1); continue;}
|
||||
if (cw == s_private ) {cur_def_vis = Private; fc.cutLeft(1); continue;}
|
||||
if (cw == s_namespace) {
|
||||
PIString prev_namespace = cur_namespace, ccmn;
|
||||
cur_namespace += fc.takeCWord() + s_ns;
|
||||
ccmn = fc.takeRange('{', '}');
|
||||
parseClass(ce, ccmn, true);
|
||||
cur_namespace = prev_namespace;
|
||||
continue;
|
||||
}
|
||||
if (cw == s_class || cw == s_struct || cw == s_union) {
|
||||
if (isDeclaration(fc, 0, &end)) {
|
||||
fc.cutLeft(end);
|
||||
@@ -436,7 +487,7 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
|
||||
stmp = fc.takeRange('{', '}');
|
||||
fc.takeSymbol();
|
||||
stmp = cw + ' ' + tmp + '{' + stmp + '}';
|
||||
parseClass(ce, stmp);
|
||||
parseClass(ce, stmp, false);
|
||||
continue;
|
||||
}
|
||||
if (cw == s_enum) {
|
||||
@@ -449,11 +500,13 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
|
||||
}
|
||||
if (cw == s_friend) {fc.cutLeft(fc.find(';') + 1); continue;}
|
||||
if (cw == s_typedef) {
|
||||
ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';')));
|
||||
typedefs << ce->typedefs.back();
|
||||
typedefs.back().first.insert(0, cur_namespace);
|
||||
if (ce->typedefs.back().first.isEmpty())
|
||||
ce->typedefs.pop_back();
|
||||
if (ce) {
|
||||
ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';')));
|
||||
typedefs << ce->typedefs.back();
|
||||
typedefs.back().first.insert(0, cur_namespace);
|
||||
if (ce->typedefs.back().first.isEmpty())
|
||||
ce->typedefs.pop_back();
|
||||
}
|
||||
fc.takeSymbol();
|
||||
continue;
|
||||
}
|
||||
@@ -467,7 +520,7 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
|
||||
}
|
||||
def = !isDeclaration(fc, 0, &end);
|
||||
tmp = (cw + fc.takeLeft(end)).trim();
|
||||
if (!tmp.isEmpty())
|
||||
if (!tmp.isEmpty() && ce)
|
||||
parseMember(ce, tmp);
|
||||
if (def) fc.takeRange('{', '}');
|
||||
else fc.takeSymbol();
|
||||
@@ -476,7 +529,6 @@ PIString PICodeParser::parseClass(Entity * parent, PIString & fc) {
|
||||
}
|
||||
cur_def_vis = prev_vis;
|
||||
cur_namespace = prev_namespace;
|
||||
return ce->name;
|
||||
}
|
||||
|
||||
|
||||
@@ -1052,10 +1104,10 @@ PIString PICodeParser::procMacros(PIString fc) {
|
||||
|
||||
|
||||
bool PICodeParser::parseDirective(PIString d) {
|
||||
static const PIString s_include = PIStringAscii("include");
|
||||
static const PIString s_define = PIStringAscii("define");
|
||||
static const PIString s_undef = PIStringAscii("undef");
|
||||
static const PIString s_PIMETA = PIStringAscii("PIMETA");
|
||||
static const PIString s_include = PIStringAscii("include");
|
||||
static const PIString s_define = PIStringAscii("define");
|
||||
static const PIString s_undef = PIStringAscii("undef");
|
||||
static const PIString s_PIMETA = PIStringAscii("PIMETA");
|
||||
if (d.isEmpty()) return true;
|
||||
PIString dname = d.takeCWord();
|
||||
//piCout << "parseDirective" << d;
|
||||
@@ -1074,9 +1126,19 @@ bool PICodeParser::parseDirective(PIString d) {
|
||||
if (mname == s_PIMETA) return true;
|
||||
if (d.left(1) == PIChar('(')) { // macro
|
||||
PIStringList args = d.takeRange('(', ')').split(',').trim();
|
||||
for (int i = 0; i < macros.size_s(); ++i)
|
||||
if (macros[i].name == mname) {
|
||||
macros.remove(i);
|
||||
break;
|
||||
}
|
||||
macros << Macro(mname, d.trim(), args);
|
||||
} else { // define
|
||||
d.trim();
|
||||
for (int i = 0; i < defines.size_s(); ++i)
|
||||
if (defines[i].first == mname) {
|
||||
defines.remove(i);
|
||||
break;
|
||||
}
|
||||
defines << Define(mname, d);
|
||||
evaluator.setVariable(mname, complexd_1);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*! @file picodeparser.h
|
||||
* @brief C++ code parser
|
||||
*/
|
||||
/*! \file picodeparser.h
|
||||
* \ingroup Code
|
||||
* \~\brief
|
||||
* \~english C++ code parser
|
||||
* \~russian Разбор C++ кода
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
C++ code parser
|
||||
@@ -148,7 +151,7 @@ private:
|
||||
bool parseFileContent(PIString & fc, bool main);
|
||||
bool parseDirective(PIString d);
|
||||
Entity * parseClassDeclaration(const PIString & fc);
|
||||
PIString parseClass(Entity * parent, PIString & fc);
|
||||
void parseClass(Entity * parent, PIString & fc, bool is_namespace);
|
||||
MetaMap parseMeta(PIString & fc);
|
||||
bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta);
|
||||
Typedef parseTypedef(PIString fc);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file picompress.h
|
||||
* @brief Compress class using zlib
|
||||
/*! \file picompress.h
|
||||
* \brief Compress class using zlib
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
#ifndef WINDOWS
|
||||
# include <termios.h>
|
||||
#else
|
||||
# include <wingdi.h>
|
||||
# include <wincon.h>
|
||||
#endif
|
||||
|
||||
/** \class PIKbdListener
|
||||
* @brief Keyboard console input listener
|
||||
* \brief Keyboard console input listener
|
||||
* \details This class provide listening of console keyboard input.
|
||||
* There is two ways to receive pressed key:
|
||||
* * external static function with format "void func(char key, void * data_)"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pikbdlistener.h
|
||||
* @brief Keyboard console input listener
|
||||
/*! \file pikbdlistener.h
|
||||
* \brief Keyboard console input listener
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "pithread.h"
|
||||
|
||||
#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) piMSleep(PIP_MIN_MSLEEP*5);
|
||||
#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) piMSleep(PIP_MIN_MSLEEP*5); // TODO: rewrite with condvar
|
||||
|
||||
|
||||
class PIP_EXPORT PIKbdListener: public PIThread
|
||||
@@ -181,20 +181,20 @@ public:
|
||||
//! \{
|
||||
|
||||
//! \fn void enableExitCapture(int key = 'Q')
|
||||
//! @brief Enable exit key "key" awaiting
|
||||
//! \brief Enable exit key "key" awaiting
|
||||
|
||||
//! \fn void disableExitCapture()
|
||||
//! @brief Disable exit key awaiting
|
||||
//! \brief Disable exit key awaiting
|
||||
|
||||
//! \fn void setActive(bool yes = true)
|
||||
//! @brief Set keyboard listening is active or not
|
||||
//! \brief Set keyboard listening is active or not
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
|
||||
//! @brief Raise on key "key" pressed, "data" is custom data
|
||||
//! \brief Raise on key "key" pressed, "data" is custom data
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piscreen.h
|
||||
* @brief Console GUI class
|
||||
/*! \file piscreen.h
|
||||
* \brief Console GUI class
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -80,23 +80,23 @@ public:
|
||||
//! \{
|
||||
|
||||
//! \fn void waitForFinish()
|
||||
//! @brief block until finished (exit key will be pressed)
|
||||
//! \brief block until finished (exit key will be pressed)
|
||||
|
||||
//! \fn void start(bool wait = false)
|
||||
//! @brief Start console output and if "wait" block until finished (exit key will be pressed)
|
||||
//! \brief Start console output and if "wait" block until finished (exit key will be pressed)
|
||||
|
||||
//! \fn void stop(bool clear = false)
|
||||
//! @brief Stop console output and if "clear" clear the screen
|
||||
//! \brief Stop console output and if "clear" clear the screen
|
||||
|
||||
//! \}
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
//! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data)
|
||||
//! @brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
|
||||
//! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object
|
||||
|
||||
//! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e)
|
||||
//! @brief Raise on some event "e" from tile "tile"
|
||||
//! \brief Raise on some event "e" from tile "tile"
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piscreenconsole.h
|
||||
* @brief Tile for PIScreen with PIConsole API
|
||||
/*! \file piscreenconsole.h
|
||||
* \brief Tile for PIScreen with PIConsole API
|
||||
*
|
||||
* This file declares TileVars
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piscreendrawer.h
|
||||
* @brief Drawer for PIScreen
|
||||
/*! \file piscreendrawer.h
|
||||
* \brief Drawer for PIScreen
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piscreentile.h
|
||||
* @brief Basic PIScreen tile
|
||||
/*! \file piscreentile.h
|
||||
* \brief Basic PIScreen tile
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piscreentiles.h
|
||||
* @brief Various tiles for PIScreen
|
||||
/*! \file piscreentiles.h
|
||||
* \brief Various tiles for PIScreen
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piscreentypes.h
|
||||
* @brief Types for PIScreen
|
||||
/*! \file piscreentypes.h
|
||||
* \brief Types for PIScreen
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piterminal.h
|
||||
* @brief Virtual terminal
|
||||
/*! \file piterminal.h
|
||||
* \brief Virtual terminal
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
/*! @file picontainers.h
|
||||
* @brief Base for generic containers
|
||||
*
|
||||
* This file declare all containers and useful macros
|
||||
* to use them
|
||||
*/
|
||||
/*! \addtogroup Containers
|
||||
* \{
|
||||
* \file picontainers.h
|
||||
* \brief
|
||||
* \~english Base macros for generic containers
|
||||
* \~russian Базовые макросы для контейнеров
|
||||
* \~\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
|
||||
Base for generic containers
|
||||
Base macros for generic containers
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -37,87 +45,122 @@
|
||||
#include <type_traits>
|
||||
#include <string.h>
|
||||
#include <new>
|
||||
#ifndef PIP_MEMALIGN_BYTES
|
||||
# define PIP_MEMALIGN_BYTES (sizeof(void*)*4)
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
# ifdef CC_GCC
|
||||
# define amalloc(s) __mingw_aligned_malloc(s, PIP_MEMALIGN_BYTES)
|
||||
# define afree(p) __mingw_aligned_free(p)
|
||||
# else
|
||||
# ifdef CC_VC
|
||||
# define amalloc(s) _aligned_malloc(s, PIP_MEMALIGN_BYTES)
|
||||
# define afree(p) _aligned_free(p)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# define amalloc(s) aligned_alloc(PIP_MEMALIGN_BYTES, s)
|
||||
# define afree(p) free(p)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
/*!@brief Macro for iterate any container
|
||||
* \details Use this macros instead of standard "for"
|
||||
* to get read/write access to each element of container.
|
||||
* Pass direction is direct \n
|
||||
* Example: \snippet picontainers.cpp foreach
|
||||
*/
|
||||
# define piForeach(i,c)
|
||||
|
||||
/*!@brief Macro for iterate any container only for read
|
||||
* \details Use this macros instead of standard "for"
|
||||
* to get read access to each element of container.
|
||||
* Pass direction is direct \n
|
||||
* Example: \snippet picontainers.cpp foreachC
|
||||
*/
|
||||
# define piForeachC(i,c)
|
||||
|
||||
/*!@brief Macro for iterate any container with reverse direction
|
||||
* \details Use this macros instead of standard "for"
|
||||
* to get read/write access to each element of container.
|
||||
* Pass direction is reverse \n
|
||||
* Example: \snippet picontainers.cpp foreachR
|
||||
*/
|
||||
# define piForeachR(i,c)
|
||||
|
||||
/*!@brief Macro for iterate any container only for read with reverse direction
|
||||
* \details Use this macros instead of standard "for"
|
||||
* to get read access to each element of container.
|
||||
* Pass direction is reverse \n
|
||||
* Example: \snippet picontainers.cpp foreachCR
|
||||
*/
|
||||
# define piForeachCR(i,c)
|
||||
|
||||
#else
|
||||
|
||||
|
||||
template <typename C>
|
||||
struct _reverse_wrapper {
|
||||
C & c_;
|
||||
_reverse_wrapper(C & c): c_(c) {}
|
||||
_reverse_wrapper(const C & c): c_(const_cast<C&>(c)) {}
|
||||
class _PIReverseWrapper {
|
||||
public:
|
||||
_PIReverseWrapper(C & c): c_(c) {}
|
||||
_PIReverseWrapper(const C & c): c_(const_cast<C&>(c)) {}
|
||||
typename C::reverse_iterator begin() {return c_.rbegin();}
|
||||
typename C::reverse_iterator end() {return c_.rend(); }
|
||||
typename C::const_reverse_iterator begin() const {return c_.rbegin();}
|
||||
typename C::const_reverse_iterator end() const {return c_.rend(); }
|
||||
private:
|
||||
C & c_;
|
||||
};
|
||||
|
||||
template <typename C> _reverse_wrapper<C> _reverse_wrap(C & c) {return _reverse_wrapper<C>(c);}
|
||||
template <typename C> _reverse_wrapper<C> _reverse_wrap(const C & c) {return _reverse_wrapper<C>(c);}
|
||||
|
||||
/*! \brief
|
||||
* \~english Template reverse wrapper over any container
|
||||
* \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
|
||||
*/
|
||||
template <typename C> _PIReverseWrapper<C> PIReverseWrap(C & c) {return _PIReverseWrapper<C>(c);}
|
||||
template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _PIReverseWrapper<C>(c);}
|
||||
|
||||
|
||||
# define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
|
||||
/*! \brief
|
||||
* \~english Macro for short replacement of standart "for"
|
||||
* \~russian Макрос для короткой записи стандартного цикла "for"
|
||||
* \~\param c
|
||||
* \~english Iteration times in loop
|
||||
* \~russian Количество итераций цикла
|
||||
*/
|
||||
#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
|
||||
|
||||
# define piForeach(i,c) for(i : c)
|
||||
# define piForeachC(i,c) for(const i : c)
|
||||
# define piForeachR(i,c) for(i : _reverse_wrap(c))
|
||||
# define piForeachRC(i,c) for(const i : _reverse_wrap(c))
|
||||
|
||||
# define piForeachCR piForeachRC
|
||||
/*! \brief
|
||||
* \~english Macro for iterate any container
|
||||
* \~russian Макрос для перебора любых контейнеров
|
||||
* \~\deprecated
|
||||
* \~english Deprecated, using only for backward compatibility. Use
|
||||
* [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
|
||||
* \~russian Устарело, используется только для обратной совместимости. Используйте
|
||||
* [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
|
||||
* \~\details
|
||||
* \~english Get read/write access to each element of container.
|
||||
* Iterating in forward direction.
|
||||
* Example of using:
|
||||
* \~russian Перебор всех элементов контейнера с доступом на чтение и запись.
|
||||
* Перебор осуществляется в прямом порядке.
|
||||
* Пример использования:
|
||||
* \~\code
|
||||
* PIVector<int> vec;
|
||||
* vec << 1 << 2 << 3;
|
||||
* piForeach(int & i, vec) piCout << i;
|
||||
* // 1
|
||||
* // 2
|
||||
* // 3
|
||||
* piForeach(int & i, vec) i++;
|
||||
* piForeach(int & i, vec) piCout << i;
|
||||
* // 2
|
||||
* // 3
|
||||
* // 4
|
||||
* \endcode
|
||||
* \sa \a piForeachC, \a piForeachR, \a piForeachRC
|
||||
*/
|
||||
#define piForeach(i, c) for(i : c)
|
||||
|
||||
#endif // DOXYGEN
|
||||
/*! \brief
|
||||
* \~english Macro for iterate any container
|
||||
* \~russian Макрос для перебора любых контейнеров
|
||||
* \~\deprecated
|
||||
* \~english Deprecated, using only for backward compatibility. Use
|
||||
* [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
|
||||
* \~russian Устарело, используется только для обратной совместимости. Используйте
|
||||
* [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
|
||||
* \~\details
|
||||
* \~english Get read only access to each element of container.
|
||||
* Iterating in forward direction.
|
||||
* \~russian Перебор всех элементов контейнера с доступом только на чтение.
|
||||
* Перебор осуществляется в прямом порядке.
|
||||
* \~ \sa \a piForeach, \a piForeachR, \a piForeachRC
|
||||
*/
|
||||
#define piForeachC(i, c) for(const i : c)
|
||||
|
||||
/*! \brief
|
||||
* \~english Macro for iterate any container
|
||||
* \~russian Макрос для перебора любых контейнеров
|
||||
* \~\deprecated
|
||||
* \~english Deprecated, using only for backward compatibility. Use
|
||||
* [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
|
||||
* \~russian Устарело, используется только для обратной совместимости. Используйте
|
||||
* [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
|
||||
* \~\details
|
||||
* \~english Get read/write access to each element of container.
|
||||
* Iterating in backward direction.
|
||||
* \~russian Перебор всех элементов контейнера с доступом на чтение и запись.
|
||||
* Перебор осуществляется в обратном порядке.
|
||||
* \~ \sa \a piForeach, \a piForeachC, \a piForeachRC
|
||||
*/
|
||||
#define piForeachR(i, c) for(i : PIReverseWrap(c))
|
||||
|
||||
/*! \brief
|
||||
* \~english Macro for iterate any container
|
||||
* \~russian Макрос для перебора любых контейнеров
|
||||
* \~\deprecated
|
||||
* \~english Deprecated, using only for backward compatibility. Use
|
||||
* [C++ Range-based for loop](https://en.cppreference.com/w/cpp/language/range-for).
|
||||
* \~russian Устарело, используется только для обратной совместимости. Используйте
|
||||
* [C++ Range-based for loop](https://ru.cppreference.com/w/cpp/language/range-for).
|
||||
* \~\details
|
||||
* \~english Get read only access to each element of container.
|
||||
* Iterating in backward direction. Also has alias **piForeachCR**
|
||||
* \~russian Перебор всех элементов контейнера с доступом только на чтение.
|
||||
* Перебор осуществляется в обратном порядке. Также можно писать **piForeachCR**
|
||||
* \~ \sa \a piForeach, \a piForeachC, \a piForeachR
|
||||
*/
|
||||
#define piForeachRC(i, c) for(const i : PIReverseWrap(c))
|
||||
#define piForeachCR piForeachRC
|
||||
|
||||
#endif // PICONTAINERS_H
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Module includes
|
||||
Containers
|
||||
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -16,6 +16,30 @@
|
||||
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/>.
|
||||
*/
|
||||
/** \defgroup Containers
|
||||
* \~\brief
|
||||
* \~english This module contains various standart containers realization.
|
||||
* \~russian Модуль содержит основные классы контейнеров.
|
||||
*
|
||||
* \~\details
|
||||
* Scope | Use
|
||||
* ----- | -------
|
||||
* C++ | #include <picontainersmodule.h>
|
||||
* CMake | PIP
|
||||
*
|
||||
* \~english This includes
|
||||
* \~russian В него входят
|
||||
* \~ \a PIVector, \a PIDeque, \a PIMap, \a PISet,
|
||||
* \a PIStack, \a PIQueue, \a PIPair, \a PIVector2D.
|
||||
*
|
||||
* \authors
|
||||
* \~english
|
||||
* Ivan Pelipenko peri4ko@yandex.ru;
|
||||
* Andrey Bychkov work.a.b@yandex.ru;
|
||||
* \~russian
|
||||
* Иван Пелипенко peri4ko@yandex.ru;
|
||||
* Андрей Бычков work.a.b@yandex.ru;
|
||||
*/
|
||||
|
||||
#ifndef PICONTAINERSMODULE_H
|
||||
#define PICONTAINERSMODULE_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pideque.h
|
||||
* @brief Dynamic array of any type
|
||||
/*! \file pideque.h
|
||||
* \brief Dynamic array of any type
|
||||
*
|
||||
* This file declares PIDeque
|
||||
*/
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
resize(pid_size, f);
|
||||
}
|
||||
inline PIDeque(size_t piv_size, std::function<T(size_t)> f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||
inline PIDeque(size_t piv_size, std::function<T(size_t i)> f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
resize(piv_size, f);
|
||||
}
|
||||
@@ -174,6 +174,20 @@ public:
|
||||
inline size_t capacity() const {return pid_rsize;}
|
||||
inline size_t _start() const {return pid_start;}
|
||||
inline bool isEmpty() const {return (pid_size == 0);}
|
||||
inline bool isNotEmpty() const {return (pid_size > 0);}
|
||||
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) {
|
||||
if (test(pid_data[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
if (!test(pid_data[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline T & operator [](size_t index) {return pid_data[pid_start + index];}
|
||||
inline const T & operator [](size_t index) const {return pid_data[pid_start + index];}
|
||||
@@ -182,48 +196,102 @@ public:
|
||||
inline const T & back() const {return pid_data[pid_start + pid_size - 1];}
|
||||
inline T & front() {return pid_data[pid_start];}
|
||||
inline const T & front() const {return pid_data[pid_start];}
|
||||
inline bool operator ==(const PIDeque<T> & t) const {
|
||||
if (pid_size != t.pid_size) return false;
|
||||
for (size_t i = 0; i < pid_size; ++i)
|
||||
if (t[i] != (*this)[i])
|
||||
inline bool operator ==(const PIDeque<T> & v) const {
|
||||
if (pid_size != v.pid_size) return false;
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
if (v[i] != (*this)[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline bool operator !=(const PIDeque<T> & t) const {return !(*this == t);}
|
||||
inline bool operator >(const PIDeque<T> & t) const {
|
||||
if (pid_size != t.pid_size) return pid_size > t.pid_size;
|
||||
for (size_t i = 0; i < pid_size; ++i)
|
||||
if (t[i] != (*this)[i]) return t[i] > (*this)[i];
|
||||
inline bool operator !=(const PIDeque<T> & v) const {return !(*this == v);}
|
||||
inline bool operator <(const PIDeque<T> & v) const {
|
||||
if (pid_size != v.pid_size) return pid_size < v.pid_size;
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
if ((*this)[i] != v[i]) return (*this)[i] < v[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool contains(const T & v) const {
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i)
|
||||
if (v == pid_data[i])
|
||||
inline bool operator >(const PIDeque<T> & v) const {
|
||||
if (pid_size != v.pid_size) return pid_size > v.pid_size;
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
if ((*this)[i] != v[i]) return (*this)[i] > v[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool contains(const T & e) const {
|
||||
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
if (e == pid_data[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline int etries(const T & v) const {
|
||||
inline int etries(const T & e, size_t start = 0) const {
|
||||
int ec = 0;
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i)
|
||||
if (v == pid_data[i]) ++ec;
|
||||
if (start >= pid_size) return ec;
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
if (e == pid_data[i]) ++ec;
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
inline ssize_t indexOf(const T & v) const {
|
||||
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i)
|
||||
if (v == pid_data[i])
|
||||
inline int etries(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||
int ec = 0;
|
||||
if (start >= pid_size) return ec;
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
if (test(pid_data[i])) ++ec;
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
inline ssize_t indexOf(const T & e, size_t start = 0) const {
|
||||
if (start >= pid_size) return -1;
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
if (e == pid_data[i]) {
|
||||
return i - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline ssize_t lastIndexOf(const T & v) const {
|
||||
for (ssize_t i = pid_start + (ssize_t)pid_size - 1; i >= pid_start; --i)
|
||||
if (v == pid_data[i])
|
||||
inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||
if (start >= pid_size) return -1;
|
||||
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||
if (test(pid_data[i])) {
|
||||
return i - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
|
||||
if (start < 0) start = pid_size - 1;
|
||||
else start = piMin<ssize_t>(pid_size - 1, start);
|
||||
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
|
||||
if (e == pid_data[i]) {
|
||||
return i - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
|
||||
if (start < 0) start = pid_size - 1;
|
||||
else start = piMin<ssize_t>(pid_size - 1, start);
|
||||
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
|
||||
if (test(pid_data[i])) {
|
||||
return i - pid_start;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline T * data(size_t index = 0) {return &(pid_data[pid_start + index]);}
|
||||
inline const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);}
|
||||
|
||||
PIDeque<T> getRange(size_t index, size_t count) const {
|
||||
if (index >= pid_size || count == 0) return PIDeque<T>();
|
||||
if (index + count > pid_size) count = pid_size - index;
|
||||
return PIDeque(&(pid_data[pid_start + index]), count);
|
||||
}
|
||||
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
@@ -244,15 +312,17 @@ public:
|
||||
inline PIDeque<T> & fill(const T & f = T()) {
|
||||
deleteT(pid_data + pid_start, pid_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, pid_size)
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i)
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
||||
elementNew(pid_data + i, f);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & fill(std::function<T(size_t)> f) {
|
||||
inline PIDeque<T> & fill(std::function<T(size_t i)> f) {
|
||||
deleteT(pid_data + pid_start, pid_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, pid_size)
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i)
|
||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
||||
elementNew(pid_data + i, f(i));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & assign(const T & f = T()) {return fill(f);}
|
||||
@@ -275,31 +345,35 @@ public:
|
||||
if (new_size < pid_size) {
|
||||
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
|
||||
pid_size = new_size;
|
||||
if (new_size == 0)
|
||||
if (new_size == 0) {
|
||||
pid_start = (pid_rsize - pid_size) / 2;
|
||||
}
|
||||
}
|
||||
if (new_size > pid_size) {
|
||||
size_t os = pid_size;
|
||||
alloc(new_size, true);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||
for (size_t i = os + pid_start; i < new_size + pid_start; ++i)
|
||||
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
|
||||
elementNew(pid_data + i, f);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t)> f) {
|
||||
inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
|
||||
if (new_size < pid_size) {
|
||||
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
|
||||
pid_size = new_size;
|
||||
if (new_size == 0)
|
||||
if (new_size == 0) {
|
||||
pid_start = (pid_rsize - pid_size) / 2;
|
||||
}
|
||||
}
|
||||
if (new_size > pid_size) {
|
||||
size_t os = pid_size;
|
||||
alloc(new_size, true);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||
for (size_t i = os + pid_start; i < new_size + pid_start; ++i)
|
||||
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
|
||||
elementNew(pid_data + i, f(i));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -326,8 +400,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIDeque<T> & insert(size_t index, const T & v = T()) {
|
||||
if (index == pid_size) return push_back(v);
|
||||
inline PIDeque<T> & insert(size_t index, const T & e = T()) {
|
||||
if (index == pid_size) return push_back(e);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||
if (dir) {
|
||||
@@ -338,14 +412,15 @@ public:
|
||||
}
|
||||
} else {
|
||||
alloc(pid_size + 1, false, -1);
|
||||
if (index > 0)
|
||||
if (index > 0) {
|
||||
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
|
||||
}
|
||||
}
|
||||
elementNew(pid_data + pid_start + index, v);
|
||||
elementNew(pid_data + pid_start + index, e);
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & insert(size_t index, T && v) {
|
||||
if (index == pid_size) return push_back(v);
|
||||
inline PIDeque<T> & insert(size_t index, T && e) {
|
||||
if (index == pid_size) return push_back(e);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||
if (dir) {
|
||||
@@ -356,10 +431,11 @@ public:
|
||||
}
|
||||
} else {
|
||||
alloc(pid_size + 1, false, -1);
|
||||
if (index > 0)
|
||||
if (index > 0) {
|
||||
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
|
||||
}
|
||||
}
|
||||
elementNew(pid_data + pid_start + index, std::move(v));
|
||||
elementNew(pid_data + pid_start + index, std::move(e));
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & insert(size_t index, const PIDeque<T> & other) {
|
||||
@@ -369,12 +445,14 @@ public:
|
||||
if (dir) {
|
||||
ssize_t os = pid_size - index;
|
||||
alloc(pid_size + other.pid_size, true);
|
||||
if (os > 0)
|
||||
if (os > 0) {
|
||||
memmove((void*)(&(pid_data[index + pid_start + other.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
|
||||
}
|
||||
} else {
|
||||
alloc(pid_size + other.pid_size, false, -other.pid_size);
|
||||
if (index > 0)
|
||||
if (index > 0) {
|
||||
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + other.pid_size])), index * sizeof(T));
|
||||
}
|
||||
}
|
||||
newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.pid_size);
|
||||
return *this;
|
||||
@@ -389,9 +467,13 @@ public:
|
||||
size_t os = pid_size - index - count;
|
||||
deleteT(&(pid_data[index + pid_start]), count);
|
||||
if (os <= index) {
|
||||
if (os > 0) memmove((void*)(&(pid_data[index + pid_start])), (const void*)(&(pid_data[index + pid_start + count])), os * sizeof(T));
|
||||
if (os > 0) {
|
||||
memmove((void*)(&(pid_data[index + pid_start])), (const void*)(&(pid_data[index + pid_start + count])), os * sizeof(T));
|
||||
}
|
||||
} else {
|
||||
if (index > 0) memmove((void*)(&(pid_data[pid_start + count])), (const void*)(&(pid_data[pid_start])), index * sizeof(T));
|
||||
if (index > 0) {
|
||||
memmove((void*)(&(pid_data[pid_start + count])), (const void*)(&(pid_data[pid_start])), index * sizeof(T));
|
||||
}
|
||||
pid_start += count;
|
||||
}
|
||||
pid_size -= count;
|
||||
@@ -419,88 +501,114 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIDeque<T> & removeOne(const T & v) {
|
||||
for (size_t i = 0; i < pid_size; ++i)
|
||||
if (pid_data[i + pid_start] == v) {
|
||||
inline PIDeque<T> & removeOne(const T & e) {
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
if (pid_data[i + pid_start] == e) {
|
||||
remove(i);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & removeAll(const T & v) {
|
||||
for (ssize_t i = 0; i < ssize_t(pid_size); ++i)
|
||||
if (pid_data[i + pid_start] == v) {
|
||||
inline PIDeque<T> & removeAll(const T & e) {
|
||||
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
|
||||
if (pid_data[i + pid_start] == e) {
|
||||
remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
|
||||
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
|
||||
if (test(pid_data[i + pid_start])) {
|
||||
remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIDeque<T> & push_back(const T & v) {
|
||||
inline PIDeque<T> & push_back(const T & e) {
|
||||
alloc(pid_size + 1, true);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1);
|
||||
elementNew(pid_data + pid_start + pid_size - 1, v);
|
||||
elementNew(pid_data + pid_start + pid_size - 1, e);
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & push_back(T && v) {
|
||||
inline PIDeque<T> & push_back(T && e) {
|
||||
alloc(pid_size + 1, true);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1);
|
||||
elementNew(pid_data + pid_start + pid_size - 1, std::move(v));
|
||||
elementNew(pid_data + pid_start + pid_size - 1, std::move(e));
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & append(const T & v) {return push_back(v);}
|
||||
inline PIDeque<T> & append(T && v) {return push_back(std::move(v));}
|
||||
inline PIDeque<T> & append(const PIDeque<T> & t) {
|
||||
assert(&t != this);
|
||||
inline PIDeque<T> & append(const T & e) {return push_back(e);}
|
||||
inline PIDeque<T> & append(T && e) {return push_back(std::move(e));}
|
||||
inline PIDeque<T> & append(const PIDeque<T> & v) {
|
||||
assert(&v != this);
|
||||
size_t ps = pid_size;
|
||||
alloc(pid_size + t.pid_size, true);
|
||||
newT(pid_data + ps + pid_start, t.pid_data + t.pid_start, t.pid_size);
|
||||
alloc(pid_size + v.pid_size, true);
|
||||
newT(pid_data + ps + pid_start, v.pid_data + v.pid_start, v.pid_size);
|
||||
return *this;
|
||||
}
|
||||
inline PIDeque<T> & operator <<(const T & v) {return push_back(v);}
|
||||
inline PIDeque<T> & operator <<(T && v) {return push_back(std::move(v));}
|
||||
inline PIDeque<T> & operator <<(const PIDeque<T> & t) {return append(t);}
|
||||
inline PIDeque<T> & operator <<(const T & e) {return push_back(e);}
|
||||
inline PIDeque<T> & operator <<(T && e) {return push_back(std::move(e));}
|
||||
inline PIDeque<T> & operator <<(const PIDeque<T> & v) {return append(v);}
|
||||
|
||||
inline PIDeque<T> & push_front(const T & v) {insert(0, v); return *this;}
|
||||
inline PIDeque<T> & push_front(T && v) {insert(0, std::move(v)); return *this;}
|
||||
inline PIDeque<T> & prepend(const T & v) {return push_front(v);}
|
||||
inline PIDeque<T> & prepend(T && v) {return push_front(std::move(v));}
|
||||
inline PIDeque<T> & push_front(const T & e) {insert(0, e); return *this;}
|
||||
inline PIDeque<T> & push_front(T && e) {insert(0, std::move(e)); return *this;}
|
||||
inline PIDeque<T> & prepend(const T & e) {return push_front(e);}
|
||||
inline PIDeque<T> & prepend(T && e) {return push_front(std::move(e));}
|
||||
|
||||
inline PIDeque<T> & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;}
|
||||
inline PIDeque<T> & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;}
|
||||
|
||||
inline T take_back() {T t(back()); pop_back(); return t;}
|
||||
inline T take_front() {T t(front()); pop_front(); return t;}
|
||||
inline T take_back() {T e(back()); pop_back(); return e;}
|
||||
inline T take_front() {T e(front()); pop_front(); return e;}
|
||||
|
||||
template <typename ST>
|
||||
PIDeque<ST> toType() const {
|
||||
PIDeque<ST> ret(pid_size);
|
||||
for (uint i = 0; i < pid_size; ++i)
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
ret[i] = ST(pid_data[i + pid_start]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const PIDeque<T> & forEach(std::function<void(const T &)> f) const {
|
||||
for (uint i = 0; i < pid_size; ++i)
|
||||
const PIDeque<T> & forEach(std::function<void(const T & e)> f) const {
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
f(pid_data[i + pid_start]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
PIDeque<T> copyForEach(std::function<T(const T &)> f) const {
|
||||
PIDeque<T> copyForEach(std::function<T(const T & e)> f) const {
|
||||
PIDeque<T> ret; ret.reserve(pid_size);
|
||||
for (uint i = 0; i < pid_size; ++i)
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
ret << f(pid_data[i + pid_start]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
PIDeque<T> & forEachInplace(std::function<T(const T &)> f) {
|
||||
for (uint i = 0; i < pid_size; ++i)
|
||||
PIDeque<T> & forEachInplace(std::function<T(const T & e)> f) {
|
||||
for (size_t i = 0; i < pid_size; ++i)
|
||||
pid_data[i + pid_start] = f(pid_data[i + pid_start]);
|
||||
return *this;
|
||||
}
|
||||
template <typename ST>
|
||||
PIDeque<ST> toType(std::function<ST(const T &)> f) const {
|
||||
PIDeque<ST> map(std::function<ST(const T & e)> f) const {
|
||||
PIDeque<ST> ret; ret.reserve(pid_size);
|
||||
for (uint i = 0; i < pid_size; ++i)
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
ret << f(pid_data[i + pid_start]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
template <typename ST>
|
||||
PIDeque<ST> toType(std::function<ST(const T & e)> f) const {return map(f);}
|
||||
|
||||
template <typename ST>
|
||||
ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
||||
ST ret(initial);
|
||||
for (size_t i = 0; i < pid_size; ++i) {
|
||||
ret = f(pid_data[i + pid_start], ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -510,14 +618,16 @@ public:
|
||||
assert(rows*cols == pid_size);
|
||||
ret.resize(rows);
|
||||
if (order == byRow) {
|
||||
for (size_t r = 0; r < rows; r++)
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols);
|
||||
}
|
||||
}
|
||||
if (order == byColumn) {
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret[r].resize(cols);
|
||||
for (size_t c = 0; c < cols; c++)
|
||||
for (size_t c = 0; c < cols; c++) {
|
||||
ret[r][c] = pid_data[c*rows + r];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -533,13 +643,16 @@ public:
|
||||
size_t cols = at(0).size();
|
||||
ret.reserve(rows * cols);
|
||||
if (order == byRow) {
|
||||
for (size_t r = 0; r < rows; r++)
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret.append(at(r));
|
||||
}
|
||||
}
|
||||
if (order == byColumn) {
|
||||
for (size_t c = 0; c < cols; c++)
|
||||
for (size_t r = 0; r < rows; r++)
|
||||
for (size_t c = 0; c < cols; c++) {
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret << at(r)[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.resize(rows * cols);
|
||||
return ret;
|
||||
@@ -549,11 +662,13 @@ private:
|
||||
inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
|
||||
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))
|
||||
if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) {
|
||||
return pid_rsize + pid_rsize;
|
||||
}
|
||||
ssize_t t = 0, s_ = s - 1;
|
||||
while (s_ >> t)
|
||||
while (s_ >> t) {
|
||||
++t;
|
||||
}
|
||||
return (1 << t);
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
@@ -577,8 +692,9 @@ private:
|
||||
inline void deleteT(T * d, size_t sz) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||
if ((uchar*)d != 0) {
|
||||
for (size_t i = 0; i < sz; ++i)
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
elementDelete(d[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
@@ -652,10 +768,11 @@ private:
|
||||
}
|
||||
} else {
|
||||
size_t as;
|
||||
if (pid_start + start_offset < 0)
|
||||
if (pid_start + start_offset < 0) {
|
||||
as = asize(pid_rsize - start_offset);
|
||||
else as = pid_rsize;
|
||||
|
||||
} else {
|
||||
as = pid_rsize;
|
||||
}
|
||||
if (as > pid_rsize) {
|
||||
T * td = (T*)(malloc(as * sizeof(T)));
|
||||
ssize_t ns = pid_start + as - pid_rsize;
|
||||
@@ -682,7 +799,15 @@ private:
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
template<typename T>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIDeque<T> & v) {
|
||||
s << "{";
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
s << v[i];
|
||||
if (i < v.size() - 1) s << ", ";
|
||||
}
|
||||
s << "}";
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
@@ -692,8 +817,7 @@ inline PICout operator <<(PICout s, const PIDeque<T> & v) {
|
||||
s << "{";
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
s << v[i];
|
||||
if (i < v.size() - 1)
|
||||
s << ", ";
|
||||
if (i < v.size() - 1) s << ", ";
|
||||
}
|
||||
s << "}";
|
||||
s.restoreControl();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** \class PIMap
|
||||
* @brief Associative array
|
||||
* \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
|
||||
@@ -9,97 +9,97 @@
|
||||
* \a makeIterator() and \a makeReverseIterator().
|
||||
|
||||
* \fn PIMap::PIMap();
|
||||
* @brief Contructs an empty map
|
||||
* \brief Contructs an empty map
|
||||
|
||||
* \fn PIMap::PIMap(const PIMap & other);
|
||||
* @brief Contructs a copy of "other"
|
||||
* \brief Contructs a copy of "other"
|
||||
|
||||
* \fn PIMap & PIMap::operator =(const PIMap & other);
|
||||
* @brief Copy operator
|
||||
* \brief Copy operator
|
||||
|
||||
* \fn PIMap::PIMap(const PIMap & other);
|
||||
* @brief Contructs a copy of "other"
|
||||
* \brief Contructs a copy of "other"
|
||||
|
||||
* \fn PIMapIterator PIMap::makeIterator() const
|
||||
* @brief Returns PIMapIterator for this map
|
||||
* \brief Returns PIMapIterator for this map
|
||||
|
||||
* \fn PIMapIterator PIMap::makeReverseIterator() const
|
||||
* @brief Returns reverse PIMapIterator for this map
|
||||
* \brief Returns reverse PIMapIterator for this map
|
||||
|
||||
|
||||
* \fn size_t PIMap::size() const
|
||||
* @brief Returns entries count
|
||||
* \brief Returns entries count
|
||||
|
||||
* \fn int PIMap::size_s() const
|
||||
* @brief Returns entries count
|
||||
* \brief Returns entries count
|
||||
|
||||
* \fn size_t PIMap::length() const
|
||||
* @brief Returns entries count
|
||||
* \brief Returns entries count
|
||||
|
||||
* \fn bool PIMap::isEmpty() const
|
||||
* @brief Returns if map is empty
|
||||
* \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.
|
||||
* \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().
|
||||
* \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 []
|
||||
* \brief Equivalent to operator []
|
||||
|
||||
* \fn const T PIMap::at(const Key & key) const
|
||||
* @brief Equivalent to operator []
|
||||
* \brief Equivalent to operator []
|
||||
|
||||
|
||||
* \fn PIMap & PIMap::operator <<(const PIMap & other)
|
||||
* @brief Insert all etries of "other" to this map. Override existing values.
|
||||
* \brief Insert all etries of "other" to this map. Override existing values.
|
||||
|
||||
* \fn bool PIMap::operator ==(const PIMap & t) const
|
||||
* @brief Compare operator
|
||||
* \brief Compare operator
|
||||
|
||||
* \fn bool PIMap::operator !=(const PIMap & t) const
|
||||
* @brief Compare operator
|
||||
* \brief Compare operator
|
||||
|
||||
* \fn bool PIMap::contains(const Key & key) const
|
||||
* @brief Returns "true" if map contains entry with key "key"
|
||||
* \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
|
||||
* \brief Reserve space for "new_size" entries
|
||||
|
||||
* \fn PIMap & PIMap::removeOne(const Key & key)
|
||||
* @brief Remove entry with key "key"
|
||||
* \brief Remove entry with key "key"
|
||||
|
||||
* \fn PIMap & PIMap::remove(const Key & key)
|
||||
* @brief Equivalent \a removeOne(key)
|
||||
* \brief Equivalent \a removeOne(key)
|
||||
|
||||
* \fn PIMap & PIMap::erase(const Key & key)
|
||||
* @brief Equivalent \a removeOne(key)
|
||||
* \brief Equivalent \a removeOne(key)
|
||||
|
||||
* \fn PIMap & PIMap::clear()
|
||||
* @brief Clear map
|
||||
* \brief Clear map
|
||||
|
||||
|
||||
* \fn void PIMap::swap(PIMap & other)
|
||||
* @brief Swap map with "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"
|
||||
* \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".
|
||||
* \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
|
||||
* \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".
|
||||
* \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
|
||||
* \brief Returns all keys as PIVector
|
||||
|
||||
* */
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
|
||||
/** \class PIMapIterator
|
||||
* @brief Helper class to iterate over PIMap
|
||||
* \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.
|
||||
@@ -164,24 +164,24 @@
|
||||
* \endcode
|
||||
|
||||
* \fn PIMapIterator(const PIMap & map, bool reverse = false)
|
||||
* @brief Contructs iterator for "map". Current position is invalid.
|
||||
* \brief Contructs iterator for "map". Current position is invalid.
|
||||
|
||||
* \fn const Key & PIMapIterator::key() const
|
||||
* @brief Returns current entry key
|
||||
* \brief Returns current entry key
|
||||
|
||||
* \fn const T & PIMapIterator::value() const
|
||||
* @brief Returns current entry value
|
||||
* \brief Returns current entry value
|
||||
|
||||
* \fn T & PIMapIterator::valueRef() const
|
||||
* @brief Returns reference to current entry value
|
||||
* \brief Returns reference to current entry value
|
||||
|
||||
* \fn bool PIMapIterator::hasNext()
|
||||
* @brief Returns if iterator can jump to next entry
|
||||
* \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.
|
||||
* \brief Jump to next entry and return if new position is valid.
|
||||
|
||||
* \fn void PIMapIterator::reset()
|
||||
* @brief Reset iterator to initial position.
|
||||
* \brief Reset iterator to initial position.
|
||||
|
||||
* */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pimap.h
|
||||
* @brief Associative array with custom types of key and value
|
||||
/*! \file pimap.h
|
||||
* \brief Associative array with custom types of key and value
|
||||
*
|
||||
* This file declares PIMap
|
||||
*/
|
||||
@@ -107,6 +107,7 @@ public:
|
||||
iterator(): parent(0), 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));}
|
||||
void operator ++() {++pos;}
|
||||
void operator ++(int) {++pos;}
|
||||
void operator --() {--pos;}
|
||||
@@ -125,6 +126,7 @@ public:
|
||||
reverse_iterator(): parent(0), 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));}
|
||||
void operator ++() {--pos;}
|
||||
void operator ++(int) {--pos;}
|
||||
void operator --() {++pos;}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pipair.h
|
||||
* @brief pair
|
||||
/*! \file pipair.h
|
||||
* \brief pair
|
||||
*
|
||||
* This file declare PIPair
|
||||
*/
|
||||
@@ -33,6 +33,7 @@ template<typename Type0, typename Type1>
|
||||
class PIPair {
|
||||
public:
|
||||
PIPair() {first = Type0(); second = Type1();}
|
||||
PIPair(std::tuple<Type0, Type1> tuple) {first = std::get<0>(tuple); second = std::get<1>(tuple);}
|
||||
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}
|
||||
Type0 first;
|
||||
Type1 second;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pideque.h
|
||||
* @brief Queue container
|
||||
/*! \file pideque.h
|
||||
* \brief Queue container
|
||||
*
|
||||
* This file declare PIQueue
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piset.h
|
||||
* @brief Set container
|
||||
/*! \file piset.h
|
||||
* \brief Set container
|
||||
*
|
||||
* This file declare PISet
|
||||
*/
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "pimap.h"
|
||||
|
||||
/*! @brief Set of any type
|
||||
/*! \brief Set of any type
|
||||
* \details This class used to store collection of unique elements
|
||||
* of any type. You can only add values to set with \a operator<< or
|
||||
* with function \a insert(). You can discover if value already in
|
||||
@@ -129,16 +129,16 @@ public:
|
||||
};
|
||||
|
||||
|
||||
//! \relatesalso PISet @brief Returns unite of two sets
|
||||
//! \relatesalso PISet \brief Returns unite of two sets
|
||||
template <typename T> PISet<T> operator +(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.unite(v1); return ret;}
|
||||
|
||||
//! \relatesalso PISet @brief Returns subtraction of two sets
|
||||
//! \relatesalso PISet \brief Returns subtraction of two sets
|
||||
template <typename T> PISet<T> operator -(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.subtract(v1); return ret;}
|
||||
|
||||
//! \relatesalso PISet @brief Returns unite of two sets
|
||||
//! \relatesalso PISet \brief Returns unite of two sets
|
||||
template <typename T> PISet<T> operator |(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.unite(v1); return ret;}
|
||||
|
||||
//! \relatesalso PISet @brief Returns intersetion of two sets
|
||||
//! \relatesalso PISet \brief Returns intersetion of two sets
|
||||
template <typename T> PISet<T> operator &(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.intersect(v1); return ret;}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pistack.h
|
||||
* @brief Stack container
|
||||
/*! \file pistack.h
|
||||
* \brief Stack container
|
||||
*
|
||||
* This file declare PIStack
|
||||
*/
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
/** \class PIVector
|
||||
* @brief Dynamic array of any type
|
||||
* \details This class used to store dynamic array of any
|
||||
* type of data. In memory data stored linear. You can insert
|
||||
* item in any place of remove some items from any place.
|
||||
* For quick add elements this is stream operator <<.
|
||||
|
||||
* \fn PIVector::PIVector();
|
||||
* Contructs an empty vector
|
||||
|
||||
* \fn PIVector::PIVector(size_t size, const T & value = T());
|
||||
* @brief Contructs vector with size "size" filled elements "value"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::PIVector
|
||||
|
||||
* \fn PIVector::PIVector(std::initializer_list list);
|
||||
* @brief Contructs vector from C++11 initializer list
|
||||
* \details Example: \snippet picontainers.cpp PIVector::PIVector
|
||||
|
||||
* \fn const T & PIVector::at(size_t index) const;
|
||||
* @brief Read-only access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::at_c
|
||||
* \sa \a operator[]
|
||||
|
||||
* \fn T & PIVector::at(size_t index);
|
||||
* @brief Full access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::at
|
||||
* \sa \a operator[]
|
||||
|
||||
* \fn const T * PIVector::data(size_t index = 0) const;
|
||||
* @brief Read-only pointer to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::data_c
|
||||
|
||||
* \fn T * PIVector::data(size_t index = 0);
|
||||
* @brief Pointer to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::data
|
||||
|
||||
* \fn size_t PIVector::size() const;
|
||||
* @brief Elements count
|
||||
|
||||
* \fn ssize_t PIVector::size_s() const;
|
||||
* @brief Elements count
|
||||
|
||||
* \fn bool PIVector::isEmpty() const;
|
||||
* @brief Return \c "true" if vector is empty, i.e. size = 0
|
||||
|
||||
* \fn bool PIVector::has(const T & t) const;
|
||||
|
||||
* \fn bool PIVector::contains(const T & v) const;
|
||||
* @brief Return \c "true" if vector has at least one element equal "t"
|
||||
|
||||
* \fn int PIVector::etries(const T & t) const;
|
||||
* @brief Return how many times element "t" appears in vector
|
||||
|
||||
* \fn ssize_t PIVector::indexOf(const T & t) const;
|
||||
* @brief Return index of first element equal "t" or -1 if there is no such element
|
||||
|
||||
* \fn ssize_t PIVector::lastIndexOf(const T & t) const;
|
||||
* @brief Return index of last element equal "t" or -1 if there is no such element
|
||||
|
||||
* \fn static int PIVector::compare_func(const T * t0, const T * t1);
|
||||
* @brief Standard compare function for type "T". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1.
|
||||
|
||||
* \fn void PIVector::resize(size_t size, const T & new_type = T());
|
||||
* @brief Resize vector to size "size"
|
||||
* \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n
|
||||
* Example: \snippet picontainers.cpp PIVector::resize
|
||||
* \sa \a size(), \a clear()
|
||||
|
||||
* \fn PIVector & PIVector::enlarge(size_t size);
|
||||
* @brief Increase vector size with "size" elements
|
||||
|
||||
* \fn void PIVector::clear();
|
||||
* @brief Clear vector. Equivalent to call <tt>"resize(0)"</tt>
|
||||
|
||||
* \fn PIVector & PIVector::sort(CompareFunc compare = compare_func);
|
||||
* @brief Sort vector using quick sort algorithm and standard compare function
|
||||
* \details Example: \snippet picontainers.cpp PIVector::sort_0
|
||||
* With custom compare function: \snippet picontainers.cpp PIVector::sort_1
|
||||
|
||||
* \fn PIVector & PIVector::fill(const T & t);
|
||||
* @brief Fill vector with elements "t" leave size is unchanged and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::fill
|
||||
|
||||
* \fn PIVector & PIVector::assign(const T & t = T());
|
||||
* @brief Synonym of \a fill(t)
|
||||
|
||||
* \fn PIVector & PIVector::assign(size_t new_size, const T & t);
|
||||
* @brief Resize to "new_size", then fill with "t"
|
||||
|
||||
* \fn T & PIVector::back();
|
||||
* @brief Last element of the vector
|
||||
|
||||
* \fn const T & PIVector::back() const;
|
||||
* @brief Last element of the vector
|
||||
|
||||
* \fn T & PIVector::front();
|
||||
* @brief First element of the vector
|
||||
|
||||
* \fn const T & PIVector::front() const;
|
||||
* @brief First element of the vector
|
||||
|
||||
* \fn PIVector & PIVector::push_back(const T & t);
|
||||
* @brief Add new element "t" at the end of vector and return reference to vector
|
||||
|
||||
* \fn PIVector & PIVector::push_front(const T & t);
|
||||
* @brief Add new element "t" at the beginning of vector and return reference to vector
|
||||
|
||||
* \fn PIVector & PIVector::pop_back();
|
||||
* @brief Remove one element from the end of vector and return reference to vector
|
||||
|
||||
* \fn PIVector & PIVector::pop_front();
|
||||
* @brief Remove one element from the beginning of vector and return reference to vector
|
||||
|
||||
* \fn T PIVector::take_back();
|
||||
* @brief Remove one element from the end of vector and return it
|
||||
|
||||
* \fn T PIVector::take_front();
|
||||
* @brief Remove one element from the beginning of vector and return it
|
||||
|
||||
* \fn PIVector & PIVector::remove(size_t index);
|
||||
* @brief Remove one element by index "index" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::remove_0
|
||||
* \sa \a removeOne(), \a removeAll()
|
||||
|
||||
* \fn PIVector & PIVector::remove(size_t index, size_t count);
|
||||
* @brief Remove "count" elements by first index "index" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::remove_1
|
||||
* \sa \a removeOne(), \a removeAll()
|
||||
|
||||
* \fn PIVector & PIVector::removeOne(const T & v);
|
||||
* @brief Remove no more than one element equal "v" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::removeOne
|
||||
* \sa \a remove(), \a removeAll()
|
||||
|
||||
* \fn PIVector & PIVector::removeAll(const T & v);
|
||||
* @brief Remove all elements equal "v" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::removeAll
|
||||
* \sa \a remove(), \a removeOne()
|
||||
|
||||
* \fn PIVector & PIVector::insert(size_t pos, const T & t);
|
||||
* @brief Insert element "t" after index "pos" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::insert_0
|
||||
|
||||
* \fn PIVector & PIVector::insert(size_t pos, const PIVector & t);
|
||||
* @brief Insert other vector "t" after index "pos" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::insert_1
|
||||
|
||||
* \fn T & PIVector::operator [](size_t index);
|
||||
* @brief Full access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::()
|
||||
* \sa \a at()
|
||||
|
||||
* \fn const T & PIVector::operator [](size_t index) const;
|
||||
* @brief Read-only access to element by index "index"
|
||||
* \details Example: \snippet picontainers.cpp PIVector::()_c
|
||||
* \sa \a at()
|
||||
|
||||
* \fn PIVector & PIVector::operator <<(const T & t);
|
||||
* @brief Add new element "t" at the end of vector and return reference to vector
|
||||
|
||||
* \fn PIVector & PIVector::operator <<(const PIVector & t);
|
||||
* @brief Add vector "t" at the end of vector and return reference to vector
|
||||
|
||||
* \fn bool PIVector::operator ==(const PIVector & t);
|
||||
* @brief Compare with vector "t"
|
||||
|
||||
* \fn bool PIVector::operator !=(const PIVector & t);
|
||||
* @brief Compare with vector "t"
|
||||
|
||||
* */
|
||||
@@ -1,11 +1,20 @@
|
||||
/*! @file pivector.h
|
||||
* @brief Dynamic array of any type
|
||||
*
|
||||
* This file declares PIVector
|
||||
*/
|
||||
/*! \addtogroup Containers
|
||||
* \{
|
||||
* \file pivector.h
|
||||
* \brief
|
||||
* \~english Declares \a PIVector
|
||||
* \~russian Объявление \a PIVector
|
||||
* \~\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
|
||||
Dynamic array of any type
|
||||
Sequence linear container aka dynamic size array of any type
|
||||
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -27,23 +36,81 @@
|
||||
|
||||
#include "picontainers.h"
|
||||
|
||||
|
||||
/*! \addtogroup Containers
|
||||
* \{
|
||||
* \class PIVector pivector.h
|
||||
* \brief
|
||||
* \~english Sequence linear container - dynamic size array of any type
|
||||
* \~russian Последовательный контейнер с линейной памятью - динамический массив любого типа
|
||||
* \~\}
|
||||
* \details
|
||||
* \~english
|
||||
* The elements are stored contiguously,
|
||||
* which means that elements can be accessed not only through iterators,
|
||||
* but also using offsets to regular pointers to elements.
|
||||
* This means that a pointer to an element of a vector may be passed to any function
|
||||
* that expects a pointer to an element of an array.
|
||||
*
|
||||
* The storage of the vector is handled automatically,
|
||||
* being expanded and contracted as needed.
|
||||
* Vectors usually occupy more space than static arrays,
|
||||
* because more memory is allocated to handle future growth.
|
||||
* This way a vector does not need to reallocate each time an element is inserted,
|
||||
* but only when the additional memory is exhausted.
|
||||
* The total amount of allocated memory can be queried using \a capacity() function.
|
||||
* Reallocations are usually costly operations in terms of performance.
|
||||
* The \a reserve() function can be used to eliminate reallocations
|
||||
* if the number of elements is known beforehand.
|
||||
*
|
||||
* The complexity (efficiency) of common operations on vectors is as follows:
|
||||
* - Random access - constant 𝓞(1)
|
||||
* - Insertion or removal of elements at the end - amortized constant 𝓞(1)
|
||||
* - Insertion or removal of elements - linear in the distance to the end of the vector 𝓞(n)
|
||||
*
|
||||
* \~russian
|
||||
* Элементы хранятся непрерывно, а значит доступны не только через итераторы,
|
||||
* но и с помощью смещений для обычных указателей на элементы.
|
||||
* Это означает, что указатель на элемент вектора может передаваться в любую функцию,
|
||||
* ожидающую указатель на элемент массива.
|
||||
*
|
||||
* Память вектора обрабатывается автоматически,
|
||||
* расширяясь и сжимаясь по мере необходимости.
|
||||
* Векторы обычно занимают больше места, чем статические массивы,
|
||||
* поскольку больше памяти выделяется для обработки будущего роста.
|
||||
* Таким образом, память для вектора требуется выделять
|
||||
* не при каждой вставке элемента,
|
||||
* а только после исчерпания дополнительной памяти.
|
||||
* Общий объём выделенной памяти можно получить с помощью функции \a capacity().
|
||||
*
|
||||
* Выделение памяти обычно является дорогостоящей операцией
|
||||
* с точки зрения производительности.
|
||||
* Функцию \a reserve() можно использовать для исключения выделения памяти,
|
||||
* если количество элементов известно заранее.
|
||||
*
|
||||
* Сложность (эффективность) обычных операций над векторами следующая:
|
||||
* - Произвольный доступ — постоянная 𝓞(1)
|
||||
* - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1)
|
||||
* - Вставка и удаление элементов — линейная по расстоянию до конца вектора 𝓞(n)
|
||||
*/
|
||||
template <typename T>
|
||||
class PIVector {
|
||||
public:
|
||||
//! Contructs an empty vector
|
||||
inline PIVector(): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
}
|
||||
//! \brief Contructs vector with size "size" filled elements "value"
|
||||
inline PIVector(const T * data, size_t size): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
alloc(size);
|
||||
newT(piv_data, data, piv_size);
|
||||
}
|
||||
inline PIVector(const PIVector<T> & other): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||
inline PIVector(const PIVector<T> & v): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
alloc(other.piv_size);
|
||||
newT(piv_data, other.piv_data, piv_size);
|
||||
alloc(v.piv_size);
|
||||
newT(piv_data, v.piv_data, piv_size);
|
||||
}
|
||||
//! \brief Contructs vector from C++11 initializer list
|
||||
inline PIVector(std::initializer_list<T> init_list): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
alloc(init_list.size());
|
||||
@@ -53,13 +120,13 @@ public:
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
resize(piv_size, f);
|
||||
}
|
||||
inline PIVector(size_t piv_size, std::function<T(size_t)> f): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||
inline PIVector(size_t piv_size, std::function<T(size_t i)> f): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
resize(piv_size, f);
|
||||
}
|
||||
inline PIVector(PIVector<T> && other): piv_data(other.piv_data), piv_size(other.piv_size), piv_rsize(other.piv_rsize) {
|
||||
inline PIVector(PIVector<T> && v): piv_data(v.piv_data), piv_size(v.piv_size), piv_rsize(v.piv_rsize) {
|
||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||
other._reset();
|
||||
v._reset();
|
||||
}
|
||||
inline virtual ~PIVector() {
|
||||
PIINTROSPECTION_CONTAINER_DELETE(T)
|
||||
@@ -69,22 +136,20 @@ public:
|
||||
_reset();
|
||||
}
|
||||
|
||||
inline PIVector<T> & operator =(const PIVector<T> & other) {
|
||||
if (this == &other) return *this;
|
||||
inline PIVector<T> & operator =(const PIVector<T> & v) {
|
||||
if (this == &v) return *this;
|
||||
clear();
|
||||
deleteT(piv_data, piv_size);
|
||||
alloc(other.piv_size);
|
||||
newT(piv_data, other.piv_data, piv_size);
|
||||
alloc(v.piv_size);
|
||||
newT(piv_data, v.piv_data, piv_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIVector<T> & operator =(PIVector<T> && other) {
|
||||
swap(other);
|
||||
inline PIVector<T> & operator =(PIVector<T> && v) {
|
||||
swap(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
enum ReshapeOrder {
|
||||
byRow,
|
||||
byColumn
|
||||
@@ -174,6 +239,19 @@ public:
|
||||
inline size_t length() const {return piv_size;}
|
||||
inline size_t capacity() const {return piv_rsize;}
|
||||
inline bool isEmpty() const {return (piv_size == 0);}
|
||||
inline bool isNotEmpty() const {return (piv_size > 0);}
|
||||
inline bool any(std::function<bool(const T & e)> test) const {
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if (test(piv_data[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool every(std::function<bool(const T & e)> test) const {
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if (!test(piv_data[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline T & operator [](size_t index) {return piv_data[index];}
|
||||
inline const T & operator [](size_t index) const {return piv_data[index];}
|
||||
@@ -183,42 +261,103 @@ public:
|
||||
inline T & front() {return piv_data[0];}
|
||||
inline const T & front() const {return piv_data[0];}
|
||||
inline bool operator ==(const PIVector<T> & t) const {
|
||||
if (piv_size != t.piv_size)
|
||||
if (piv_size != t.piv_size) {
|
||||
return false;
|
||||
for (size_t i = 0; i < piv_size; ++i)
|
||||
if (t[i] != piv_data[i])
|
||||
}
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if (t[i] != piv_data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline bool operator !=(const PIVector<T> & t) const {return !(*this == t);}
|
||||
inline bool contains(const T & v) const {
|
||||
for (size_t i = 0; i < piv_size; ++i)
|
||||
if (v == piv_data[i])
|
||||
return true;
|
||||
inline bool operator <(const PIVector<T> & t) const {
|
||||
if (piv_size != t.piv_size) return piv_size < t.piv_size;
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if ((*this)[i] != t[i]) return (*this)[i] < t[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline int etries(const T & v) const {
|
||||
inline bool operator >(const PIVector<T> & t) const {
|
||||
if (piv_size != t.piv_size) return piv_size > t.piv_size;
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if ((*this)[i] != t[i]) return (*this)[i] > t[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool contains(const T & e) const {
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if (e == piv_data[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline int etries(const T & e, size_t start = 0) const {
|
||||
int ec = 0;
|
||||
for (size_t i = 0; i < piv_size; ++i)
|
||||
if (v == piv_data[i]) ++ec;
|
||||
if (start >= piv_size) return ec;
|
||||
for (size_t i = start; i < piv_size; ++i) {
|
||||
if (e == piv_data[i]) ++ec;
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
inline ssize_t indexOf(const T & v) const {
|
||||
for (size_t i = 0; i < piv_size; ++i)
|
||||
if (v == piv_data[i])
|
||||
inline int etries(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||
int ec = 0;
|
||||
if (start >= piv_size) return ec;
|
||||
for (size_t i = start; i < piv_size; ++i) {
|
||||
if (test(piv_data[i])) ++ec;
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
inline ssize_t indexOf(const T & e, size_t start = 0) const {
|
||||
if (start >= piv_size) return -1;
|
||||
for (size_t i = start; i < piv_size; ++i) {
|
||||
if (e == piv_data[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline ssize_t lastIndexOf(const T & v) const {
|
||||
for (ssize_t i = piv_size - 1; i >= 0; --i)
|
||||
if (v == piv_data[i])
|
||||
inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||
if (start >= piv_size) return -1;
|
||||
for (size_t i = start; i < piv_size; ++i) {
|
||||
if (test(piv_data[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
|
||||
if (start < 0) start = piv_size - 1;
|
||||
else start = piMin<ssize_t>(piv_size - 1, start);
|
||||
for (ssize_t i = start; i >= 0; --i) {
|
||||
if (e == piv_data[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
|
||||
if (start < 0) start = piv_size - 1;
|
||||
else start = piMin<ssize_t>(piv_size - 1, start);
|
||||
for (ssize_t i = start; i >= 0; --i) {
|
||||
if (test(piv_data[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline T * data(size_t index = 0) {return &(piv_data[index]);}
|
||||
inline const T * data(size_t index = 0) const {return &(piv_data[index]);}
|
||||
|
||||
PIVector<T> getRange(size_t index, size_t count) const {
|
||||
if (index >= piv_size || count == 0) return PIVector<T>();
|
||||
if (index + count > piv_size) count = piv_size - index;
|
||||
return PIVector(&(piv_data[index]), count);
|
||||
}
|
||||
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
!std::is_trivially_copyable<T1>::value
|
||||
, int>::type = 0>
|
||||
@@ -238,15 +377,17 @@ public:
|
||||
inline PIVector<T> & fill(const T & f = T()) {
|
||||
deleteT(piv_data, piv_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, piv_size)
|
||||
for (size_t i = 0; i < piv_size; ++i)
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
elementNew(piv_data + i, f);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & fill(std::function<T(size_t)> f) {
|
||||
inline PIVector<T> & fill(std::function<T(size_t i)> f) {
|
||||
deleteT(piv_data, piv_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, piv_size)
|
||||
for (size_t i = 0; i < piv_size; ++i)
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
elementNew(piv_data + i, f(i));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & assign(const T & f = T()) {return fill(f);}
|
||||
@@ -275,12 +416,13 @@ public:
|
||||
size_t os = piv_size;
|
||||
alloc(new_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||
for (size_t i = os; i < new_size; ++i)
|
||||
for (size_t i = os; i < new_size; ++i) {
|
||||
elementNew(piv_data + i, f);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & resize(size_t new_size, std::function<T(size_t)> f) {
|
||||
inline PIVector<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
|
||||
if (new_size < piv_size) {
|
||||
T * de = &(piv_data[new_size]);
|
||||
deleteT(de, piv_size - new_size);
|
||||
@@ -290,8 +432,9 @@ public:
|
||||
size_t os = piv_size;
|
||||
alloc(new_size);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||
for (size_t i = os; i < new_size; ++i)
|
||||
for (size_t i = os; i < new_size; ++i) {
|
||||
elementNew(piv_data + i, f(i));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -320,34 +463,35 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIVector<T> & insert(size_t index, const T & v = T()) {
|
||||
inline PIVector<T> & insert(size_t index, const T & e = T()) {
|
||||
alloc(piv_size + 1);
|
||||
if (index < piv_size - 1) {
|
||||
size_t os = piv_size - index - 1;
|
||||
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||
}
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||
elementNew(piv_data + index, v);
|
||||
elementNew(piv_data + index, e);
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & insert(size_t index, T && v) {
|
||||
inline PIVector<T> & insert(size_t index, T && e) {
|
||||
alloc(piv_size + 1);
|
||||
if (index < piv_size - 1) {
|
||||
size_t os = piv_size - index - 1;
|
||||
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||
}
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||
elementNew(piv_data + index, std::move(v));
|
||||
elementNew(piv_data + index, std::move(e));
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & insert(size_t index, const PIVector<T> & other) {
|
||||
if (other.isEmpty()) return *this;
|
||||
assert(&other != this);
|
||||
inline PIVector<T> & insert(size_t index, const PIVector<T> & v) {
|
||||
if (v.isEmpty()) return *this;
|
||||
assert(&v != this);
|
||||
ssize_t os = piv_size - index;
|
||||
alloc(piv_size + other.piv_size);
|
||||
if (os > 0)
|
||||
memmove((void*)(&(piv_data[index + other.piv_size])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||
newT(piv_data + index, other.piv_data, other.piv_size);
|
||||
alloc(piv_size + v.piv_size);
|
||||
if (os > 0) {
|
||||
memmove((void*)(&(piv_data[index + v.piv_size])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||
}
|
||||
newT(piv_data + index, v.piv_data, v.piv_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -364,10 +508,10 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void swap(PIVector<T> & other) {
|
||||
piSwap<T*>(piv_data, other.piv_data);
|
||||
piSwap<size_t>(piv_size, other.piv_size);
|
||||
piSwap<size_t>(piv_rsize, other.piv_rsize);
|
||||
inline void swap(PIVector<T> & v) {
|
||||
piSwap<T*>(piv_data, v.piv_data);
|
||||
piSwap<size_t>(piv_size, v.piv_size);
|
||||
piSwap<size_t>(piv_rsize, v.piv_rsize);
|
||||
}
|
||||
|
||||
typedef int (*CompareFunc)(const T * , const T * );
|
||||
@@ -384,115 +528,149 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIVector<T> & removeOne(const T & v) {
|
||||
for (size_t i = 0; i < piv_size; ++i)
|
||||
if (piv_data[i] == v) {
|
||||
/*! \brief Remove no more than one element equal "v" and return reference to vector
|
||||
* \details Example: \snippet picontainers.cpp PIVector::removeOne
|
||||
* \sa \a remove(), \a removeAll()
|
||||
*/
|
||||
inline PIVector<T> & removeOne(const T & e) {
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
if (piv_data[i] == e) {
|
||||
remove(i);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & removeAll(const T & v) {
|
||||
for (ssize_t i = 0; i < ssize_t(piv_size); ++i)
|
||||
if (piv_data[i] == v) {
|
||||
inline PIVector<T> & removeAll(const T & e) {
|
||||
for (ssize_t i = 0; i < ssize_t(piv_size); ++i) {
|
||||
if (piv_data[i] == e) {
|
||||
remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & removeWhere(std::function<bool(const T & e)> test) {
|
||||
for (ssize_t i = 0; i < ssize_t(piv_size); ++i) {
|
||||
if (test(piv_data[i])) {
|
||||
remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PIVector<T> & push_back(const T & v) {
|
||||
inline PIVector<T> & push_back(const T & e) {
|
||||
alloc(piv_size + 1);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1);
|
||||
elementNew(piv_data + piv_size - 1, v);
|
||||
elementNew(piv_data + piv_size - 1, e);
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & push_back(T && v) {
|
||||
|
||||
inline PIVector<T> & push_back(T && e) {
|
||||
alloc(piv_size + 1);
|
||||
PIINTROSPECTION_CONTAINER_USED(T, 1);
|
||||
elementNew(piv_data + piv_size - 1, std::move(v));
|
||||
elementNew(piv_data + piv_size - 1, std::move(e));
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & append(const T & v) {return push_back(v);}
|
||||
inline PIVector<T> & append(T && v) {return push_back(std::move(v));}
|
||||
inline PIVector<T> & append(const PIVector<T> & other) {
|
||||
assert(&other != this);
|
||||
|
||||
inline PIVector<T> & append(const T & e) {return push_back(e);}
|
||||
inline PIVector<T> & append(T && e) {return push_back(std::move(e));}
|
||||
inline PIVector<T> & append(const PIVector<T> & v) {
|
||||
assert(&v != this);
|
||||
size_t ps = piv_size;
|
||||
alloc(piv_size + other.piv_size);
|
||||
newT(piv_data + ps, other.piv_data, other.piv_size);
|
||||
alloc(piv_size + v.piv_size);
|
||||
newT(piv_data + ps, v.piv_data, v.piv_size);
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & operator <<(const T & v) {return push_back(v);}
|
||||
inline PIVector<T> & operator <<(T && v) {return push_back(std::move(v));}
|
||||
inline PIVector<T> & operator <<(const PIVector<T> & other) {return append(other);}
|
||||
inline PIVector<T> & operator <<(const T & e) {return push_back(e);}
|
||||
inline PIVector<T> & operator <<(T && e) {return push_back(std::move(e));}
|
||||
inline PIVector<T> & operator <<(const PIVector<T> & v) {return append(v);}
|
||||
|
||||
inline PIVector<T> & push_front(const T & v) {insert(0, v); return *this;}
|
||||
inline PIVector<T> & push_front(T && v) {insert(0, std::move(v)); return *this;}
|
||||
inline PIVector<T> & prepend(const T & v) {return push_front(v);}
|
||||
inline PIVector<T> & prepend(T && v) {return push_front(std::move(v));}
|
||||
inline PIVector<T> & push_front(const T & e) {insert(0, e); return *this;}
|
||||
inline PIVector<T> & push_front(T && e) {insert(0, std::move(e)); return *this;}
|
||||
inline PIVector<T> & prepend(const T & e) {return push_front(e);}
|
||||
inline PIVector<T> & prepend(T && e) {return push_front(std::move(e));}
|
||||
|
||||
inline PIVector<T> & pop_back() {
|
||||
if (piv_size == 0)
|
||||
return *this;
|
||||
if (piv_size == 0) return *this;
|
||||
resize(piv_size - 1);
|
||||
return *this;
|
||||
}
|
||||
inline PIVector<T> & pop_front() {
|
||||
if (piv_size == 0)
|
||||
return *this;
|
||||
if (piv_size == 0) return *this;
|
||||
remove(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline T take_back() {T t(back()); pop_back(); return t;}
|
||||
inline T take_front() {T t(front()); pop_front(); return t;}
|
||||
inline T take_back() {T e(back()); pop_back(); return e;}
|
||||
inline T take_front() {T e(front()); pop_front(); return e;}
|
||||
|
||||
template <typename ST>
|
||||
PIVector<ST> toType() const {
|
||||
PIVector<ST> ret(piv_size);
|
||||
for (uint i = 0; i < piv_size; ++i)
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
ret[i] = ST(piv_data[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const PIVector<T> & forEach(std::function<void(const T &)> f) const {
|
||||
for (uint i = 0; i < piv_size; ++i)
|
||||
const PIVector<T> & forEach(std::function<void(const T & e)> f) const {
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
f(piv_data[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
PIVector<T> copyForEach(std::function<T(const T &)> f) const {
|
||||
PIVector<T> copyForEach(std::function<T(const T & e)> f) const {
|
||||
PIVector<T> ret; ret.reserve(piv_size);
|
||||
for (uint i = 0; i < piv_size; ++i)
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
ret << f(piv_data[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
PIVector<T> & forEachInplace(std::function<T(const T &)> f) {
|
||||
for (uint i = 0; i < piv_size; ++i)
|
||||
PIVector<T> & forEachInplace(std::function<T(const T & e)> f) {
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
piv_data[i] = f(piv_data[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename ST>
|
||||
PIVector<ST> map(std::function<ST(const T & e)> f) const {
|
||||
PIVector<ST> ret; ret.reserve(piv_size);
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
ret << f(piv_data[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
template <typename ST>
|
||||
PIVector<ST> toType(std::function<ST(const T &)> f) const {
|
||||
PIVector<ST> ret; ret.reserve(piv_size);
|
||||
for (uint i = 0; i < piv_size; ++i)
|
||||
ret << f(piv_data[i]);
|
||||
PIVector<ST> toType(std::function<ST(const T & e)> f) const {return map(f);}
|
||||
|
||||
template <typename ST>
|
||||
ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
||||
ST ret(initial);
|
||||
for (size_t i = 0; i < piv_size; ++i) {
|
||||
ret = f(piv_data[i], ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, int order = byRow) const {
|
||||
inline PIVector<PIVector<T>> reshape(size_t rows, size_t cols, ReshapeOrder order = byRow) const {
|
||||
PIVector<PIVector<T>> ret;
|
||||
if (isEmpty()) return ret;
|
||||
assert(rows*cols == piv_size);
|
||||
ret.resize(rows);
|
||||
if (order == byRow) {
|
||||
for (size_t r = 0; r < rows; r++)
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret[r] = PIVector<T>(&(piv_data[r*cols]), cols);
|
||||
}
|
||||
}
|
||||
if (order == byColumn) {
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret[r].resize(cols);
|
||||
for (size_t c = 0; c < cols; c++)
|
||||
for (size_t c = 0; c < cols; c++) {
|
||||
ret[r][c] = piv_data[c*rows + r];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -501,20 +679,23 @@ public:
|
||||
template<typename C, typename std::enable_if<
|
||||
std::is_same<T, PIVector<C>>::value
|
||||
, int>::type = 0>
|
||||
inline PIVector<C> reshape(int order = byRow) const {
|
||||
inline PIVector<C> reshape(ReshapeOrder order = byRow) const {
|
||||
PIVector<C> ret;
|
||||
if (isEmpty()) return ret;
|
||||
size_t rows = size();
|
||||
size_t cols = at(0).size();
|
||||
ret.reserve(rows * cols);
|
||||
if (order == byRow) {
|
||||
for (size_t r = 0; r < rows; r++)
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret.append(at(r));
|
||||
}
|
||||
}
|
||||
if (order == byColumn) {
|
||||
for (size_t c = 0; c < cols; c++)
|
||||
for (size_t r = 0; r < rows; r++)
|
||||
for (size_t c = 0; c < cols; c++) {
|
||||
for (size_t r = 0; r < rows; r++) {
|
||||
ret << at(r)[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.resize(rows * cols);
|
||||
return ret;
|
||||
@@ -524,8 +705,9 @@ private:
|
||||
inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;}
|
||||
inline size_t asize(size_t s) {
|
||||
if (s == 0) return 0;
|
||||
if (piv_rsize + piv_rsize >= s && piv_rsize < s)
|
||||
if (piv_rsize + piv_rsize >= s && piv_rsize < s) {
|
||||
return piv_rsize + piv_rsize;
|
||||
}
|
||||
ssize_t t = 0, s_ = s - 1;
|
||||
while (s_ >> t) ++t;
|
||||
return (1 << t);
|
||||
@@ -551,8 +733,9 @@ private:
|
||||
inline void deleteT(T * d, size_t sz) {
|
||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||
if ((uchar*)d != 0) {
|
||||
for (size_t i = 0; i < sz; ++i)
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
elementDelete(d[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T1 = T, typename std::enable_if<
|
||||
@@ -612,7 +795,15 @@ private:
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
template<typename T>
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIVector<T> & v) {
|
||||
s << "{";
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
s << v[i];
|
||||
if (i < v.size() - 1) s << ", ";
|
||||
}
|
||||
s << "}";
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
@@ -622,8 +813,9 @@ inline PICout operator <<(PICout s, const PIVector<T> & v) {
|
||||
s << "{";
|
||||
for (size_t i = 0; i < v.size(); ++i) {
|
||||
s << v[i];
|
||||
if (i < v.size() - 1)
|
||||
if (i < v.size() - 1) {
|
||||
s << ", ";
|
||||
}
|
||||
}
|
||||
s << "}";
|
||||
s.restoreControl();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file pivector2d.h
|
||||
* @brief 2D wrapper around PIVector
|
||||
/*! \file pivector2d.h
|
||||
* \brief 2D wrapper around PIVector
|
||||
*
|
||||
* This file declares PIVector
|
||||
*/
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "pivector.h"
|
||||
|
||||
/*! @brief 2D array,
|
||||
/*! \brief 2D array,
|
||||
* \details This class used to store 2D array of any type elements as plain vector.
|
||||
* You can read/write any element via operators [][], first dimension - row, second - column.
|
||||
* The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc.
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
/*! @file pibase.h
|
||||
* @brief Base types and functions
|
||||
/*! \file pibase.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Base types and functions
|
||||
* \~russian Базовые типы и методы
|
||||
*
|
||||
* \~\details
|
||||
* \~english
|
||||
* This file implements first layer above the system and
|
||||
* declares some basic useful functions
|
||||
* \~russian
|
||||
* Этот файл реализует первый слой после системы и объявляет
|
||||
* несколько базовых полезных методов
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -32,95 +40,173 @@
|
||||
#include "pip_defs.h"
|
||||
#include "string.h"
|
||||
|
||||
//! \~english
|
||||
//! Meta-information section for any entity.
|
||||
//! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo.
|
||||
//! Contains sequence of key=value pairs, e.g.
|
||||
//! \~russian
|
||||
//! Секция метаинформации для любой сущности.
|
||||
//! Парсится \a pip_cmg и доступна с помощью \a PICodeInfo.
|
||||
//! Содержит набор пар ключ=значение, например
|
||||
//! \~
|
||||
//! PIMETA(id=12345,tag="my string")
|
||||
#define PIMETA(...)
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
//! Major value of PIP version
|
||||
//! \~\brief
|
||||
//! \~english Major value of PIP version
|
||||
//! \~russian Мажорная версия PIP
|
||||
# define PIP_VERSION_MAJOR
|
||||
|
||||
//! Minor value of PIP version
|
||||
//! \~\brief
|
||||
//! \~english Minor value of PIP version
|
||||
//! \~russian Минорная версия PIP
|
||||
# define PIP_VERSION_MINOR
|
||||
|
||||
//! Revision value of PIP version
|
||||
//! \~\brief
|
||||
//! \~english Revision value of PIP version
|
||||
//! \~russian Ревизия версии PIP
|
||||
# define PIP_VERSION_REVISION
|
||||
|
||||
//! Suffix of PIP version
|
||||
//! \~\brief
|
||||
//! \~english Suffix of PIP version
|
||||
//! \~russian Суффикс версии PIP
|
||||
# define PIP_VERSION_SUFFIX
|
||||
|
||||
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
||||
//! \~\brief
|
||||
//! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
||||
//! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision)
|
||||
# define PIP_VERSION
|
||||
|
||||
//! Macro is defined when compile-time debug is enabled
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when compile-time debug is enabled
|
||||
//! \~russian Макрос объявлен когда включена compile-time отладка
|
||||
# define PIP_DEBUG
|
||||
|
||||
//! Macro is defined when host is any Windows
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is any Windows
|
||||
//! \~russian Макрос объявлен когда операционная система Windows
|
||||
# define WINDOWS
|
||||
|
||||
//! Macro is defined when host is QNX or Blackberry
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is QNX or Blackberry
|
||||
//! \~russian Макрос объявлен когда операционная система QNX или Blackberry
|
||||
# define QNX
|
||||
|
||||
//! Macro is defined when host is Blackberry
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is Blackberry
|
||||
//! \~russian Макрос объявлен когда операционная система Blackberry
|
||||
# define BLACKBERRY
|
||||
|
||||
//! Macro is defined when host is FreeBSD
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is FreeBSD
|
||||
//! \~russian Макрос объявлен когда операционная система FreeBSD
|
||||
# define FREE_BSD
|
||||
|
||||
//! Macro is defined when host is Mac OS
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is Mac OS
|
||||
//! \~russian Макрос объявлен когда операционная система Mac OS
|
||||
# define MAC_OS
|
||||
|
||||
//! Macro is defined when host is Android
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is Android
|
||||
//! \~russian Макрос объявлен когда операционная система Android
|
||||
# define ANDROID
|
||||
|
||||
//! Macro is defined when host is any Linux
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is any Linux
|
||||
//! \~russian Макрос объявлен когда операционная система Linux
|
||||
# define LINUX
|
||||
|
||||
//! Macro is defined when compiler is GCC or MinGW
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when operation system is FreeRTOS
|
||||
//! \~russian Макрос объявлен когда операционная система FreeRTOS
|
||||
# define FREERTOS
|
||||
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when compiler is GCC or MinGW
|
||||
//! \~russian Макрос объявлен когда компилятор GCC или MinGW
|
||||
# define CC_GCC
|
||||
|
||||
//! Macro is defined when PIP is decided that host is support language
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when PIP is decided that host is support language
|
||||
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
|
||||
# define HAS_LOCALE
|
||||
|
||||
//! Macro is defined when compiler is Visual Studio
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when PIP is building for embedded systems
|
||||
//! \~russian Макрос объявлен когда PIP собирается для встраиваемых систем
|
||||
# define MICRO_PIP
|
||||
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when compiler is Visual Studio
|
||||
//! \~russian Макрос объявлен когда компилятор Visual Studio
|
||||
# define CC_VC
|
||||
|
||||
//! Macro is defined when compiler is unknown
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when compiler is AVR GCC
|
||||
//! \~russian Макрос объявлен когда компилятор AVR GCC
|
||||
# define CC_AVR_GCC
|
||||
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when compiler is unknown
|
||||
//! \~russian Макрос объявлен когда компилятор неизвестен
|
||||
# define CC_OTHER
|
||||
|
||||
//! Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation
|
||||
//! \~\brief
|
||||
//! \~english Macro is defined when PIP can use "rt" library for \a PITimer::ThreadRT timers implementation
|
||||
//! \~russian Макрос объявлен когда PIP может использовать библиотеку "rt" для \a PITimer::ThreadRT реализации таймера
|
||||
# define PIP_TIMER_RT
|
||||
|
||||
//! Macro to declare private section, export is optional
|
||||
//! \~\brief
|
||||
//! \~english Macro to declare private section, "export" is optional
|
||||
//! \~russian Макрос для объявления частной секции, "export" необязателен
|
||||
# define PRIVATE_DECLARATION(export)
|
||||
|
||||
//! Macro to start definition of private section
|
||||
//! \~\brief
|
||||
//! \~english Macro to start definition of private section
|
||||
//! \~russian Макрос для начала реализации частной секции
|
||||
# define PRIVATE_DEFINITION_START(Class)
|
||||
|
||||
//! Macro to end definition of private section
|
||||
//! \~\brief
|
||||
//! \~english Macro to end definition of private section
|
||||
//! \~russian Макрос для окончания реализации частной секции
|
||||
# define PRIVATE_DEFINITION_END(Class)
|
||||
|
||||
//! Macro to access private section by pointer
|
||||
//! \~\brief
|
||||
//! \~english Macro to access private section by pointer
|
||||
//! \~russian Макрос для доступа к частной секции
|
||||
# define PRIVATE
|
||||
|
||||
//! Macro to access private section by pointer without brakes ()
|
||||
//! \~\brief
|
||||
//! \~english Macro to access private section by pointer without brakes ()
|
||||
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
|
||||
# define PRIVATEWB
|
||||
|
||||
//! Macro to start static initializer
|
||||
//! \~\brief
|
||||
//! \~english Macro to start static initializer
|
||||
//! \~russian Макрос для начала статической инициализации
|
||||
# define STATIC_INITIALIZER_BEGIN
|
||||
|
||||
//! Macro to end static initializer
|
||||
//! \~\brief
|
||||
//! \~english Macro to end static initializer
|
||||
//! \~russian Макрос для окончания статической инициализации
|
||||
# define STATIC_INITIALIZER_END
|
||||
|
||||
|
||||
#undef MICRO_PIP
|
||||
#undef FREERTOS
|
||||
#endif //DOXYGEN
|
||||
|
||||
#ifdef CC_AVR_GCC
|
||||
# include <ArduinoSTL.h>
|
||||
#endif
|
||||
#include <functional>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <atomic>
|
||||
|
||||
#ifdef WINDOWS
|
||||
# ifdef CC_VC
|
||||
# define SHUT_RDWR 2
|
||||
@@ -139,6 +225,8 @@
|
||||
extern long long __pi_perf_freq;
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
#ifdef ANDROID
|
||||
///# define tcdrain(fd) ioctl(fd, TCSBRK, 1)
|
||||
//inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
|
||||
@@ -161,7 +249,6 @@
|
||||
#ifdef NDEBUG
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
#include <cassert>
|
||||
#ifndef assert
|
||||
# define assert(x)
|
||||
# define assertm(exp, msg)
|
||||
@@ -221,7 +308,7 @@
|
||||
# define DEPRECATED
|
||||
#endif
|
||||
|
||||
|
||||
#endif //DOXYGEN
|
||||
// Private data macros
|
||||
#ifndef DOXYGEN
|
||||
|
||||
@@ -274,28 +361,47 @@
|
||||
} _PIP_ADD_COUNTER(_pip_initializer_);
|
||||
|
||||
|
||||
#ifdef FREERTOS
|
||||
# define PIP_MIN_MSLEEP 10.
|
||||
#else
|
||||
# define PIP_MIN_MSLEEP 1.
|
||||
//! \~\brief
|
||||
//! \~english Minimal sleep in milliseconds for internal PIP using
|
||||
//! \~russian Минимальное значание задержки в милисекундах для внутреннего использования в библиотеке PIP
|
||||
//! \~\details
|
||||
//! \~english Using in \a piMinSleep(), \a PIThread, \a PITimer::Pool. By default 1ms.
|
||||
//! \~russian Используется в \a piMinSleep(), \a PIThread, \a PITimer::Pool. По умолчанию равна 1мс.
|
||||
#ifndef PIP_MIN_MSLEEP
|
||||
# ifndef MICRO_PIP
|
||||
# define PIP_MIN_MSLEEP 1.
|
||||
# else
|
||||
# define PIP_MIN_MSLEEP 10.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
//! Macro used for infinite loop
|
||||
//! \~\brief
|
||||
//! \~english Macro used for infinite loop
|
||||
//! \~russian Макрос для бесконечного цикла
|
||||
#define FOREVER for (;;)
|
||||
|
||||
//! Macro used for infinite wait
|
||||
#define FOREVER_WAIT FOREVER msleep(PIP_MIN_MSLEEP);
|
||||
//! \~\brief
|
||||
//! \~english Macro used for infinite wait
|
||||
//! \~russian Макрос для бесконечного ожидания
|
||||
#define FOREVER_WAIT FOREVER piMinSleep;
|
||||
|
||||
//! Macro used for infinite wait
|
||||
#define WAIT_FOREVER FOREVER msleep(PIP_MIN_MSLEEP);
|
||||
//! \~\brief
|
||||
//! \~english Macro used for infinite wait
|
||||
//! \~russian Макрос для бесконечного ожидания
|
||||
#define WAIT_FOREVER FOREVER piMinSleep;
|
||||
|
||||
|
||||
//! global variable enabling output to piCout, default is true
|
||||
//! \~\brief
|
||||
//! \~english Global variable enabling output to piCout, default is true
|
||||
//! \~russian Глобальная переменная, включающая вывод в piCout, при старте true
|
||||
extern PIP_EXPORT bool piDebug;
|
||||
|
||||
//! global variable that set minimum real update interval
|
||||
//! \~\brief
|
||||
//! \~english Global variable that set minimum real update interval
|
||||
//! for function PIInit::mountInfo(), default is 10000 ms
|
||||
//! \~russian Глобальная переменная минимального ожидания между реальным обновлением
|
||||
//! в методе PIInit::mountInfo(), по умолчанию 10000 мс
|
||||
extern PIP_EXPORT double piMountInfoRefreshIntervalMs;
|
||||
|
||||
typedef unsigned char uchar;
|
||||
@@ -306,12 +412,20 @@ typedef unsigned long long ullong;
|
||||
typedef long long llong;
|
||||
typedef long double ldouble;
|
||||
|
||||
/*! @brief Templated function for swap two values
|
||||
* \details Example:\n \snippet piincludes.cpp swap */
|
||||
//! \~\brief
|
||||
//! \~english Templated function for swap two values
|
||||
//! \~russian Шаблонный метод для перестановки двух значений
|
||||
//! \~\details
|
||||
//! \~english Example:\n \snippet piincludes.cpp swap
|
||||
//! \~russian Пример:\n \snippet piincludes.cpp swap
|
||||
template<typename T> inline void piSwap(T & f, T & s) {T t(std::move(f)); f = std::move(s); s = std::move(t);}
|
||||
|
||||
/*! @brief Templated function for swap two values without "="
|
||||
* \details Example:\n \snippet piincludes.cpp swapBinary */
|
||||
//! \~\brief
|
||||
//! \~english Templated function for swap two values without "="
|
||||
//! \~russian Шаблонный метод для перестановки двух значений без использования "="
|
||||
//! \~\details
|
||||
//! \~english Example:\n \snippet piincludes.cpp swapBinary
|
||||
//! \~russian Пример:\n \snippet piincludes.cpp swapBinary
|
||||
template<typename T> inline void piSwapBinary(T & f, T & s) {
|
||||
if ((size_t*)&f == (size_t*)&s) return;
|
||||
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
|
||||
@@ -346,8 +460,12 @@ template<> inline void piSwapBinary(const void *& f, const void *& s) {
|
||||
}
|
||||
|
||||
|
||||
/*! @brief Function for compare two values without "=" by raw content
|
||||
* \details Example:\n \snippet piincludes.cpp compareBinary */
|
||||
//! \~\brief
|
||||
//! \~english Function for compare two values without "==" by raw content
|
||||
//! \~russian Метод для сравнения двух значений без использования "==" (по сырому содержимому)
|
||||
//! \~\details
|
||||
//! \~english Example:\n \snippet piincludes.cpp compareBinary
|
||||
//! \~russian Пример:\n \snippet piincludes.cpp compareBinary
|
||||
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (((const uchar*)f)[i] != ((const uchar*)s)[i])
|
||||
@@ -355,152 +473,323 @@ inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! @brief Templated function return round of float falue
|
||||
* \details Round is the nearest integer value \n
|
||||
* There are some macros:
|
||||
* - \c piRoundf for "float"
|
||||
* - \c piRoundd for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp round */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return round of float falue
|
||||
//! \~russian Шаблонный метод, возвращающий округленное значение
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Round is the nearest integer value \n
|
||||
//! There are some macros:
|
||||
//! - \c piRoundf for "float"
|
||||
//! - \c piRoundd for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp round
|
||||
//! \~russian
|
||||
//! Округленное значение - это ближайшее целое число\n
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piRoundf для "float"
|
||||
//! - \c piRoundd для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp round
|
||||
template<typename T> inline constexpr int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
|
||||
|
||||
/*! @brief Templated function return floor of float falue
|
||||
* \details Floor is the largest integer that is not greater than value \n
|
||||
* There are some macros:
|
||||
* - \c piFloorf for "float"
|
||||
* - \c piFloord for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp floor */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return floor of float falue
|
||||
//! \~russian Шаблонный метод, возвращающий floor значение
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Floor is the largest integer that is not greater than "v" \n
|
||||
//! There are some macros:
|
||||
//! - \c piFloorf for "float"
|
||||
//! - \c piFloord for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp floor
|
||||
//! \~russian
|
||||
//! Floor значение - это наибольшее целое, не большее чем "v"\n
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piFloorf для "float"
|
||||
//! - \c piFloord для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp floor
|
||||
template<typename T> inline constexpr int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
|
||||
|
||||
/*! @brief Templated function return ceil of float falue
|
||||
* \details Ceil is the smallest integer that is not less than value \n
|
||||
* There are some macros:
|
||||
* - \c piCeilf for "float"
|
||||
* - \c piCeild for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp ceil */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return ceil of float falue
|
||||
//! \~russian Шаблонный метод, возвращающий ceil значение
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Ceil is the smallest integer that is not less than "v" \n
|
||||
//! There are some macros:
|
||||
//! - \c piCeilf for "float"
|
||||
//! - \c piCeild for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp ceil
|
||||
//! \~russian
|
||||
//! Ceil значение - это наименьшее целое, не меньшее чем "v" \n
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piCeilf для "float"
|
||||
//! - \c piCeild для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp ceil
|
||||
template<typename T> inline constexpr int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
|
||||
|
||||
/*! @brief Templated function return absolute of numeric falue
|
||||
* \details Absolute is the positive or equal 0 value \n
|
||||
* There are some macros:
|
||||
* - \c piAbss for "short"
|
||||
* - \c piAbsi for "int"
|
||||
* - \c piAbsl for "long"
|
||||
* - \c piAbsll for "llong"
|
||||
* - \c piAbsf for "float"
|
||||
* - \c piAbsd for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp abs */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return absolute of numeric falue
|
||||
//! \~russian Шаблонный метод, возвращающий модуль числового значения
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Absolute is the positive or equal 0 value \n
|
||||
//! There are some macros:
|
||||
//! - \c piAbss for "short"
|
||||
//! - \c piAbsi for "int"
|
||||
//! - \c piAbsl for "long"
|
||||
//! - \c piAbsll for "llong"
|
||||
//! - \c piAbsf for "float"
|
||||
//! - \c piAbsd for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp abs
|
||||
//! \~russian
|
||||
//! Модуль числового значения всегда >= 0 \n
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piAbss для "short"
|
||||
//! - \c piAbsi для "int"
|
||||
//! - \c piAbsl для "long"
|
||||
//! - \c piAbsll для "llong"
|
||||
//! - \c piAbsf для "float"
|
||||
//! - \c piAbsd для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp abs
|
||||
template<typename T> inline constexpr T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
||||
|
||||
/*! @brief Templated function return minimum of two values
|
||||
* \details There are some macros:
|
||||
* - \c piMins for "short"
|
||||
* - \c piMini for "int"
|
||||
* - \c piMinl for "long"
|
||||
* - \c piMinll for "llong"
|
||||
* - \c piMinf for "float"
|
||||
* - \c piMind for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp min2 */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return minimum of two values
|
||||
//! \~russian Шаблонный метод, возвращающий минимум из двух значений
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! There are some macros:
|
||||
//! - \c piMins for "short"
|
||||
//! - \c piMini for "int"
|
||||
//! - \c piMinl for "long"
|
||||
//! - \c piMinll for "llong"
|
||||
//! - \c piMinf for "float"
|
||||
//! - \c piMind for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp min2
|
||||
//! \~russian
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piMins для "short"
|
||||
//! - \c piMini для "int"
|
||||
//! - \c piMinl для "long"
|
||||
//! - \c piMinll для "llong"
|
||||
//! - \c piMinf для "float"
|
||||
//! - \c piMind для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp min2
|
||||
template<typename T> inline constexpr T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
|
||||
|
||||
/*! @brief Templated function return minimum of tree values
|
||||
* \details There are some macros:
|
||||
* - \c piMins for "short"
|
||||
* - \c piMini for "int"
|
||||
* - \c piMinl for "long"
|
||||
* - \c piMinll for "llong"
|
||||
* - \c piMinf for "float"
|
||||
* - \c piMind for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp min3 */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return minimum of tree values
|
||||
//! \~russian Шаблонный метод, возвращающий минимум из трех значений
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! There are some macros:
|
||||
//! - \c piMins for "short"
|
||||
//! - \c piMini for "int"
|
||||
//! - \c piMinl for "long"
|
||||
//! - \c piMinll for "llong"
|
||||
//! - \c piMinf for "float"
|
||||
//! - \c piMind for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp min3
|
||||
//! \~russian
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piMins для "short"
|
||||
//! - \c piMini для "int"
|
||||
//! - \c piMinl для "long"
|
||||
//! - \c piMinll для "llong"
|
||||
//! - \c piMinf для "float"
|
||||
//! - \c piMind для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp min3
|
||||
template<typename T> inline constexpr T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
|
||||
|
||||
/*! @brief Templated function return maximum of two values
|
||||
* \details There are some macros:
|
||||
* - \c piMaxs for "short"
|
||||
* - \c piMaxi for "int"
|
||||
* - \c piMaxl for "long"
|
||||
* - \c piMaxll for "llong"
|
||||
* - \c piMaxf for "float"
|
||||
* - \c piMaxd for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp max2 */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return maximum of two values
|
||||
//! \~russian Шаблонный метод, возвращающий максимум из двух значений
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! There are some macros:
|
||||
//! - \c piMaxs for "short"
|
||||
//! - \c piMaxi for "int"
|
||||
//! - \c piMaxl for "long"
|
||||
//! - \c piMaxll for "llong"
|
||||
//! - \c piMaxf for "float"
|
||||
//! - \c piMaxd for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp max2
|
||||
//! \~russian
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piMaxs для "short"
|
||||
//! - \c piMaxi для "int"
|
||||
//! - \c piMaxl для "long"
|
||||
//! - \c piMaxll для "llong"
|
||||
//! - \c piMaxf для "float"
|
||||
//! - \c piMaxd для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp max2
|
||||
template<typename T> inline constexpr T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
|
||||
|
||||
/*! @brief Templated function return maximum of tree values
|
||||
* \details There are some macros:
|
||||
* - \c piMaxs for "short"
|
||||
* - \c piMaxi for "int"
|
||||
* - \c piMaxl for "long"
|
||||
* - \c piMaxll for "llong"
|
||||
* - \c piMaxf for "float"
|
||||
* - \c piMaxd for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp max3 */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return maximum of tree values
|
||||
//! \~russian Шаблонный метод, возвращающий максимум из трех значений
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! There are some macros:
|
||||
//! - \c piMaxs for "short"
|
||||
//! - \c piMaxi for "int"
|
||||
//! - \c piMaxl for "long"
|
||||
//! - \c piMaxll for "llong"
|
||||
//! - \c piMaxf for "float"
|
||||
//! - \c piMaxd for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp max3
|
||||
//! \~russian
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piMaxs для "short"
|
||||
//! - \c piMaxi для "int"
|
||||
//! - \c piMaxl для "long"
|
||||
//! - \c piMaxll для "llong"
|
||||
//! - \c piMaxf для "float"
|
||||
//! - \c piMaxd для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp max3
|
||||
template<typename T> inline constexpr T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
|
||||
|
||||
/*! @brief Templated function return clamped value
|
||||
* \details Clamped is the not greater than "max" and not lesser than "min" value \n
|
||||
* There are some macros:
|
||||
* - \c piClamps for "short"
|
||||
* - \c piClampi for "int"
|
||||
* - \c piClampl for "long"
|
||||
* - \c piClampll for "llong"
|
||||
* - \c piClampf for "float"
|
||||
* - \c piClampd for "double"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp clamp */
|
||||
//! \~\brief
|
||||
//! \~english Templated function return clamped value
|
||||
//! \~russian Шаблонный метод, возвращающий ограниченное значение
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Clamped is the not greater than "max" and not lesser than "min" value \n
|
||||
//! There are some macros:
|
||||
//! - \c piClamps for "short"
|
||||
//! - \c piClampi for "int"
|
||||
//! - \c piClampl for "long"
|
||||
//! - \c piClampll for "llong"
|
||||
//! - \c piClampf for "float"
|
||||
//! - \c piClampd for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp clamp
|
||||
//! \~russian
|
||||
//! Ограниченное значение - не больше чем "max" и не меньше чем "min"
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piClamps для "short"
|
||||
//! - \c piClampi для "int"
|
||||
//! - \c piClampl для "long"
|
||||
//! - \c piClampll для "llong"
|
||||
//! - \c piClampf для "float"
|
||||
//! - \c piClampd для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp clamp
|
||||
template<typename T> inline constexpr T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
|
||||
|
||||
/// Function inverse byte order in memory block
|
||||
//! \~\brief
|
||||
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
|
||||
//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1])
|
||||
inline void piLetobe(void * data, int size) {
|
||||
for (int i = 0; i < size / 2; i++)
|
||||
piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]);
|
||||
}
|
||||
|
||||
/// @brief Templated function that inverse byte order of value "v"
|
||||
//! \~\brief
|
||||
//! \~english Function for compare two numeric values with epsilon
|
||||
//! \~russian Метод для сравнения двух чисел с порогом
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! There are some macros:
|
||||
//! - \c piComparef for "float"
|
||||
//! - \c piCompared for "double"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp compare
|
||||
//! \~russian
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piComparef для "float"
|
||||
//! - \c piCompared для "double"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp compare
|
||||
template<typename T>
|
||||
inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric_limits<T>::epsilon()) {
|
||||
return piAbs(a - b) <= epsilon;
|
||||
}
|
||||
|
||||
//! \~\brief
|
||||
//! \~english Templated function that inverse byte order of value "v"
|
||||
//! \~russian Шаблонный метод, меняющий порядок байт в переменной "v"
|
||||
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
|
||||
|
||||
/*! @brief Templated function that returns "v" with inversed byte order
|
||||
* \details This function used to convert values between little and big endian \n
|
||||
* There are some macros:
|
||||
* - \c piLetobes for "ushort"
|
||||
* - \c piLetobei for "uint"
|
||||
* - \c piLetobel for "ulong"
|
||||
* - \c piLetobell for "ullong"
|
||||
*
|
||||
* Example:
|
||||
* \snippet piincludes.cpp letobe */
|
||||
//! \~\brief
|
||||
//! \~english Templated function that returns "v" with inversed byte order
|
||||
//! \~russian Шаблонный метод, возвращающий переменную "v" с измененным порядком байт
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! This function used to convert values between little and big endian \n
|
||||
//! There are some macros:
|
||||
//! - \c piLetobes for "ushort"
|
||||
//! - \c piLetobei for "uint"
|
||||
//! - \c piLetobel for "ulong"
|
||||
//! - \c piLetobell for "ullong"
|
||||
//!
|
||||
//! Example:
|
||||
//! \snippet piincludes.cpp letobe
|
||||
//! \~russian
|
||||
//! Этот метод используется для изменения порядка байт между little и big endian
|
||||
//! Есть несколько макросов:
|
||||
//! - \c piLetobes для "ushort"
|
||||
//! - \c piLetobei для "uint"
|
||||
//! - \c piLetobel для "ulong"
|
||||
//! - \c piLetobell для "ullong"
|
||||
//!
|
||||
//! Пример:
|
||||
//! \snippet piincludes.cpp letobe
|
||||
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
|
||||
|
||||
// specialization
|
||||
template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);}
|
||||
template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
||||
template<> inline uint16_t piLetobe(const uint16_t & v) {return (v << 8) | (v >> 8);}
|
||||
template<> inline uint32_t piLetobe(const uint32_t & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
||||
template<> inline float piLetobe(const float & v) {
|
||||
union _pletobe_f {
|
||||
_pletobe_f(const float &f_) {f = f_;}
|
||||
float f;
|
||||
uint v;
|
||||
uint32_t v;
|
||||
};
|
||||
_pletobe_f a(v);
|
||||
a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000);
|
||||
return a.f;
|
||||
}
|
||||
|
||||
/// @brief Generic hash function, implements murmur3/32 algorithm
|
||||
//! \~\brief
|
||||
//! \~english Generic hash function, implements murmur3/32 algorithm
|
||||
//! \~russian Хэш-функция общего назначения, по алгоритму murmur3/32
|
||||
inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
|
||||
if (!data || len <= 0) return 0u;
|
||||
uint h = seed;
|
||||
@@ -558,6 +847,8 @@ template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar
|
||||
|
||||
#define piRoundf piRound<float>
|
||||
#define piRoundd piRound<double>
|
||||
#define piComparef piCompare<float>
|
||||
#define piCompared piCompare<double>
|
||||
#define piFloorf piFloor<float>
|
||||
#define piFloord piFloor<double>
|
||||
#define piCeilf piCeil<float>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/*! @file pibitarray.h
|
||||
* @brief Bit array
|
||||
/*! \file pibitarray.h
|
||||
* \~\brief
|
||||
* \~english Bit array
|
||||
* \~russian Битовый массив
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -21,6 +21,85 @@
|
||||
#include "pistringlist.h"
|
||||
#include <iostream>
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \class PIByteArray pibytearray.h
|
||||
//!
|
||||
//! \~\brief
|
||||
//! \~english The %PIByteArray class provides an array of bytes
|
||||
//! \~russian Класс %PIByteArray представляет собой массив байтов
|
||||
//! \}
|
||||
//!
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! %PIByteArray used to store raw bytes.
|
||||
//! 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
|
||||
//! to manipulate it.
|
||||
//! \~russian
|
||||
//! %PIByteArray используется для хранения байтов.
|
||||
//! Он может быть сконструирован из любых даных.
|
||||
//! Можно использовать %PIByteArray как потоковый объект
|
||||
//! для сериализации/десериализации любых типов и данных.
|
||||
//! Этот класс наследован от 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
|
||||
//! of array.
|
||||
//! In addition there are Hex and Base64 convertions
|
||||
//! \~russian
|
||||
//! %PIByteArray может быть использован для сохранения любых данных и работы с ними.
|
||||
//! Он предоставляет множество операторов для сохранения/извлечения общих типов.
|
||||
//! Операторы сохранения добавляют данные в конец массива, а операторы извлечения
|
||||
//! берут данные из его начала.
|
||||
//!
|
||||
//! \~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
|
||||
//!
|
||||
//! \~english \section PIByteArray_sec1 Attention
|
||||
//! \~russian \section PIByteArray_sec1 Внимание
|
||||
//! \~english
|
||||
//! Stream operator of %PIByteArray store byte array as vector, not simply append
|
||||
//! content of byte array. This operators useful to transmit custom data as %PIByteArray
|
||||
//! packed into parent byte array, e.g. to form packet from %PIByteArray.
|
||||
//! To append one byte array to another use funtion \a append().
|
||||
//! \~russian
|
||||
//! Потоковый оператор для типа %PIByteArray сохраняет его как контейнер,
|
||||
//! а не просто добавляет его содержимое в конец. Этот оператор полезен для управляемой
|
||||
//! упаковки произвольных данных в виде %PIByteArray.
|
||||
//! Для добавления содержимого одного байтового массива к другому используется
|
||||
//! метов \a append().
|
||||
//! \~\snippet pibytearray.cpp 3
|
||||
//!
|
||||
|
||||
|
||||
static const uchar base64Table[64] = {
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
@@ -221,22 +300,48 @@ PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
|
||||
}
|
||||
|
||||
|
||||
uchar PIByteArray::checksumPlain8() const {
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! This is simple sum of all bytes, if "inverse" then add 1 and inverse.
|
||||
//! Pseudocode:
|
||||
//! \~russian
|
||||
//! Это простая сумма всех байтов, если "inverse", то ещё добавляется 1 и инвертируется результат.
|
||||
//! Псевдокод:
|
||||
//! \~\code
|
||||
//! for (i)
|
||||
//! sum += at(i);
|
||||
//! if (inverse) return ~(sum + 1);
|
||||
//! else return sum;
|
||||
//! \endcode
|
||||
uchar PIByteArray::checksumPlain8(bool inverse) const {
|
||||
uchar c = 0;
|
||||
int sz = size_s();
|
||||
for (int i = 0; i < sz; ++i)
|
||||
c += at(i);
|
||||
c = ~(c + 1);
|
||||
if (inverse) c = ~(c + 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
uint PIByteArray::checksumPlain32() const {
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! This is sum of all bytes multiplied by index+1, if inverse then add 1 and inverse.
|
||||
//! Pseudocode:
|
||||
//! \~russian
|
||||
//! Это простая сумма всех байтов, умноженных на индекс+1, если "inverse", то ещё добавляется 1 и инвертируется результат.
|
||||
//! Псевдокод:
|
||||
//! \~\code
|
||||
//! for (i)
|
||||
//! sum += at(i) * (i + 1);
|
||||
//! if (inverse) return ~(sum + 1);
|
||||
//! else return sum;
|
||||
//! \endcode
|
||||
uint PIByteArray::checksumPlain32(bool inverse) const {
|
||||
uint c = 0;
|
||||
int sz = size_s();
|
||||
for (int i = 0; i < sz; ++i)
|
||||
c += at(i) * (i + 1);
|
||||
c = ~(c + 1);
|
||||
if (inverse) c = ~(c + 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file pibytearray.h
|
||||
* @brief Byte array
|
||||
/*! \file pibytearray.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Byte array
|
||||
* \~russian Байтовый массив
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -27,8 +30,9 @@
|
||||
#include "pibitarray.h"
|
||||
#include "pimap.h"
|
||||
#include "pivector2d.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef FREERTOS
|
||||
#ifdef MICRO_PIP
|
||||
# define _TYPENAME_(T) "?"
|
||||
#else
|
||||
# define _TYPENAME_(T) typeid(T).name()
|
||||
@@ -38,74 +42,49 @@ class PIString;
|
||||
class PIByteArray;
|
||||
|
||||
|
||||
/*! @class PIByteArray
|
||||
* @brief The PIByteArray class provides an array of bytes
|
||||
* @details PIByteArray used to store raw bytes.
|
||||
* 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
|
||||
* to manipulate it.
|
||||
*
|
||||
* @section PIByteArray_sec0 Usage
|
||||
* %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
|
||||
* of array.
|
||||
* In addition there are Hex and Base64 convertions
|
||||
*
|
||||
* 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:
|
||||
* @snippet pibytearray.cpp 0
|
||||
*
|
||||
* Or you can descibe stream operator of your own type and store/restore vectors of
|
||||
* your type:
|
||||
* @snippet pibytearray.cpp 1
|
||||
*
|
||||
* 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.
|
||||
* @snippet pibytearray.cpp 2
|
||||
*
|
||||
* @section PIByteArray_sec1 Attention
|
||||
* Stream operator of %PIByteArray store byte array as vector, not simply append
|
||||
* content of byte array. This operators useful to transmit custom data as %PIByteArray
|
||||
* packed into parent byte array, e.g. to form packet from %PIByteArray.
|
||||
* To append one byte array to another use funtion \a append().
|
||||
* @snippet pibytearray.cpp 3
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
class PIP_EXPORT PIByteArray: public PIDeque<uchar>
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructs an empty byte array
|
||||
//! \~english Constructs an empty byte array
|
||||
//! \~russian Создает пустой байтовый массив
|
||||
PIByteArray() {;}
|
||||
|
||||
//! \~english Constructs copy of byte array "o"
|
||||
//! \~russian Создает копию байтового массива "o"
|
||||
PIByteArray(const PIByteArray & o): PIDeque<uchar>(o) {}
|
||||
|
||||
//! \~english Constructs copy of byte array "o"
|
||||
//! \~russian Создает копию байтового массива "o"
|
||||
PIByteArray(const PIDeque<uchar> & o): PIDeque<uchar>(o) {}
|
||||
|
||||
PIByteArray(PIByteArray && o): PIDeque<uchar>(std::move(o)) {}
|
||||
|
||||
//! Constructs 0-filled byte array with size "size"
|
||||
//! \~english Constructs 0-filled byte array with size "size"
|
||||
//! \~russian Создает заполненный "0" байтовый массив размером "size"
|
||||
PIByteArray(const uint size) {resize(size);}
|
||||
|
||||
//! Constructs byte array from data "data" and size "size"
|
||||
//! \~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)) {}
|
||||
|
||||
//! Constructs byte array with size "size" filled by "t"
|
||||
//! \~english Constructs byte array with size "size" filled by "t"
|
||||
//! \~russian Создает заполненный "t" байтовый массив размером "size"
|
||||
PIByteArray(const uint size, uchar t): PIDeque<uchar>(size, t) {}
|
||||
|
||||
|
||||
//! Help struct to store/restore custom blocks of data to/from PIByteArray
|
||||
//! \~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:
|
||||
//! Constructs data block
|
||||
//! \~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;}
|
||||
//! Constructs data block
|
||||
//! \~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:
|
||||
@@ -113,16 +92,27 @@ public:
|
||||
int s;
|
||||
};
|
||||
|
||||
//! Return resized byte array
|
||||
//! \~english Return resized byte array
|
||||
//! \~russian Возвращает копию байтового массива с измененным размером
|
||||
PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
|
||||
|
||||
//! Convert data to Base 64 and return this byte array
|
||||
//! \~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);
|
||||
}
|
||||
|
||||
|
||||
//! \~english Convert data to Base 64 and return this byte array
|
||||
//! \~russian Преобразует данные в Base 64 и возвращает текущий массив
|
||||
PIByteArray & convertToBase64();
|
||||
|
||||
//! Convert data from Base 64 and return this byte array
|
||||
//! \~english Convert data from Base 64 and return this byte array
|
||||
//! \~russian Преобразует данные из Base 64 и возвращает текущий массив
|
||||
PIByteArray & convertFromBase64();
|
||||
|
||||
//! Return converted to Base 64 data
|
||||
//! \~english Return converted to Base 64 data
|
||||
//! \~russian Возвращает копию байтового массива, преобразованного в Base 64
|
||||
PIByteArray toBase64() const;
|
||||
|
||||
PIByteArray & compressRLE(uchar threshold = 192);
|
||||
@@ -130,36 +120,40 @@ public:
|
||||
PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;}
|
||||
PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;}
|
||||
|
||||
//! \~english Return string representation of data, each byte in "base" base, separated by spaces
|
||||
//! \~russian Возвращает текстовое представление байтового массива, каждый байт в "base" системе, с пробелами
|
||||
PIString toString(int base = 16) const;
|
||||
|
||||
//! Returns a hex encoded copy of the byte array.
|
||||
//! \~english
|
||||
//! Returns a hex encoded copy of the byte array, without spaces.
|
||||
//! The hex encoding uses the numbers 0-9 and the letters a-f.
|
||||
//! \~russian
|
||||
//! Возвращает шестнадцатеричное представление массива, без пробелов.
|
||||
//! Оно использует цифры 0-9 и буквы a-f.
|
||||
PIString toHex() const;
|
||||
|
||||
//! Add to the end data "data" with size "size"
|
||||
//! \~english Add to the end data "data" with size "size"
|
||||
//! \~russian Добавляет в конец массива данные по указателю "data" размером "size"
|
||||
PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
|
||||
|
||||
//! Add to the end byte array "data"
|
||||
//! \~english Add to the end byte array "data"
|
||||
//! \~russian Добавляет в конец массива содержимое массива "data"
|
||||
PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;}
|
||||
|
||||
//! Add to the end "t"
|
||||
//! \~english Add to the end "t"
|
||||
//! \~russian Добавляет в конец массива байт "t"
|
||||
PIByteArray & append(uchar t) {push_back(t); return *this;}
|
||||
|
||||
//! Returns 8-bit checksum
|
||||
//! sum all bytes, add 1, inverse
|
||||
//! Pseudocode:
|
||||
//! sum += at(i);
|
||||
//! return ~(sum + 1)
|
||||
uchar checksumPlain8() const;
|
||||
//! \~english Returns 8-bit checksum
|
||||
//! \~russian Возвращает 8-битную контрольную сумму
|
||||
uchar checksumPlain8(bool inverse = true) const;
|
||||
|
||||
//! Returns 32-bit checksum
|
||||
//! sum all bytes multiplyed by index+1, add 1, inverse
|
||||
//! Pseudocode:
|
||||
//! sum += at(i) * (i + 1);
|
||||
//! return ~(sum + 1)
|
||||
uint checksumPlain32() const;
|
||||
//! \~english Returns 32-bit checksum
|
||||
//! \~russian Возвращает 32-битную контрольную сумму
|
||||
uint checksumPlain32(bool inverse = true) const;
|
||||
|
||||
//! Returns hash
|
||||
//! \~english Returns hash of content
|
||||
//! \~russian Возвращает хэш содержимого
|
||||
uint hash() const;
|
||||
|
||||
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
|
||||
@@ -172,7 +166,8 @@ public:
|
||||
|
||||
static PIByteArray fromHex(PIString str);
|
||||
|
||||
//! Return converted from Base 64 data
|
||||
//! \~english Return converted from Base 64 data
|
||||
//! \~russian Возвращает массив из Base 64 представления
|
||||
static PIByteArray fromBase64(const PIByteArray & base64);
|
||||
static PIByteArray fromBase64(const PIString & base64);
|
||||
|
||||
@@ -187,43 +182,58 @@ public:
|
||||
|
||||
};
|
||||
|
||||
//! \relatesalso PIByteArray @brief Byte arrays compare operator
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Byte arrays compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
|
||||
if (v0.size() == v1.size()) {
|
||||
for (uint i = 0; i < v0.size(); ++i)
|
||||
if (v0[i] != v1[i])
|
||||
return v0[i] < v1[i];
|
||||
return false;
|
||||
if (v0.isEmpty()) return false;
|
||||
return memcmp(v0.data(), v1.data(), v0.size()) < 0;
|
||||
}
|
||||
return v0.size() < v1.size();
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Byte arrays compare operator
|
||||
inline bool operator ==(PIByteArray & f, PIByteArray & s) {
|
||||
if (f.size_s() != s.size_s())
|
||||
return false;
|
||||
for (int i = 0; i < f.size_s(); ++i)
|
||||
if (f[i] != s[i])
|
||||
return false;
|
||||
return true;
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Byte arrays compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >(const PIByteArray & v0, const PIByteArray & v1) {
|
||||
if (v0.size() == v1.size()) {
|
||||
if (v0.isEmpty()) return false;
|
||||
return memcmp(v0.data(), v1.data(), v0.size()) > 0;
|
||||
}
|
||||
return v0.size() > v1.size();
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Byte arrays compare operator
|
||||
inline bool operator !=(PIByteArray & f, PIByteArray & s) {
|
||||
if (f.size_s() != s.size_s())
|
||||
return true;
|
||||
for (int i = 0; i < f.size_s(); ++i)
|
||||
if (f[i] != s[i])
|
||||
return true;
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Byte arrays compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator ==(const PIByteArray & v0, const PIByteArray & v1) {
|
||||
if (v0.size() == v1.size()) {
|
||||
if (v0.isEmpty()) return true;
|
||||
return memcmp(v0.data(), v1.data(), v0.size()) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Byte arrays compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator !=(const PIByteArray & v0, const PIByteArray & v1) {
|
||||
if (v0.size() == v1.size()) {
|
||||
if (v0.isEmpty()) return false;
|
||||
return memcmp(v0.data(), v1.data(), v0.size()) != 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
//! \relatesalso PIByteArray @brief Output to std::ostream operator
|
||||
//! \relatesalso PIByteArray \brief Output to std::ostream operator
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
|
||||
#endif
|
||||
|
||||
//! \relatesalso PIByteArray @brief Output to PICout operator
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Output operator to \a PICout
|
||||
//! \~russian Оператор вывода в \a PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
|
||||
|
||||
|
||||
@@ -232,16 +242,24 @@ PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
|
||||
// store operators for basic types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator for any trivial copyable type
|
||||
//! \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();
|
||||
@@ -250,10 +268,14 @@ inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator, see \ref PIByteArray_sec1 for details
|
||||
//! \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 @brief Store operator, see \ref PIByteArray_sec1 for details
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator, see \ref PIByteArray_sec1 for details
|
||||
//! \~russian Оператор сохранения, подробнее в \ref PIByteArray_sec1
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
|
||||
int os = s.size_s();
|
||||
if (v.s > 0) {
|
||||
@@ -263,7 +285,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator for PIVector of any trivial copyable type
|
||||
//! \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>
|
||||
@@ -285,7 +309,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator for PIDeque of any trivial copyable type
|
||||
//! \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>
|
||||
@@ -307,7 +333,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator for PIVector2D of any trivial copyable type
|
||||
//! \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>
|
||||
@@ -328,10 +356,14 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store operator
|
||||
//! \~russian Оператор сохранения
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
|
||||
|
||||
//! \relatesalso PIPair @brief Store operator
|
||||
//! \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;}
|
||||
|
||||
@@ -341,16 +373,24 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v
|
||||
// restore operators for basic types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator
|
||||
//! \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 @brief Restore operator
|
||||
//! \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 @brief Restore operator
|
||||
//! \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 @brief Restore operator for any trivial copyable type
|
||||
//! \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)) {
|
||||
@@ -362,10 +402,14 @@ inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
//! \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 @brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore operator, see \ref PIByteArray_sec1 for details
|
||||
//! \~russian Оператор извлечения, подробнее в \ref PIByteArray_sec1
|
||||
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);
|
||||
@@ -378,7 +422,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator for PIVector of any trivial copyable type
|
||||
//! \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>
|
||||
@@ -409,7 +455,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator for PIDeque of any trivial copyable type
|
||||
//! \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>
|
||||
@@ -440,7 +488,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator for PIVector2D of any trivial copyable type
|
||||
//! \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>
|
||||
@@ -473,10 +523,14 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator
|
||||
//! \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 @brief Restore operator
|
||||
//! \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;}
|
||||
|
||||
@@ -486,7 +540,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >
|
||||
// store operators for complex types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator for PIVector of any compound type
|
||||
//! \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());
|
||||
@@ -494,7 +550,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator for PIDeque of any compound type
|
||||
//! \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());
|
||||
@@ -502,7 +560,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Store operator for PIVector2D of any compound type
|
||||
//! \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();
|
||||
@@ -515,7 +575,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||
// restore operators for complex types
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator for PIVector of any compound type
|
||||
//! \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) {
|
||||
@@ -528,7 +590,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator for PIDeque of any compound type
|
||||
//! \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) {
|
||||
@@ -541,7 +605,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Restore operator for PIVector2D of any compound type
|
||||
//! \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) {
|
||||
@@ -561,6 +627,9 @@ inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||
// 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());
|
||||
@@ -571,6 +640,9 @@ inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
|
||||
}
|
||||
|
||||
|
||||
//! \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) {
|
||||
@@ -606,16 +678,29 @@ inline PIByteArray & operator >>(PIByteArray & s, T & ) {
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Returns PIByteArray::hash() of "ba"
|
||||
//! \~russian Возвращает PIByteArray::hash() от "ba"
|
||||
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Swap contents betwee "f" and "s"
|
||||
//! \~russian Меняет содержимое массивов "f" и "s"
|
||||
template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Store "value" to bytearray and returns it
|
||||
//! \~russian Сохраняет "value" в байтовый массив и возвращает его
|
||||
template <typename T> PIByteArray piSerialize(const T & value) {
|
||||
PIByteArray ret;
|
||||
ret << value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! \relatesalso PIByteArray
|
||||
//! \~english Restore type "T" from bytearray "data" and returns it
|
||||
//! \~russian Извлекает тип "T" из байтового массива "data" и возвращает его
|
||||
template <typename T> T piDeserialize(const PIByteArray & data) {
|
||||
T ret;
|
||||
if (!data.isEmpty()) {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/*! @file pichar.h
|
||||
* @brief Unicode char
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Unicode char
|
||||
@@ -45,11 +42,24 @@ char * __utf8name__ = 0;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*! \class PIChar
|
||||
* @brief Unicode char
|
||||
* \details This class is wrapper around \c "uint".
|
||||
* There are many contructors and information functions
|
||||
*/
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \class PIChar pichar.h
|
||||
//!
|
||||
//! \~\brief
|
||||
//! \~english %PIChar represents a single character
|
||||
//! \~russian %PIChar представляет собой один символ строки
|
||||
//!
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! This class is wrapper around UTF16.
|
||||
//! There are many contructors and information functions
|
||||
//!
|
||||
//! \~russian
|
||||
//! %PIChar хранит один сивол в UTF16. Имеет много контрукторов, геттеров в различные
|
||||
//! кодировки (системную, консольную, UTF8) и информационных функций.
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
ushort charFromCodepage(const char * c, int size, const char * codepage, int * taken = 0) {
|
||||
@@ -81,7 +91,7 @@ ushort charFromCodepage(const char * c, int size, const char * codepage, int * t
|
||||
ret = mbtowc(&wc, c, size);
|
||||
//printf("mbtowc = %d\n", ret);
|
||||
if (ret < 1) return 0;
|
||||
return ushort(int(wc));
|
||||
return ushort(wc);
|
||||
# endif
|
||||
#endif
|
||||
return ushort(c[0]);
|
||||
@@ -324,12 +334,12 @@ char PIChar::toSystem() const {
|
||||
|
||||
|
||||
PIChar PIChar::toUpper() const {
|
||||
if (isAscii()) return PIChar(toupper(ch));
|
||||
if (isAscii()) return PIChar((ushort)toupper(ch));
|
||||
#ifdef PIP_ICU
|
||||
UChar c(0);
|
||||
UErrorCode e((UErrorCode)0);
|
||||
u_strToUpper(&c, 1, (const UChar*)(&ch), 1, 0, &e);
|
||||
return PIChar(c);
|
||||
return PIChar((ushort)c);
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
ushort wc = 0;
|
||||
@@ -337,17 +347,17 @@ PIChar PIChar::toUpper() const {
|
||||
return PIChar(wc);
|
||||
# endif
|
||||
#endif
|
||||
return PIChar(towupper(ch));
|
||||
return PIChar((ushort)towupper(ch));
|
||||
}
|
||||
|
||||
|
||||
PIChar PIChar::toLower() const {
|
||||
if (isAscii()) return PIChar(tolower(ch));
|
||||
if (isAscii()) return PIChar((ushort)tolower(ch));
|
||||
#ifdef PIP_ICU
|
||||
UChar c(0);
|
||||
UErrorCode e((UErrorCode)0);
|
||||
u_strToLower(&c, 1, (const UChar*)(&ch), 1, 0, &e);
|
||||
return PIChar(c);
|
||||
return PIChar((ushort)c);
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
ushort wc = 0;
|
||||
@@ -355,7 +365,7 @@ PIChar PIChar::toLower() const {
|
||||
return PIChar(wc);
|
||||
# endif
|
||||
#endif
|
||||
return PIChar(towlower(ch));
|
||||
return PIChar((ushort)towlower(ch));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file pichar.h
|
||||
* @brief Unicode char
|
||||
/*! \file pichar.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Single string character
|
||||
* \~russian Один символ строки
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -34,97 +37,134 @@ class PIP_EXPORT PIChar
|
||||
friend class PIString;
|
||||
friend PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
|
||||
public:
|
||||
//! Contructs ascii symbol
|
||||
PIChar(const char c) {ch = c; ch &= 0xFF;}
|
||||
//! \~english Contructs Ascii symbol
|
||||
//! \~russian Создает символ Ascii
|
||||
PIChar(char c) {ch = c; ch &= 0xFF;}
|
||||
|
||||
//! Contructs 2-bytes symbol
|
||||
PIChar(const short c) {ch = c;}
|
||||
//! \~english Contructs ascii symbol
|
||||
//! \~russian Создает символ Ascii
|
||||
PIChar(uchar c) {ch = c;}
|
||||
|
||||
//! Contructs 4-bytes symbol
|
||||
PIChar(const int c) {ch = c;}
|
||||
//! \~english Contructs 2-bytes symbol
|
||||
//! \~russian Создает 2-байтный символ
|
||||
PIChar(ushort c = 0) {ch = c;}
|
||||
|
||||
//! Contructs ascii symbol
|
||||
PIChar(const uchar c) {ch = c; ch &= 0xFF;}
|
||||
//! \~english Contructs 2-bytes symbol from `wchar_t`
|
||||
//! \~russian Создает 2-байтный символ из `wchar_t`
|
||||
PIChar(wchar_t c) {ch = c;}
|
||||
|
||||
//! Contructs 2-bytes symbol
|
||||
PIChar(const ushort c) {ch = c;}
|
||||
|
||||
//! Default constructor. Contructs 4-bytes symbol
|
||||
PIChar(const uint c = 0) {ch = c;}
|
||||
|
||||
//! Contructs symbol from no more than 4 bytes of string
|
||||
//! \~english Contructs symbol from system locale and no more than 4 bytes of string
|
||||
//! \~russian Создает символ из системной локали не более 4 байт длины
|
||||
PIChar(const char * c, int * bytes = 0);
|
||||
|
||||
//! Copy operator
|
||||
//! \~english Copy operator
|
||||
//! \~russian Оператор присваивания
|
||||
PIChar & operator =(const char v) {ch = v; return *this;}
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator ==(const PIChar & o) const;
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator !=(const PIChar & o) const {return !(o == *this);}
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >(const PIChar & o) const;
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <(const PIChar & o) const;
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >=(const PIChar & o) const;
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <=(const PIChar & o) const;
|
||||
|
||||
//! Return \b true if symbol is digit ('0' to '9')
|
||||
//! \~english Returns \b true if symbol is digit ('0' to '9')
|
||||
//! \~russian Возвращает \b true если символ является
|
||||
bool isDigit() const;
|
||||
|
||||
//! Return \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F')
|
||||
//! \~english Returns \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F')
|
||||
//! \~russian Возвращает \b true если символ является HEX цифрой ('0' до '9', 'a' до 'f', 'A' до 'F')
|
||||
bool isHex() const;
|
||||
|
||||
//! Return \b true if symbol is drawable (without space)
|
||||
//! \~english Returns \b true if symbol is drawable (without space)
|
||||
//! \~russian Возвращает \b true если символ является графическим (исключая пробельные)
|
||||
bool isGraphical() const;
|
||||
|
||||
//! Return \b true if symbol is control byte (< 32 or 127)
|
||||
//! \~english Returns \b true if symbol is control byte (< 32 or 127)
|
||||
//! \~russian Возвращает \b true если символ является контрольным (< 32 or 127)
|
||||
bool isControl() const;
|
||||
|
||||
//! Return \b true if symbol is in lower case
|
||||
//! \~english Returns \b true if symbol is in lower case
|
||||
//! \~russian Возвращает \b true если символ в нижнем регистре
|
||||
bool isLower() const;
|
||||
|
||||
//! Return \b true if symbol is in upper case
|
||||
|
||||
//! \~english Returns \b true if symbol is in upper case
|
||||
//! \~russian Возвращает \b true если символ в верхнем регистре
|
||||
bool isUpper() const;
|
||||
|
||||
//! Return \b true if symbol is printable (with space)
|
||||
//! \~english Returns \b true if symbol is printable (with space)
|
||||
//! \~russian Возвращает \b true если символ является печатным (включая пробельные)
|
||||
bool isPrint() const;
|
||||
|
||||
//! Return \b true if symbol is space or tab
|
||||
//! \~english Returns \b true if symbol is space or tab
|
||||
//! \~russian Возвращает \b true если символ является пробельным или табуляцией
|
||||
bool isSpace() const;
|
||||
|
||||
//! Return \b true if symbol is alphabetical letter
|
||||
//! \~english Returns \b true if symbol is alphabetical letter
|
||||
//! \~russian Возвращает \b true если символ является алфавитной буквой
|
||||
bool isAlpha() const;
|
||||
|
||||
//! Return \b true if symbol is ascii (< 128)
|
||||
//! \~english Returns \b true if symbol is Ascii (< 128)
|
||||
//! \~russian Возвращает \b true если символ является Ascii (< 128)
|
||||
bool isAscii() const;
|
||||
|
||||
const wchar_t * toWCharPtr() const;
|
||||
|
||||
//! Return as <tt>"char * "</tt> string
|
||||
//! \~english Returns as `char *` string
|
||||
//! \~russian Возвращает символ как указатель на `char *`
|
||||
const char * toCharPtr() const;
|
||||
|
||||
wchar_t toWChar() const;
|
||||
|
||||
//! \~english Returns symbol as Ascii
|
||||
//! \~russian Возвращает символ в Ascii
|
||||
char toAscii() const {return ch % 256;}
|
||||
|
||||
//! \~english Returns symbol as console codepage
|
||||
//! \~russian Возвращает символ в консольной кодировке
|
||||
char toConsole1Byte() const;
|
||||
|
||||
//! \~english Returns symbol as system codepage
|
||||
//! \~russian Возвращает символ в системной кодировке
|
||||
char toSystem() const;
|
||||
|
||||
ushort unicode16Code() const {return ch;}
|
||||
|
||||
//! Return symbol in upper case
|
||||
//! \~english Returns symbol in upper case
|
||||
//! \~russian Возвращает символ в нижнем регистре
|
||||
PIChar toUpper() const;
|
||||
|
||||
//! Return symbol in lower case
|
||||
//! \~english Returns symbol in lower case
|
||||
//! \~russian Возвращает символ в верхнем регистре
|
||||
PIChar toLower() const;
|
||||
|
||||
//! \~english Returns symbol from console codepage
|
||||
//! \~russian Возвращает символ из консольной кодировки
|
||||
static PIChar fromConsole(char c);
|
||||
|
||||
//! \~english Returns symbol from system codepage
|
||||
//! \~russian Возвращает символ из системной кодировки
|
||||
static PIChar fromSystem(char c);
|
||||
|
||||
//! \~english Returns symbol from UTF8 codepage
|
||||
//! \~russian Возвращает символ из UTF8 кодировки
|
||||
static PIChar fromUTF8(const char * c);
|
||||
|
||||
private:
|
||||
@@ -132,54 +172,86 @@ private:
|
||||
|
||||
};
|
||||
|
||||
//! Output operator to \a PICout
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Output operator to \a PICout
|
||||
//! \~russian Оператор вывода в \a PICout
|
||||
PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);}
|
||||
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);}
|
||||
|
||||
//! Compare operator
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= c);}
|
||||
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator ==(const int v, const PIChar & c) {return (PIChar(v) == c);}
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator ==(const int v, const PIChar & c) {return (PIChar((ushort)v) == c);}
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator >(const int v, const PIChar & c) {return (PIChar(v) > c);}
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >(const int v, const PIChar & c) {return (PIChar((ushort)v) > c);}
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator <(const int v, const PIChar & c) {return (PIChar(v) < c);}
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator <(const int v, const PIChar & c) {return (PIChar((ushort)v) < c);}
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator >=(const int v, const PIChar & c) {return (PIChar(v) >= c);}
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator >=(const int v, const PIChar & c) {return (PIChar((ushort)v) >= c);}
|
||||
|
||||
//! Compare operator
|
||||
inline bool operator <=(const int v, const PIChar & c) {return (PIChar(v) <= c);}
|
||||
//! \relatesalso PIChar
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
inline bool operator <=(const int v, const PIChar & c) {return (PIChar((ushort)v) <= c);}
|
||||
|
||||
#endif // PICHAR_H
|
||||
|
||||
@@ -19,45 +19,77 @@
|
||||
|
||||
#include "pichunkstream.h"
|
||||
|
||||
/*! \class PIChunkStream
|
||||
* @brief Class for binary serialization
|
||||
*
|
||||
* \section PIChunkStream_sec0 Synopsis
|
||||
* This class provides very handly mechanism to store and restore values to and from
|
||||
* \a PIByteArray. The main advantage of using this class is that your binary data
|
||||
* become independent from order and collection of your values.
|
||||
*
|
||||
* \section PIChunkStream_sec1 Mechanism
|
||||
* %PIChunkStream works with items called "chunk". Chunk is an ID and any value that
|
||||
* can be stored and restored to \a PIByteArray with stream operators << and >>.
|
||||
* You can place chunks to stream and read chunks from stream.
|
||||
*
|
||||
* To construct %PIChunkStream for writing data use any constructor. Empty constructor
|
||||
* creates internal empty buffer that can be accessed by function \a data().
|
||||
* Non-empty constructor works with given byte array.
|
||||
*
|
||||
* To read chunks from byte array use function \a read() that returns ID of
|
||||
* next chunk. Then you can get value of this chunk with function \a getData(),
|
||||
* but you should definitely know type of this value. You can read from byte array
|
||||
* while \a atEnd() if false.
|
||||
*
|
||||
* \section PIChunkStream_sec2 Examples
|
||||
*
|
||||
* Using simple operator and cascade serialization:
|
||||
*
|
||||
* Prepare your structs to work with %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp struct
|
||||
* Old-style writing to %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp write
|
||||
* Fastest reading from %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp read
|
||||
*
|
||||
* And next code show how to serialize your struct with %PIChunkStream:
|
||||
* \snippet pichunkstream.cpp write_new
|
||||
*
|
||||
* ... and deserialize:
|
||||
* \snippet pichunkstream.cpp read_new
|
||||
*/
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \class PIChunkStream pichunkstream.h
|
||||
//! \brief
|
||||
//! \~english Class for binary de/serialization
|
||||
//! \~russian Класс для бинарной де/сериализации
|
||||
//!
|
||||
//! \~english \section PIChunkStream_sec0 Synopsis
|
||||
//! \~russian \section PIChunkStream_sec0 Краткий обзор
|
||||
//! \~english
|
||||
//! This class provides very handly mechanism to store and restore values to and from
|
||||
//! \a PIByteArray. The main advantage of using this class is that your binary data
|
||||
//! become independent from order and collection of your values.
|
||||
//!
|
||||
//! \~russian
|
||||
//! Этот класс предоставляет очень удобный механизм для сохранения и извлечения значений
|
||||
//! в/из \a PIByteArray. Главным плюсом является то, что данные не будут зависеть от порядка
|
||||
//! и наличия значений.
|
||||
//!
|
||||
//! \~english \section PIChunkStream_sec1 Mechanism
|
||||
//! \~russian \section PIChunkStream_sec1 Механизм
|
||||
//! \~english
|
||||
//! %PIChunkStream works with items called "chunk". Chunk is an ID, size and any value that
|
||||
//! can be stored and restored to/from %PIChunkStream with stream operators << and >>.
|
||||
//!
|
||||
//! To construct %PIChunkStream for writing data use any non-default constructor. Empty constructor
|
||||
//! creates internal buffer that can be accessed by function \a data().
|
||||
//! Non-empty constructor works with given byte array.
|
||||
//!
|
||||
//! To read chunks from byte array use function \a read() that returns ID of
|
||||
//! readed chunk. Then you can get value of this chunk with functions \a getData() or \a get(),
|
||||
//! but you should definitely know type of this value. You can read from byte array
|
||||
//! while \a atEnd() if false.
|
||||
//!
|
||||
//! \~russian
|
||||
//! %PIChunkStream работает с элементами под названием "чанк". Чанк имеет ID, размер и значение,
|
||||
//! и может быть записан или прочитан в/из %PIChunkStream с помощью операторов << и >>.
|
||||
//!
|
||||
//! Для создания потока на запись используется любой не-умолчальный конструктор. Пустой конструктор
|
||||
//! создает внутренний буфер, который можно получить с помощью метода \a data().
|
||||
//! Непустой конструктор работает с переданным байтовым массивом.
|
||||
//!
|
||||
//! Для чтения чанков из байтового массива используется метод \a read(), который возвращает
|
||||
//! ID прочитанного чанка. Получить значение этого чанка далее можно с помощью методов \a getData() или get(),
|
||||
//! но тип значения должен быть известен. Читать из потока можно пока метод \a atEnd() возвращает ложь.
|
||||
//!
|
||||
//! \~english \section PIChunkStream_sec2 Examples
|
||||
//! \~russian \section PIChunkStream_sec2 Пример
|
||||
//!
|
||||
//! \~english Using simple operator and cascade serialization:
|
||||
//! \~russian Использование простого оператора и каскадная сериализация:
|
||||
//!
|
||||
//! \~english Prepare your structs to work with %PIChunkStream:
|
||||
//! \~russian Подготовка своей структуры для работы с %PIChunkStream:
|
||||
//! \~\snippet pichunkstream.cpp struct
|
||||
//! \~english Old-style writing to %PIChunkStream:
|
||||
//! \~russian Старый стиль использования %PIChunkStream:
|
||||
//! \~\snippet pichunkstream.cpp write
|
||||
//! \~english Fastest reading from %PIChunkStream:
|
||||
//! \~russian Самое быстрое чтение из %PIChunkStream:
|
||||
//! \~\snippet pichunkstream.cpp read
|
||||
//!
|
||||
//! \~english And next code show how to serialize your struct with %PIChunkStream:
|
||||
//! \~russian Следующий код показывает, как сериализовать свою структуру в %PIChunkStream:
|
||||
//! \~\snippet pichunkstream.cpp write_new
|
||||
//!
|
||||
//! \~english ... and deserialize:
|
||||
//! \~russian ... и десериализовать:
|
||||
//! \~\snippet pichunkstream.cpp read_new
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
void PIChunkStream::setSource(const PIByteArray & data) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file pichunkstream.h
|
||||
* @brief Binary markup serializator
|
||||
/*! \file pichunkstream.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Binary markup de/serializator stream
|
||||
* \~russian Бинарный поток для де/сериализации с разметкой
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -30,20 +33,27 @@ class PIP_EXPORT PIChunkStream
|
||||
{
|
||||
public:
|
||||
|
||||
//! \~english
|
||||
//! Version of data packing. Read-access %PIChunkStream automatic detect version, but write-access
|
||||
//! %PIChunkStream by default write in new version, be careful!
|
||||
//! \~russian
|
||||
//! Версия хранения данных. %PIChunkStream на чтение автоматически определяет версию, но для записи
|
||||
//! использует по умолчанию новую, осторожно!
|
||||
enum Version {
|
||||
Version_1 /*! First, old version */,
|
||||
Version_2 /*! Second, more optimized version */ = 2,
|
||||
Version_1 /*! \~english First, old version \~russian Первая, старая версия */,
|
||||
Version_2 /*! \~english Second, more optimized version \~russian Вторая, более оптимизированная версия */ = 2,
|
||||
};
|
||||
|
||||
//! Contructs stream for read from "data"
|
||||
//! \~english Contructs stream for read from "data"
|
||||
//! \~russian Создает поток на чтение из "data"
|
||||
PIChunkStream(const PIByteArray & data): version_(Version_2) {setSource(data);}
|
||||
|
||||
//! Contructs stream for read or write to/from "data", or empty stream for write
|
||||
//! \~english Contructs stream for read or write to/from "data", or empty stream for write if "data" = 0
|
||||
//! \~russian Создает поток на чтение или запись из/в "data", или пустой поток на запись если "data" = 0
|
||||
PIChunkStream(PIByteArray * data = 0, Version v = Version_2): version_(v) {setSource(data);}
|
||||
|
||||
//! Contructs empty stream for write with version \"v\"
|
||||
//! \~english Contructs empty stream for write with version \"v\"
|
||||
//! \~russian Создает пустой поток на запись с версией \"v\"
|
||||
PIChunkStream(Version v): version_(v) {setSource(0);}
|
||||
|
||||
~PIChunkStream();
|
||||
@@ -61,48 +71,64 @@ public:
|
||||
const T & data;
|
||||
};
|
||||
|
||||
//! Returns chunk with ID "id" and value "data" for write to stream
|
||||
//! \~english Returns chunk with ID "id" and value "data" for write to stream
|
||||
//! \~russian Возвращает чанк с ID "id" и значением "data" для записи в поток
|
||||
template <typename T> static ChunkConst<T> chunk(int id, const T & data) {return ChunkConst<T>(id, data);}
|
||||
|
||||
//! Add data to this chunk strean with ID "id" and value "data"
|
||||
//! \~english Add to this stream chunk with ID "id" and value "data"
|
||||
//! \~russian Добавляет в этот поток чанк с ID "id" и значением "data"
|
||||
template <typename T> PIChunkStream & add(int id, const T & data) {*this << ChunkConst<T>(id, data); return *this;}
|
||||
|
||||
//! \~english
|
||||
//! Extract %PIByteArray from "data" and set it current stream.
|
||||
//! If "read_all" then call \a readAll() after extract.
|
||||
//! Returns if has data to read.
|
||||
//! \~russian
|
||||
//! Извлекает %PIByteArray из "data" и инициализирует им поток.
|
||||
//! Если указан "read_all", то вызывает \a readAll() после инициализации.
|
||||
//! Возвращает если ли данные для чтения.
|
||||
bool extract(PIByteArray & data, bool read_all = false);
|
||||
|
||||
void setSource(const PIByteArray & data);
|
||||
void setSource(PIByteArray * data);
|
||||
|
||||
//! Returns internal buffer with written data
|
||||
//! \~english Returns internal buffer with written data
|
||||
//! \~russian Возвращает внутренний буфер с записанными данными
|
||||
PIByteArray data() const;
|
||||
|
||||
//! Returns if there is end of stream
|
||||
//! \~english Returns if there is end of stream
|
||||
//! \~russian Возвращает достигнут ли конец потока
|
||||
bool atEnd() const {return data_->size_s() <= 1;}
|
||||
|
||||
//! Returns stream version
|
||||
//! \~english Returns stream version
|
||||
//! \~russian Возвращает версию потока
|
||||
Version version() const {return (Version)version_;}
|
||||
|
||||
|
||||
//! Read one chunk from stream and returns its ID
|
||||
//! \~english Read one chunk from stream and returns its ID
|
||||
//! \~russian Читает один чанк из потока и возвращает его ID
|
||||
int read();
|
||||
|
||||
//! Read all chunks from stream. This function just index input data
|
||||
//! \~english Read all chunks from stream. This function just index input data
|
||||
//! \~russian Читает все чанки из потока. Данный метод лишь индексирует данные
|
||||
void readAll();
|
||||
|
||||
//! Returns last readed chunk ID
|
||||
//! \~english Returns last readed chunk ID
|
||||
//! \~russian Возвращает ID последнего прочитанного чанка
|
||||
int getID() {return last_id;}
|
||||
|
||||
//! Returns value of last readed chunk
|
||||
//! \~english Returns value of last readed chunk
|
||||
//! \~russian Возвращает значение последнего прочитанного чанка
|
||||
template <typename T>
|
||||
T getData() const {T ret; PIByteArray s(last_data); s >> ret; return ret;}
|
||||
|
||||
//! Place value of last readed chunk into \"v\"
|
||||
//! \~english Place value of last readed chunk into \"v\"
|
||||
//! \~russian Записывает значение последнего прочитанного чанка в \"v\"
|
||||
template <typename T>
|
||||
void get(T & v) const {v = getData<T>();}
|
||||
|
||||
//! Place value of chunk with id \"id\" into \"v\". You should call \a readAll() before using this function!
|
||||
//! \~english Place value of chunk with ID \"id\" into \"v\". You should call \a readAll() before using this function!
|
||||
//! \~russian Записывает значение чанка с ID \"id\" в \"v\". Необходимо вызвать \a readAll() перед использованием этого метода!
|
||||
template <typename T>
|
||||
const PIChunkStream & get(int id, T & v) const {
|
||||
CacheEntry pos = data_map.value(id);
|
||||
@@ -113,7 +139,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Replace value of chunk with ID \"id\" to \"v\". You should call \a readAll() before using this function!
|
||||
//! \~english Replace value of chunk with ID \"id\" to \"v\". You should call \a readAll() before using this function!
|
||||
//! \~russian Заменяет значение чанка с ID \"id\" на \"v\". Необходимо вызвать \a readAll() перед использованием этого метода!
|
||||
template <typename T>
|
||||
PIChunkStream & set(int id, const T & v) {
|
||||
PIByteArray ba;
|
||||
|
||||
@@ -21,16 +21,32 @@
|
||||
#include "pisysteminfo.h"
|
||||
|
||||
|
||||
/*! \class PICLI
|
||||
* @brief Command-line arguments parser
|
||||
*
|
||||
* \section PICLI_sec0 Synopsis
|
||||
* This class provide handy parsing of command-line arguments. First you should add
|
||||
* arguments to PICLI with function \a addArgument(). Then you can check if there
|
||||
* is some argument in application command-line with function \a hasArgument();
|
||||
* \section PICLI_sec1 Example
|
||||
* \snippet picli.cpp main
|
||||
*/
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \class PICLI picli.h
|
||||
//! \~\brief
|
||||
//! \~english Command-Line parser
|
||||
//! \~russian Парсер командной строки
|
||||
//!
|
||||
//! \~english \section PICLI_sec0 Synopsis
|
||||
//! \~russian \section PICLI_sec0 Краткий обзор
|
||||
//! \~english
|
||||
//! This class provide handy parsing of command-line arguments. First you should add
|
||||
//! arguments to %PICLI with function \a addArgument(). Then you can check if there
|
||||
//! is some argument in application command-line with function \a hasArgument(),
|
||||
//! or obtain argument value by \a argumentValue().
|
||||
//!
|
||||
//! \~russian
|
||||
//! Этот класс предоставляет удобный механизм для разбора аргументов командной строки.
|
||||
//! Сперва необходимо добавить аргументы в %PICLI с помощью методов \a addArgument().
|
||||
//! Далее можно проверять аргументы на наличие в командной строке методом \a hasArgument(),
|
||||
//! а также получить их значения при помощи \a argumentValue().
|
||||
//!
|
||||
//! \~english \section PICLI_sec1 Example
|
||||
//! \~russian \section PICLI_sec0 Пример
|
||||
//! \~\snippet picli.cpp main
|
||||
//!
|
||||
//! /}
|
||||
|
||||
|
||||
PICLI::PICLI(int argc, char * argv[]) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file picli.h
|
||||
* @brief Command-Line parser
|
||||
/*! \file picli.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Command-Line parser
|
||||
* \~russian Парсер командной строки
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -30,39 +33,54 @@ class PIP_EXPORT PICLI: public PIObject
|
||||
PIOBJECT_SUBCLASS(PICLI, PIObject)
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
//! \~english Constructor
|
||||
//! \~russian Конструктор
|
||||
PICLI(int argc, char * argv[]);
|
||||
|
||||
|
||||
//! Add argument with name "name", short key = name first letter, full key = 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;}
|
||||
|
||||
//! Add argument with name "name", short key = "shortKey", full key = name
|
||||
//! \~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;}
|
||||
|
||||
//! Add argument with name "name", short key = "shortKey", full key = name
|
||||
//! \~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;}
|
||||
|
||||
//! Add argument with name "name", short key = "shortKey", full key = "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;}
|
||||
|
||||
//! Add argument with name "name", short key = "shortKey", full key = "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;}
|
||||
|
||||
|
||||
//! Returns unparsed command-line argument by index "index". Index 0 is program execute command.
|
||||
//! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command
|
||||
//! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы
|
||||
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];}
|
||||
|
||||
//! Returns unparsed command-line arguments
|
||||
//! \~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;}
|
||||
|
||||
//! Returns program execute command without arguments
|
||||
//! \~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"
|
||||
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" или пустую строку, если значения нет
|
||||
PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();}
|
||||
PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();}
|
||||
PIString argumentFullKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.full_key; return PIString();}
|
||||
|
||||
@@ -20,15 +20,28 @@
|
||||
#include "picollection.h"
|
||||
|
||||
|
||||
/** \class PICollection
|
||||
* @brief Interface to discover element groups
|
||||
* \details
|
||||
* \section PICollection_sec0 Synopsis
|
||||
* This class has only static functions so no need to create instance of the
|
||||
* %PICollection. This class provide macros to add some classes or existing
|
||||
* objects to global collection and access to them from any place of the code.
|
||||
* \snippet picollection.cpp main
|
||||
* */
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PICollection picollection.h
|
||||
//! \~\brief
|
||||
//! \~english Helper to collect and retrieve classes to groups
|
||||
//! \~russian Помощник для создания и получения классов в группы
|
||||
//!
|
||||
//! \~\details
|
||||
//! \~english \section PICollection_sec0 Synopsis
|
||||
//! \~russian \section PICollection_sec0 Краткий обзор
|
||||
//! \~english
|
||||
//! This class has only static functions so no need to create instance of the
|
||||
//! %PICollection. This class provide macros to add some classes or existing
|
||||
//! objects to global collection and access to them from any place of the code.
|
||||
//!
|
||||
//! \~russian
|
||||
//! Этот класс предоставляет статические методы, поэтому не нужно создавать
|
||||
//! его экземпляр. Имеется несколько макросов для добавления классов или существующих
|
||||
//! объектов в глобальные группы. Затем можно получить их список в любом месте программы.
|
||||
//! \~\snippet picollection.cpp main
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
PIStringList PICollection::groups() {
|
||||
@@ -77,7 +90,8 @@ PIVector<PICollection::Group> & PICollection::_groups() {
|
||||
|
||||
PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name, bool own) {
|
||||
if (!element) return;
|
||||
const_cast<PIObject * >(element)->setName(name);
|
||||
if (name.isNotEmpty())
|
||||
const_cast<PIObject * >(element)->setName(name);
|
||||
bool added = PICollection::addToGroup(group, element);
|
||||
if (!added && own)
|
||||
delete element;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file picollection.h
|
||||
* @brief Custom elements collection
|
||||
/*! \file picollection.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Custom elements collection
|
||||
* \~russian
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -27,32 +30,70 @@
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
/** @brief Add existing element "object" in group with name "group"
|
||||
* \relatesalso PICollection
|
||||
* \details If there is no group with name "group" it will be created.
|
||||
* Only one element of the class "object" can be in group "group". If
|
||||
* this is already exists nothing be happens. \n "object" should to
|
||||
* be pointer to object based on PIObject. */
|
||||
//! \~\relatesalso PICollection
|
||||
//! \~\brief
|
||||
//! \~english Add existing element "object" in group with name "group"
|
||||
//! \~russian Добавляет существующий элемент "object" в группу с именем "group"
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! If this is no group with name "group" it will be created.
|
||||
//! Only one element of the class "object" can be in group. If
|
||||
//! this is already exists nothing be happens. \n "object" should to
|
||||
//! be pointer to object based on \a PIObject.
|
||||
//! \~russian
|
||||
//! Если такой группы нет, она создается. В каждой группе может присутствовать
|
||||
//! только один элемент класса объекта "object". Если такой элемент уже есть,
|
||||
//! то ничего не изменится. \n "object" должен быть наследником \a PIObject.
|
||||
# define ADD_TO_COLLECTION(group, object)
|
||||
|
||||
/** @brief Add new element of class "class" in group with name "group"
|
||||
* \relatesalso PICollection
|
||||
* \details If there is no group with name "group" it will be created.
|
||||
* Only one element of the class "class" can be in group "group". If
|
||||
* this is already exists nothing be happens. \n "class" should to
|
||||
* be name of the any class based on PIObject. */
|
||||
//! \~\relatesalso PICollection
|
||||
//! \~\brief
|
||||
//! \~english Add existing element "object" in group with name "group" and set its name to "name"
|
||||
//! \~russian Добавляет существующий элемент "object" в группу с именем "group" и присваивает объекту имя "name"
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Similar to \a ADD_TO_COLLECTION(group, object) but set object name to "name"
|
||||
//! \~russian
|
||||
//! Аналогично \a ADD_TO_COLLECTION(group, object), но присваивает имя объекту "name"
|
||||
# define ADD_TO_COLLECTION_WITH_NAME(group, object, name)
|
||||
|
||||
//! \~\relatesalso PICollection
|
||||
//! \~\brief
|
||||
//! \~english Add new element of class "class" in group with name "group"
|
||||
//! \~russian Добавляет новый элемент класса "class" в группу с именем "group"
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! If this is no group with name "group" it will be created.
|
||||
//! Only one element of the class "class" can be in group. If
|
||||
//! this is already exists nothing be happens. \n "class" should to
|
||||
//! be name of the any class based on PIObject.
|
||||
//! \~russian
|
||||
//! Если такой группы нет, она создается. В каждой группе может присутствовать
|
||||
//! только один элемент класса "class". Если такой элемент уже есть,
|
||||
//! то ничего не изменится. \n "class" должен быть любым классом, наследным от \a PIObject.
|
||||
# define ADD_NEW_TO_COLLECTION(group, class)
|
||||
|
||||
//! \~\relatesalso PICollection
|
||||
//! \~\brief
|
||||
//! \~english Add new element of class "class" in group with name "group" and set its name to "name"
|
||||
//! \~russian Добавляет новый элемент класса "class" в группу с именем "group" и присваивает объекту имя "name"
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! Similar to \a ADD_NEW_TO_COLLECTION(group, class) but set object name to "name"
|
||||
//! \~russian
|
||||
//! Аналогично \a ADD_NEW_TO_COLLECTION(group, class), но присваивает имя объекту "name"
|
||||
# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name)
|
||||
|
||||
#else
|
||||
|
||||
# define ADD_TO_COLLECTION(group, object) \
|
||||
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, false);
|
||||
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, "", false);
|
||||
|
||||
# define ADD_TO_COLLECTION_WITH_NAME(group, object, name) \
|
||||
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, object, #name, false);
|
||||
|
||||
# define ADD_NEW_TO_COLLECTION(group, class) \
|
||||
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), true);
|
||||
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), "", true);
|
||||
|
||||
# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) \
|
||||
static PICollection::CollectionAdder _PIP_ADD_COUNTER(_collection_adder_)(#group, new class(), #name, true);
|
||||
@@ -65,10 +106,12 @@ class PIP_EXPORT PICollection
|
||||
public:
|
||||
PICollection() {;}
|
||||
|
||||
//! @brief Returns all existing groups by their names
|
||||
//! \~english Returns all existing groups by their names
|
||||
//! \~russian Возвращает имена всех групп
|
||||
static PIStringList groups();
|
||||
|
||||
//! @brief Returns all elements of group "group"
|
||||
//! \~english Returns all elements of group "group"
|
||||
//! \~russian Возвращает все элементы группы "group"
|
||||
static PIVector<const PIObject * > groupElements(const PIString & group);
|
||||
|
||||
static bool addToGroup(const PIString & group, const PIObject * element);
|
||||
|
||||
@@ -16,6 +16,31 @@
|
||||
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/>.
|
||||
*/
|
||||
/** \defgroup Core
|
||||
* \~\brief
|
||||
* \~english This module contains basic functionality.
|
||||
* \~russian Модуль обеспечивает базовую функциональность.
|
||||
*
|
||||
* \~\details
|
||||
* Scope | Use
|
||||
* ----- | -------
|
||||
* C++ | #include <picoremodule.h>
|
||||
* CMake | PIP
|
||||
*
|
||||
* \~english
|
||||
* These files provides platform abstraction, useful macros, methods and classes
|
||||
*
|
||||
* \~russian
|
||||
* Эти файлы обеспечивают абстракцию операционной системы, полезные макросы, методы и классы
|
||||
*
|
||||
* \~\authors
|
||||
* \~english
|
||||
* Ivan Pelipenko peri4ko@yandex.ru;
|
||||
* Andrey Bychkov work.a.b@yandex.ru;
|
||||
* \~russian
|
||||
* Иван Пелипенко peri4ko@yandex.ru;
|
||||
* Андрей Бычков work.a.b@yandex.ru;
|
||||
*/
|
||||
|
||||
#ifndef PICOREMODULE_H
|
||||
#define PICOREMODULE_H
|
||||
|
||||
@@ -24,11 +24,88 @@
|
||||
#include "pistring_std.h"
|
||||
#ifdef WINDOWS
|
||||
# include <windows.h>
|
||||
# include <wingdi.h>
|
||||
# include <wincon.h>
|
||||
# define COMMON_LVB_UNDERSCORE 0x8000
|
||||
#endif
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PICout picout.h
|
||||
//! \~\brief
|
||||
//! \~english Universal output to console class
|
||||
//! \~russian Универсальный вывод в консоль
|
||||
//!
|
||||
//! \~english \section PICout_sec0 Synopsis
|
||||
//! \~russian \section PICout_sec0 Краткий обзор
|
||||
//! \~english
|
||||
//! This class provide many stream operators for output with some features.
|
||||
//! Output to %PICout is thread-sequential, i.e. doesn`t mixed from parallel
|
||||
//! threads.
|
||||
//!
|
||||
//! \~russian
|
||||
//! Данный класс предоставляет множество операторов для вывода в консоль.
|
||||
//! Вывод в %PICout потоково-последовательный, т.е. не смешивается из параллельных
|
||||
//! потоков.
|
||||
//!
|
||||
//! \~english \section PICout_sec1 Features
|
||||
//! \~russian \section PICout_sec1 Особенности
|
||||
//! \~english
|
||||
//! * support text formatting (color, style)
|
||||
//! * insertion spaces between entries
|
||||
//! * insertion new line at the end of output
|
||||
//! * strings are quoted
|
||||
//! * custom output operator can be easily written
|
||||
//! * can outpur to console, internal buffer or both
|
||||
//!
|
||||
//! \~russian
|
||||
//! * поддержка форматирования (цвет, стиль)
|
||||
//! * вставка пробелов между выводами
|
||||
//! * вставка новой строки после последнего вывода
|
||||
//! * строки обрамляются кавычками
|
||||
//! * легко создавать сови операторы вывода
|
||||
//! * может выводить в консоль, внутренний буфер или в оба места
|
||||
//!
|
||||
//! \~english \section PICout_ex0 Usage
|
||||
//! \~russian \section PICout_ex0 Использование
|
||||
//! \~\snippet picout.cpp 0
|
||||
//!
|
||||
//! \~english \section PICout_ex1 Writing your own output operator
|
||||
//! \~russian \section PICout_ex1 Создание своего оператора вывода
|
||||
//! \~\snippet picout.cpp own
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PICout::Notifier picout.h
|
||||
//! \~\brief
|
||||
//! \~english Class for emit notifications of PICout
|
||||
//! \~russian Класс для посылки событий от PICout
|
||||
//!
|
||||
//! \~english \section PICout_sec0 Synopsis
|
||||
//! \~russian \section PICout_sec0 Краткий обзор
|
||||
//! \~english
|
||||
//! This class used as PICout events emitter. When
|
||||
//! PICout constructs with external PIString* buffer
|
||||
//! and some ID, last copy of this PICout on delete
|
||||
//! emit event "finished()" on object Notifier::object().
|
||||
//! Sample:
|
||||
//!
|
||||
//! \~russian
|
||||
//! Этот класс используется как источник событий PICout.
|
||||
//! Когда PICout сконструирован с внешним буфером PIString*
|
||||
//! и каким-то ID, последняя копия этого PICout при уничтожении
|
||||
//! посылает событие "finished()" у объекта Notifier::object().
|
||||
//! Пример:
|
||||
//!
|
||||
//! \~\snippet picout.cpp notifier
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
class NotifierObject: public PIObject {
|
||||
PIOBJECT(NotifierObject)
|
||||
public:
|
||||
@@ -203,22 +280,65 @@ PICout PICout::operator <<(const PICoutAction v) {
|
||||
}
|
||||
|
||||
|
||||
PICout PICout::operator <<(const PICoutManipulators::PICoutFormat v) {
|
||||
switch (v) {
|
||||
case PICoutManipulators::Bin: cnb_ = 2; break;
|
||||
case PICoutManipulators::Oct: cnb_ = 8; break;
|
||||
case PICoutManipulators::Dec: cnb_ = 10; break;
|
||||
case PICoutManipulators::Hex: cnb_ = 16; break;
|
||||
default: applyFormat(v);
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) {
|
||||
if (v[PICoutManipulators::Bin]) cnb_ = 2;
|
||||
if (v[PICoutManipulators::Oct]) cnb_ = 8;
|
||||
if (v[PICoutManipulators::Dec]) cnb_ = 10;
|
||||
if (v[PICoutManipulators::Hex]) cnb_ = 16;
|
||||
if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold);
|
||||
if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint);
|
||||
if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic);
|
||||
if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline);
|
||||
if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink);
|
||||
if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black);
|
||||
if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red);
|
||||
if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green);
|
||||
if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue);
|
||||
if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow);
|
||||
if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta);
|
||||
if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan);
|
||||
if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White);
|
||||
if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack);
|
||||
if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed);
|
||||
if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen);
|
||||
if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue);
|
||||
if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow);
|
||||
if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta);
|
||||
if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan);
|
||||
if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite);
|
||||
if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#define PICOUTTOTARGET(v) { \
|
||||
if (buffer_) {\
|
||||
(*buffer_) << (v);\
|
||||
(*buffer_) << (v);\
|
||||
} else {\
|
||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||
}\
|
||||
}
|
||||
}
|
||||
#define PICOUTTOTARGETS(v) { \
|
||||
if (buffer_) {\
|
||||
(*buffer_) << (v);\
|
||||
(*buffer_) << (v);\
|
||||
} else {\
|
||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v).dataConsole();\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v).dataConsole();\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||
}\
|
||||
}
|
||||
}
|
||||
#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGETS(PIString::fromNumber(v, cnb_))
|
||||
|
||||
|
||||
@@ -272,10 +392,10 @@ PICout PICout::operator <<(const PICoutSpecialChar v) {
|
||||
switch (v) {
|
||||
case Null:
|
||||
if (buffer_) {
|
||||
(*buffer_) << PIChar(0);
|
||||
(*buffer_) << PIChar();
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar(0);
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar();
|
||||
}
|
||||
break;
|
||||
case NewLine:
|
||||
@@ -345,6 +465,12 @@ PICout & PICout::restoreControl() {
|
||||
#undef PICOUTTOTARGET
|
||||
#undef PINUMERICCOUT
|
||||
|
||||
//! \details
|
||||
//! \~english
|
||||
//! If it is not a first output and control \a AddSpaces is set space character is put
|
||||
//! \~russian
|
||||
//! Добавляет пробел если это не первый вывод и установлен флаг \a AddSpaces
|
||||
//! \~\sa \a quote(), \a newLine()
|
||||
PICout & PICout::space() {
|
||||
if (!act_) return *this;
|
||||
if (!fo_ && co_[AddSpaces]) {
|
||||
@@ -359,6 +485,12 @@ PICout & PICout::space() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \details
|
||||
//! \~english
|
||||
//! If control \a AddQuotes is set quote character is put
|
||||
//! \~russian
|
||||
//! Добавляет кавычки если установлен флаг \a AddQuotes
|
||||
//! \~\sa \a space(), \a newLine()
|
||||
PICout & PICout::quote() {
|
||||
if (!act_) return *this;
|
||||
if (co_[AddQuotes]) {
|
||||
@@ -373,6 +505,12 @@ PICout & PICout::quote() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! \details
|
||||
//! \~english
|
||||
//! If control \a AddNewLine is set new line character is put
|
||||
//! \~russian
|
||||
//! Добавляет новую строку если установлен флаг \a AddNewLine
|
||||
//! \~\sa \a space(), \a quote()
|
||||
PICout & PICout::newLine() {
|
||||
if (!act_) return *this;
|
||||
if (co_[AddNewLine]) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file picout.h
|
||||
* @brief Universal output to console class
|
||||
/*! \file picout.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Universal output to console class
|
||||
* \~russian Универсальный вывод в консоль
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -27,10 +30,13 @@
|
||||
|
||||
#ifdef DOXYGEN
|
||||
|
||||
//! @brief Macro used for conditional (piDebug) output to PICout
|
||||
//! \~english Macro used for conditional (piDebug) output to PICout
|
||||
//! \~russian Макрос для условного (piDebug) вывода в PICout
|
||||
# define piCout
|
||||
|
||||
//! \relatesalso PIObject @brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
|
||||
//! \relatesalso PIObject
|
||||
//! \~english Macro used for conditional (piDebug && PIObject::debug()) output to PICout for subclasses of PIObject
|
||||
//! \~russian Макрос для условного (piDebug && PIObject::debug()) вывода в PICout для наследников PIObject
|
||||
# define piCoutObj
|
||||
|
||||
#else
|
||||
@@ -42,106 +48,97 @@
|
||||
class PIObject;
|
||||
|
||||
|
||||
//! @brief Namespace contains enums controlled PICout
|
||||
//! \relatesalso PICout
|
||||
//! \~english Namespace contains enums that controls PICout
|
||||
//! \~russian Пространство имен содержит перечисления для контроля PICout
|
||||
namespace PICoutManipulators {
|
||||
|
||||
//! @brief Enum contains special characters
|
||||
//! \~english Enum contains special characters
|
||||
//! \~russian Перечисление со спецсимволами
|
||||
enum PICoutSpecialChar {
|
||||
Null /*! Null-character, '\\0' */,
|
||||
NewLine /*! New line character, '\\n' */,
|
||||
Tab /*! Tab character, '\\t' */,
|
||||
Esc /*! Escape character, '\\e' */,
|
||||
Quote /*! Quote character, '"' */
|
||||
Null /*! \~english Null-character, '\\0' \~russian Нулевой символ, '\\0' */,
|
||||
NewLine /*! \~english New line character, '\\n' \~russian Новая строка, '\\n' */,
|
||||
Tab /*! \~english Tab character, '\\t' \~russian Табуляция, '\\t' */,
|
||||
Esc /*! \~english Escape character, '\\e' \~russian Esc-символ, '\\e' */,
|
||||
Quote /*! \~english Quote character, '"' \~russian Кавычки, '"' */
|
||||
};
|
||||
|
||||
//! @brief Enum contains immediate action
|
||||
//! \~english Enum contains immediate action
|
||||
//! \~russian Перечисление с немедленными действиями
|
||||
enum PICoutAction {
|
||||
Flush /*! Flush the output */,
|
||||
Backspace /*! Remove last symbol */,
|
||||
ShowCursor /*! Show cursor */,
|
||||
HideCursor /*! Hide cursor */,
|
||||
ClearLine /*! Clear current line */,
|
||||
ClearScreen /*! Clear the screen */,
|
||||
SaveContol /*! Save control flags, equivalent to \a saveControl() */,
|
||||
RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */
|
||||
Flush /*! \~english Flush the output \~russian Обновить вывод */,
|
||||
Backspace /*! \~english Remove last symbol \~russian Удалить последний символ */,
|
||||
ShowCursor /*! \~english Show cursor \~russian Показать курсор */,
|
||||
HideCursor /*! \~english Hide cursor \~russian Скрыть курсор */,
|
||||
ClearLine /*! \~english Clear current line \~russian Очистить текущую строку */,
|
||||
ClearScreen /*! \~english Clear the screen \~russian Очистить экран */,
|
||||
SaveContol /*! \~english Save control flags, equivalent to \a saveControl() \~russian Сохранить флаги, аналогично \a saveControl() */,
|
||||
RestoreControl /*! \~english Restore control flags, equivalent to \a restoreControl() \~russian Восстановить флаги, аналогично \a restoreControl() */
|
||||
};
|
||||
|
||||
//! @brief Enum contains control of PICout
|
||||
//! \~english Enum contains control of PICout
|
||||
//! \~russian Перечисление с управлением PICout
|
||||
enum PICoutControl {
|
||||
AddNone /*! No controls */ = 0x0,
|
||||
AddSpaces /*! Spaces will be appear after each output */ = 0x1,
|
||||
AddNewLine /*! New line will be appear after all output */ = 0x2,
|
||||
AddQuotes /*! Each string will be quoted */ = 0x4,
|
||||
DefaultControls /*! Default controls */ = AddSpaces | AddNewLine,
|
||||
AddAll /*! All controls */ = 0xFF,
|
||||
NoLock /*! Don`t use mutex for output */ = 0x100,
|
||||
AddNone /*! \~english No controls \~russian Без управления */ = 0x0,
|
||||
AddSpaces /*! \~english Spaces will be appear after each output \~russian Пробел после каждого вывода */ = 0x1,
|
||||
AddNewLine /*! \~english New line will be appear after all output \~russian Новая строка после завершения вывода */ = 0x2,
|
||||
AddQuotes /*! \~english Each string will be quoted \~russian Каждая строка в кавычках */ = 0x4,
|
||||
DefaultControls /*! \~english Default controls \~russian Управление по умолчанию */ = AddSpaces | AddNewLine,
|
||||
AddAll /*! \~english All controls \~russian Всё управление */ = 0xFF,
|
||||
NoLock /*! \~english Don`t use mutex for output \~russian Не использовать мьютекс при выводе */ = 0x100,
|
||||
};
|
||||
|
||||
//! @brief Enum contains output format
|
||||
//! \~english Enum contains output format
|
||||
//! \~russian Перечисление с форматом вывода
|
||||
enum PICoutFormat {
|
||||
Bin /*! Binary representation of integers */ = 0x01,
|
||||
Oct /*! Octal representation of integers */ = 0x02,
|
||||
Dec /*! Decimal representation of integers */ = 0x04,
|
||||
Hex /*! Hexadecimal representation of integers */ = 0x08,
|
||||
Bold /*! Bold */ = 0x10,
|
||||
Faint /*! */ = 0x20,
|
||||
Italic /*! */ = 0x40,
|
||||
Underline /*! Underline */ = 0x80,
|
||||
Blink /*! Blink */ = 0x100,
|
||||
Black /*! Black font */ = 0x400,
|
||||
Red /*! Red font */ = 0x800,
|
||||
Green /*! Green font */ = 0x1000,
|
||||
Blue /*! Blue font */ = 0x2000,
|
||||
Yellow /*! Yellow font */ = 0x4000,
|
||||
Magenta /*! Magenta font */ = 0x8000,
|
||||
Cyan /*! Cyan font */ = 0x10000,
|
||||
White /*! White font */ = 0x20000,
|
||||
BackBlack /*! Black background */ = 0x40000,
|
||||
BackRed /*! Red background */ = 0x80000,
|
||||
BackGreen /*! Green background */ = 0x100000,
|
||||
BackBlue /*! Blue background */ = 0x200000,
|
||||
BackYellow /*! Yellow background */ = 0x400000,
|
||||
BackMagenta /*! Magenta background */ = 0x800000,
|
||||
BackCyan /*! Cyan background */ = 0x1000000,
|
||||
BackWhite /*! White background */ = 0x2000000,
|
||||
Default /*! Default format */ = 0x4000000
|
||||
Bin /*! \~english Binary representation of integers \~russian Двоичное представление для целых чисел */ = 0x01,
|
||||
Oct /*! \~english Octal representation of integers \~russian Восьмеричное представление для целых чисел */ = 0x02,
|
||||
Dec /*! \~english Decimal representation of integers \~russian Десятичное представление для целых чисел */ = 0x04,
|
||||
Hex /*! \~english Hexadecimal representation of integers \~russian Шестнадцатеричное представление для целых чисел */ = 0x08,
|
||||
Bold /*! \~english Bold \~russian Жирный */ = 0x10,
|
||||
Faint /*! \~english \~russian */ = 0x20,
|
||||
Italic /*! \~english \~russian */ = 0x40,
|
||||
Underline /*! \~english Underline \~russian Подчеркнутый */ = 0x80,
|
||||
Blink /*! \~english Blink \~russian Мигающий */ = 0x100,
|
||||
Black /*! \~english Black font \~russian Чёрный */ = 0x400,
|
||||
Red /*! \~english Red font \~russian Красный */ = 0x800,
|
||||
Green /*! \~english Green font \~russian Зелёный */ = 0x1000,
|
||||
Blue /*! \~english Blue font \~russian Синий */ = 0x2000,
|
||||
Yellow /*! \~english Yellow font \~russian Жёлтый */ = 0x4000,
|
||||
Magenta /*! \~english Magenta font \~russian Пурпурный */ = 0x8000,
|
||||
Cyan /*! \~english Cyan font \~russian Голубой */ = 0x10000,
|
||||
White /*! \~english White font \~russian Белый */ = 0x20000,
|
||||
BackBlack /*! \~english Black background \~russian Чёрный фон */ = 0x40000,
|
||||
BackRed /*! \~english Red background \~russian Красный фон */ = 0x80000,
|
||||
BackGreen /*! \~english Green background \~russian Зелёный фон */ = 0x100000,
|
||||
BackBlue /*! \~english Blue background \~russian Синий фон */ = 0x200000,
|
||||
BackYellow /*! \~english Yellow background \~russian Жёлтый фон */ = 0x400000,
|
||||
BackMagenta /*! \~english Magenta background \~russian Пурпурный фон */ = 0x800000,
|
||||
BackCyan /*! \~english Cyan background \~russian Голубой фон */ = 0x1000000,
|
||||
BackWhite /*! \~english White background \~russian Белый фон */ = 0x2000000,
|
||||
Default /*! \~english Default format \~russian Формат по умолчанию */ = 0x4000000
|
||||
};
|
||||
|
||||
typedef PIFlags<PICoutControl> PICoutControls;
|
||||
}
|
||||
|
||||
|
||||
/*! \class PICout
|
||||
* @brief Class for formatted output similar std::cout
|
||||
*
|
||||
* \section PICout_sec0 Synopsis
|
||||
* This class provide many stream operators for output with some features.
|
||||
* Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel
|
||||
* threads.
|
||||
*
|
||||
* \section PICout_sec1 Features
|
||||
* - insertion spaces between entries
|
||||
* - insertion new line at the end of output
|
||||
* - strings are quoted
|
||||
* - custom output operator can be easily written
|
||||
*
|
||||
* \section PICout_ex0 Usage
|
||||
* \snippet picout.cpp 0
|
||||
*
|
||||
* \section PICout_ex1 Writing your own output operator
|
||||
* \snippet picout.cpp own
|
||||
*/
|
||||
|
||||
|
||||
class PIP_EXPORT PICout {
|
||||
public:
|
||||
//! Default constructor with default features (AddSpaces and AddNewLine)
|
||||
|
||||
//! \~english Default constructor with default features (AddSpaces and AddNewLine)
|
||||
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine)
|
||||
PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls);
|
||||
PICout(PICoutManipulators::PICoutControl control = PICoutManipulators::DefaultControls);
|
||||
|
||||
//! Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing
|
||||
//! \~english Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing
|
||||
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine), но если не \"active\" то будет неактивным
|
||||
PICout(bool active);
|
||||
|
||||
//! Construct with external buffer and id "id". See \a Notifier for details
|
||||
//! \~english Construct with external buffer and ID "id". See \a Notifier for details
|
||||
//! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier
|
||||
PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
|
||||
|
||||
PICout(const PICout & other);
|
||||
@@ -149,171 +146,171 @@ public:
|
||||
~PICout();
|
||||
|
||||
|
||||
/*! \class PICout::Notifier
|
||||
* @brief Class for emit notifications of PICout
|
||||
*
|
||||
* \section PICout_sec0 Synopsis
|
||||
* This class used as PICout events emitter. When
|
||||
* PICout constructs with external PIString* buffer
|
||||
* and some id, last copy of this PICout on delete
|
||||
* emit event "finished()" on object Notifier::object().
|
||||
* Sample:
|
||||
* \snippet picout.cpp notifier
|
||||
*/
|
||||
|
||||
class PIP_EXPORT Notifier {
|
||||
public:
|
||||
//! \~english Singleton access to %PICout::Notifier
|
||||
//! \~russian Синглтон класса %PICout::Notifier
|
||||
static Notifier * instance();
|
||||
|
||||
//! \~english Object that emit events from %PICout
|
||||
//! \~russian Объект, который посылает события от %PICout
|
||||
static PIObject * object();
|
||||
private:
|
||||
Notifier();
|
||||
PIObject * o;
|
||||
};
|
||||
|
||||
//! @brief Enum contains output devices of PICout
|
||||
//! \~english Enum contains output devices of %PICout
|
||||
//! \~russian Перечисление с устройствами вывода для %PICout
|
||||
enum OutputDevice {
|
||||
NoDevices /** PICout is disabled */ = 0x0,
|
||||
StdOut /** Standard console output */ = 0x1,
|
||||
Buffer /** Internal buffer */ = 0x2,
|
||||
AllDevices /** All */ = 0xFFFF,
|
||||
NoDevices /** \~english %PICout is disabled \~russian %PICout неактивен */ = 0x0,
|
||||
StdOut /** \~english Standard console output \~russian Стандартный вывод в консоль */ = 0x1,
|
||||
Buffer /** \~english Internal buffer \~russian Внутренний буфер */ = 0x2,
|
||||
AllDevices /** \~english All \~russian Все */ = 0xFFFF,
|
||||
};
|
||||
|
||||
typedef PIFlags<OutputDevice> OutputDevices;
|
||||
|
||||
//! Output operator for strings with <tt>"const char * "</tt> type
|
||||
//! \~english Output operator for strings with <tt>"const char * "</tt> type
|
||||
//! \~russian Оператор вывода для строк <tt>"const char * "</tt>
|
||||
PICout operator <<(const char * v);
|
||||
|
||||
//! Output operator for strings with <tt>"std::string"</tt> type
|
||||
// ! Output operator for strings with <tt>"std::string"</tt> type
|
||||
//PICout operator <<(const std::string & v);
|
||||
|
||||
//! Output operator for boolean values
|
||||
//! \~english Output operator for boolean values
|
||||
//! \~russian Оператор вывода для логических значений
|
||||
PICout operator <<(const bool v);
|
||||
|
||||
//! Output operator for <tt>"char"</tt> values
|
||||
//! \~english Output operator for <tt>"char"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"char"</tt> значений
|
||||
PICout operator <<(const char v);
|
||||
|
||||
//! Output operator for <tt>"unsigned char"</tt> values
|
||||
//! \~english Output operator for <tt>"unsigned char"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"unsigned char"</tt> значений
|
||||
PICout operator <<(const uchar v);
|
||||
|
||||
//! Output operator for <tt>"short"</tt> values
|
||||
//! \~english Output operator for <tt>"short"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"short"</tt> значений
|
||||
PICout operator <<(const short v);
|
||||
|
||||
//! Output operator for <tt>"unsigned short"</tt> values
|
||||
//! \~english Output operator for <tt>"unsigned short"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"unsigned short"</tt> значений
|
||||
PICout operator <<(const ushort v);
|
||||
|
||||
//! Output operator for <tt>"int"</tt> values
|
||||
//! \~english Output operator for <tt>"int"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"int"</tt> значений
|
||||
PICout operator <<(const int v);
|
||||
|
||||
//! Output operator for <tt>"unsigned int"</tt> values
|
||||
//! \~english Output operator for <tt>"unsigned int"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"unsigned int"</tt> значений
|
||||
PICout operator <<(const uint v);
|
||||
|
||||
//! Output operator for <tt>"long"</tt> values
|
||||
//! \~english Output operator for <tt>"long"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"long"</tt> значений
|
||||
PICout operator <<(const long v);
|
||||
|
||||
//! Output operator for <tt>"unsigned long"</tt> values
|
||||
//! \~english Output operator for <tt>"unsigned long"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"unsigned long"</tt> значений
|
||||
PICout operator <<(const ulong v);
|
||||
|
||||
//! Output operator for <tt>"long long"</tt> values
|
||||
//! \~english Output operator for <tt>"long long"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"long long"</tt> значений
|
||||
PICout operator <<(const llong v);
|
||||
|
||||
//! Output operator for <tt>"unsigned long long"</tt> values
|
||||
//! \~english Output operator for <tt>"unsigned long long"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"unsigned long long"</tt> значений
|
||||
PICout operator <<(const ullong v);
|
||||
|
||||
//! Output operator for <tt>"float"</tt> values
|
||||
//! \~english Output operator for <tt>"float"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"float"</tt> значений
|
||||
PICout operator <<(const float v);
|
||||
|
||||
//! Output operator for <tt>"double"</tt> values
|
||||
//! \~english Output operator for <tt>"double"</tt> values
|
||||
//! \~russian Оператор вывода для <tt>"double"</tt> значений
|
||||
PICout operator <<(const double v);
|
||||
|
||||
//! Output operator for pointers
|
||||
//! \~english Output operator for pointers
|
||||
//! \~russian Оператор вывода для указателей
|
||||
PICout operator <<(const void * v);
|
||||
|
||||
//! Output operator for PIObject and ancestors
|
||||
//! \~english Output operator for PIObject and ancestors
|
||||
//! \~russian Оператор вывода для PIObject и наследников
|
||||
PICout operator <<(const PIObject * v);
|
||||
|
||||
//! Output operator for \a PICoutSpecialChar values
|
||||
//! \~english Output operator for \a PICoutSpecialChar values
|
||||
//! \~russian Оператор вывода для \a PICoutSpecialChar
|
||||
PICout operator <<(const PICoutManipulators::PICoutSpecialChar v);
|
||||
|
||||
//! Output operator for \a PIFlags<PICoutFormat> values
|
||||
PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) {
|
||||
if (v[PICoutManipulators::Bin]) cnb_ = 2;
|
||||
if (v[PICoutManipulators::Oct]) cnb_ = 8;
|
||||
if (v[PICoutManipulators::Dec]) cnb_ = 10;
|
||||
if (v[PICoutManipulators::Hex]) cnb_ = 16;
|
||||
if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold);
|
||||
if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint);
|
||||
if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic);
|
||||
if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline);
|
||||
if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink);
|
||||
if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black);
|
||||
if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red);
|
||||
if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green);
|
||||
if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue);
|
||||
if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow);
|
||||
if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta);
|
||||
if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan);
|
||||
if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White);
|
||||
if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack);
|
||||
if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed);
|
||||
if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen);
|
||||
if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue);
|
||||
if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow);
|
||||
if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta);
|
||||
if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan);
|
||||
if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite);
|
||||
if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default);
|
||||
return *this;
|
||||
}
|
||||
//! \~english Output operator for \a PIFlags<PICoutFormat> values
|
||||
//! \~russian Оператор вывода для \a PIFlags<PICoutFormat>
|
||||
PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v);
|
||||
|
||||
//! Output operator for \a PICoutFormat values
|
||||
PICout operator <<(const PICoutManipulators::PICoutFormat v) {
|
||||
switch (v) {
|
||||
case PICoutManipulators::Bin: cnb_ = 2; break;
|
||||
case PICoutManipulators::Oct: cnb_ = 8; break;
|
||||
case PICoutManipulators::Dec: cnb_ = 10; break;
|
||||
case PICoutManipulators::Hex: cnb_ = 16; break;
|
||||
default: applyFormat(v);
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
//! \~english Output operator for \a PICoutFormat values
|
||||
//! \~russian Оператор вывода для \a PICoutFormat
|
||||
PICout operator <<(const PICoutManipulators::PICoutFormat v);
|
||||
|
||||
//! Do some action
|
||||
//! \~english Do some action
|
||||
//! \~russian Делает действие
|
||||
PICout operator <<(const PICoutManipulators::PICoutAction v);
|
||||
|
||||
//! Set control flag "c" is "on" state
|
||||
//! \~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;}
|
||||
|
||||
//! Set control flags "c" and if "save" exec \a saveControl()
|
||||
//! \~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;}
|
||||
|
||||
//! Save control flags to internal stack \sa \a restoreControl()
|
||||
//! \~english Save control flags to internal stack
|
||||
//! \~russian Сохраняет состояние флагов во внутренний стек
|
||||
//! \~\sa \a restoreControl()
|
||||
PICout & saveControl();
|
||||
|
||||
//! Restore control flags from internal stack \sa \a saveControl()
|
||||
//! \~english Restore control flags from internal stack
|
||||
//! \~russian Восстанавливает состояние флагов из внутреннего стека
|
||||
//! \~\sa \a saveControl()
|
||||
PICout & restoreControl();
|
||||
|
||||
/*! @brief Conditional put space character to output
|
||||
* \details If it is not a first output and control \a AddSpaces is set
|
||||
* space character is put \sa \a quote(), \a newLine() */
|
||||
//! \~english Conditional put space character to output
|
||||
//! \~russian Условно добавляет пробел
|
||||
PICout & space();
|
||||
|
||||
/*! @brief Conditional put quote character to output
|
||||
* \details If control \a AddQuotes is set
|
||||
* quote character is put \sa \a space(), \a newLine() */
|
||||
//! \~english Conditional put quote character to output
|
||||
//! \~russian Условно добавляет кавычки
|
||||
PICout & quote();
|
||||
|
||||
/*! @brief Conditional put new line character to output
|
||||
* \details If control \a AddNewLine is set
|
||||
* new line character is put \sa \a space(), \a quote() */
|
||||
//! \~english Conditional put new line character to output
|
||||
//! \~russian Условно добавляет новую строку
|
||||
PICout & newLine();
|
||||
|
||||
//! \~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 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 Clear internal PIString buffer
|
||||
//! \~russian Очищает внутренний PIString буфер
|
||||
static void clearBuffer();
|
||||
|
||||
|
||||
//! \~english Set output to device "d" enabled "on". Returns if it was enabled
|
||||
//! \~russian Устройство вывода "d" устанавливается в "on". Возвращает было ли устройство активно
|
||||
static bool setOutputDevice(OutputDevice d, bool on = true);
|
||||
|
||||
//! \~english Set output to devices to "d"
|
||||
//! \~russian Устанавливает устройства вывода "d"
|
||||
static void setOutputDevices(OutputDevices d);
|
||||
|
||||
//! \~english Returns if output device "d" is active
|
||||
//! \~russian Возвращает активно ли устройство вывода "d"
|
||||
static bool isOutputDeviceActive(OutputDevice d);
|
||||
|
||||
static PIMutex & __mutex__();
|
||||
|
||||
358
libs/main/core/pidatetime.cpp
Normal file
358
libs/main/core/pidatetime.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Timer
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "pidatetime.h"
|
||||
#include <ctime>
|
||||
#ifdef ARDUINO
|
||||
# include <Arduino.h>
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
//# include <mach/mach_traps.h>
|
||||
//# include <mach/mach.h>
|
||||
# include <mach/clock.h>
|
||||
//# include <crt_externs.h>
|
||||
#endif
|
||||
#ifdef MICRO_PIP
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \class PISystemTime pitime.h
|
||||
//! \brief
|
||||
//! \~english System time with nanosecond precision
|
||||
//! \~russian Системное время с точностью до наносекунд
|
||||
//!
|
||||
//! \~english \section PISystemTime_sec0 Synopsis
|
||||
//! \~russian \section PISystemTime_sec0 Краткий обзор
|
||||
//! \~english
|
||||
//!
|
||||
//! \~russian
|
||||
//!
|
||||
//! \~english \section PISystemTime_sec1 Example
|
||||
//! \~russian \section PISystemTime_sec1 Пример
|
||||
//! \~\snippet pitimer.cpp system_time
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
|
||||
|
||||
bool operator ==(const PITime & t0, const PITime & t1) {
|
||||
return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
|
||||
}
|
||||
|
||||
|
||||
bool operator <(const PITime & t0, const PITime & t1) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds < t1.seconds;
|
||||
} else return t0.minutes < t1.minutes;
|
||||
} else return t0.hours < t1.hours;
|
||||
}
|
||||
|
||||
|
||||
bool operator >(const PITime & t0, const PITime & t1) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds > t1.seconds;
|
||||
} else return t0.minutes > t1.minutes;
|
||||
} else return t0.hours > t1.hours;
|
||||
}
|
||||
|
||||
bool operator ==(const PIDate & t0, const PIDate & t1) {
|
||||
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day);
|
||||
}
|
||||
|
||||
|
||||
bool operator <(const PIDate & t0, const PIDate & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
return t0.day < t1.day;
|
||||
} else return t0.month < t1.month;
|
||||
} else return t0.year < t1.year;
|
||||
}
|
||||
|
||||
|
||||
bool operator >(const PIDate & t0, const PIDate & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
return t0.day > t1.day;
|
||||
} else return t0.month > t1.month;
|
||||
} else return t0.year > t1.year;
|
||||
}
|
||||
|
||||
bool operator ==(const PIDateTime & t0, const PIDateTime & t1) {
|
||||
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day &&
|
||||
t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
|
||||
}
|
||||
|
||||
|
||||
bool operator <(const PIDateTime & t0, const PIDateTime & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
if (t0.day == t1.day) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds < t1.seconds;
|
||||
} else return t0.minutes < t1.minutes;
|
||||
} else return t0.hours < t1.hours;
|
||||
} else return t0.day < t1.day;
|
||||
} else return t0.month < t1.month;
|
||||
} else return t0.year < t1.year;
|
||||
}
|
||||
|
||||
|
||||
bool operator >(const PIDateTime & t0, const PIDateTime & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
if (t0.day == t1.day) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds > t1.seconds;
|
||||
} else return t0.minutes > t1.minutes;
|
||||
} else return t0.hours > t1.hours;
|
||||
} else return t0.day > t1.day;
|
||||
} else return t0.month > t1.month;
|
||||
} else return t0.year > t1.year;
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PITime::toSystemTime() const {
|
||||
return PISystemTime((hours * 60. + minutes) * 60. + seconds, milliseconds * 1000.);
|
||||
}
|
||||
|
||||
|
||||
PITime PITime::current() {
|
||||
time_t rt = ::time(0);
|
||||
tm * pt = localtime(&rt);
|
||||
PITime t;
|
||||
t.seconds = pt->tm_sec;
|
||||
t.minutes = pt->tm_min;
|
||||
t.hours = pt->tm_hour;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
PITime PITime::fromSystemTime(const PISystemTime & st) {
|
||||
double s = st.toSeconds();
|
||||
int v = s;
|
||||
PITime ret;
|
||||
ret.milliseconds = (s - v) * 1000;
|
||||
ret.seconds = v % 60; v = (v - ret.seconds) / 60;
|
||||
ret.minutes = v % 60; v = (v - ret.minutes) / 60;
|
||||
ret.hours = v;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIDate PIDate::current() {
|
||||
time_t rt = ::time(0);
|
||||
tm * pt = localtime(&rt);
|
||||
PIDate d;
|
||||
d.day = pt->tm_mday;
|
||||
d.month = pt->tm_mon + 1;
|
||||
d.year = pt->tm_year + 1900;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
PIDateTime PIDateTime::current() {
|
||||
time_t rt = ::time(0);
|
||||
tm * pt = localtime(&rt);
|
||||
PIDateTime dt;
|
||||
dt.milliseconds = 0;
|
||||
dt.seconds = pt->tm_sec;
|
||||
dt.minutes = pt->tm_min;
|
||||
dt.hours = pt->tm_hour;
|
||||
dt.day = pt->tm_mday;
|
||||
dt.month = pt->tm_mon + 1;
|
||||
dt.year = pt->tm_year + 1900;
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIString PITime::toString(const PIString & format) const {
|
||||
PIString ts = format;
|
||||
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(hours));
|
||||
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(minutes));
|
||||
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(seconds));
|
||||
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
|
||||
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
|
||||
ts.replace("z", PIString::fromNumber(milliseconds));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString PIDate::toString(const PIString & format) const {
|
||||
PIString ts = format;
|
||||
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(month));
|
||||
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(day));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString PIDateTime::toString(const PIString & format) const {
|
||||
PIString ts = format;
|
||||
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(month));
|
||||
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(day));
|
||||
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(hours));
|
||||
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(minutes));
|
||||
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(seconds));
|
||||
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
|
||||
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
|
||||
ts.replace("z", PIString::fromNumber(milliseconds));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
time_t PIDateTime::toSecondSinceEpoch() const {
|
||||
tm pt;
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
pt.tm_sec = seconds;
|
||||
pt.tm_min = minutes;
|
||||
pt.tm_hour = hours;
|
||||
pt.tm_mday = day;
|
||||
pt.tm_mon = month - 1;
|
||||
#ifdef WINDOWS
|
||||
pt.tm_year = piMaxi(year - 1900, 70);
|
||||
#else
|
||||
pt.tm_year = piMaxi(year - 1900, 0);
|
||||
#endif
|
||||
return mktime(&pt);
|
||||
}
|
||||
|
||||
|
||||
PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) {
|
||||
tm * pt = localtime(&sec);
|
||||
PIDateTime dt;
|
||||
dt.seconds = pt->tm_sec;
|
||||
dt.minutes = pt->tm_min;
|
||||
dt.hours = pt->tm_hour;
|
||||
dt.day = pt->tm_mday;
|
||||
dt.month = pt->tm_mon + 1;
|
||||
dt.year = pt->tm_year + 1900;
|
||||
return dt;
|
||||
|
||||
}
|
||||
|
||||
|
||||
PIString time2string(const PITime & time, const PIString & format) {
|
||||
PIString ts = format;
|
||||
ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(time.hours));
|
||||
ts.replace("mm", PIString::fromNumber(time.minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(time.minutes));
|
||||
ts.replace("ss", PIString::fromNumber(time.seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(time.seconds));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString date2string(const PIDate & date, const PIString & format) {
|
||||
PIString ts = format;
|
||||
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(date.year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(date.year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(date.month));
|
||||
ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(date.day));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString datetime2string(const PIDateTime & date, const PIString & format) {
|
||||
PIString ts = format;
|
||||
ts.replace("hh", PIString::fromNumber(date.hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(date.hours));
|
||||
ts.replace("mm", PIString::fromNumber(date.minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(date.minutes));
|
||||
ts.replace("ss", PIString::fromNumber(date.seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(date.seconds));
|
||||
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(date.year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(date.year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(date.month));
|
||||
ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(date.day));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PITime & v) {
|
||||
s.space();
|
||||
s.setControl(0, true);
|
||||
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();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PIDate & v) {
|
||||
s.space();
|
||||
s.setControl(0, true);
|
||||
s << "PIDate(" << v.day << "-";
|
||||
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
|
||||
s << v.year << ")";
|
||||
s.restoreControl();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PIDateTime & v) {
|
||||
s.space();
|
||||
s.setControl(0, true);
|
||||
s << "PIDateTime(";
|
||||
s << v.day << "-";
|
||||
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
|
||||
s << v.year << " ";
|
||||
s << 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();
|
||||
return s;
|
||||
}
|
||||
|
||||
129
libs/main/core/pidatetime.h
Normal file
129
libs/main/core/pidatetime.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*! \file pidatetime.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Time and date structs
|
||||
* \~russian Типы времени и даты
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Time and date structs
|
||||
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 PIDATETIME_H
|
||||
#define PIDATETIME_H
|
||||
|
||||
|
||||
#include "pisystemtime.h"
|
||||
|
||||
|
||||
struct PIP_EXPORT PITime {
|
||||
PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;}
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
int milliseconds;
|
||||
PIString toString(const PIString & format = "h:mm:ss") const;
|
||||
PISystemTime toSystemTime() const;
|
||||
static PITime current();
|
||||
static PITime fromSystemTime(const PISystemTime & st);
|
||||
};
|
||||
|
||||
PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1);
|
||||
PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1);
|
||||
PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1);
|
||||
inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);}
|
||||
|
||||
//! \relatesalso PICout
|
||||
//! \~english \brief Output operator to PICout
|
||||
//! \~russian \brief Оператор вывода в PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PITime & v);
|
||||
|
||||
|
||||
|
||||
|
||||
struct PIP_EXPORT PIDate {
|
||||
PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;}
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
PIString toString(const PIString & format = "d.MM.yyyy") const;
|
||||
static PIDate current();
|
||||
};
|
||||
|
||||
PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1);
|
||||
PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1);
|
||||
PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1);
|
||||
inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);}
|
||||
|
||||
//! \relatesalso PICout
|
||||
//! \~english \brief Output operator to PICout
|
||||
//! \~russian \brief Оператор вывода в PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIDate & v);
|
||||
|
||||
|
||||
|
||||
|
||||
struct PIP_EXPORT PIDateTime {
|
||||
PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;}
|
||||
PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
|
||||
PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;}
|
||||
PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
int milliseconds;
|
||||
PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());}
|
||||
void normalize() {*this = normalized();}
|
||||
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const;
|
||||
time_t toSecondSinceEpoch() const;
|
||||
PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);}
|
||||
PIDate date() const {return PIDate(year, month, day);}
|
||||
PITime time() const {return PITime(hours, minutes, seconds, milliseconds);}
|
||||
void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;}
|
||||
void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;}
|
||||
void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();}
|
||||
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
|
||||
static PIDateTime fromSecondSinceEpoch(const time_t sec);
|
||||
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
|
||||
static PIDateTime current();
|
||||
};
|
||||
|
||||
inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();}
|
||||
inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();}
|
||||
PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1);
|
||||
PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1);
|
||||
PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1);
|
||||
inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDateTime & v) {s << v.year << v.month << v.day << v.hours << v.minutes << v.seconds << v.milliseconds; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, 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
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIDateTime & v);
|
||||
|
||||
|
||||
#endif // PIDATETIME_H
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file piflags.h
|
||||
* @brief General flags class
|
||||
/*! \file piflags.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english General flags class
|
||||
* \~russian Универсальные флаги
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -25,109 +28,220 @@
|
||||
|
||||
#include "pip_export.h"
|
||||
|
||||
/*! @brief This class used as container for bit flags
|
||||
* \details PIFlags is wrapper around \c "int". There are many
|
||||
* bit-wise operators, native conversion to int and function
|
||||
* to test flag. \n Example:
|
||||
* \snippet piincludes.cpp flags
|
||||
*/
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PIFlags piflags.h
|
||||
//! \~\brief
|
||||
//! \~english Container for bit flags
|
||||
//! \~russian Контейнер для битовых полей (флагов)
|
||||
//!
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! %PIFlags is wrapper around \c "int". One can use it as native \c "int".
|
||||
//! There are manybit-wise operators,
|
||||
//! native conversion to "int" and function
|
||||
//! to test flag. \n Example:
|
||||
//!
|
||||
//! \~russian
|
||||
//! %PIFlags по сути обертка вокруг \c "int". Можно использовать его как обычный \c "int".
|
||||
//! Имеет много битовых операторов,
|
||||
//! неявное преобразование в "int" и методы для проверки
|
||||
//! флагов. \n Пример:
|
||||
//!
|
||||
//! \~\snippet piincludes.cpp flags
|
||||
//!
|
||||
//! \}
|
||||
template<typename Enum>
|
||||
class PIFlags {
|
||||
public:
|
||||
//! Constructor with flags = 0
|
||||
|
||||
//! \~english Constructor with flags = 0
|
||||
//! \~russian Создает нулевые флаги
|
||||
PIFlags(): flags(0) {;}
|
||||
//! Constructor with flags = Enum "e"
|
||||
|
||||
//! \~english Constructor with flags = Enum "e"
|
||||
//! \~russian Создает флаги со значением = Enum "e"
|
||||
PIFlags(Enum e): flags(e) {;}
|
||||
//! Constructor with flags = int "i"
|
||||
|
||||
//! \~english Constructor with flags = int "i"
|
||||
//! \~russian Создает флаги со значением = int "i"
|
||||
PIFlags(const int i): flags(i) {;}
|
||||
//! Set flags "f" to value "on"
|
||||
|
||||
//! \~english Set flags on positions "f" to value "on"
|
||||
//! \~russian Устанавливает флаги по позициям "f" в "on"
|
||||
PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
|
||||
//! Set flag "e" to value "on"
|
||||
|
||||
//! \~english Set flag "e" to value "on"
|
||||
//! \~russian Устанавливает флаг "e" в "on"
|
||||
PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
|
||||
//! Set flag "i" to value "on"
|
||||
|
||||
//! \~english Set flag "i" to value "on"
|
||||
//! \~russian Устанавливает флаг "i" в "on"
|
||||
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
|
||||
//! copy operator
|
||||
|
||||
//! \~english Assign operator
|
||||
//! \~russian Оператор присваивания
|
||||
void operator =(const Enum & e) {flags = e;}
|
||||
//! copy operator
|
||||
|
||||
//! \~english Assign operator
|
||||
//! \~russian Оператор присваивания
|
||||
void operator =(const int & i) {flags = i;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator ==(const PIFlags & f) {return flags == f.flags;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator ==(const Enum & e) {return flags == e;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator ==(const int i) {return flags == i;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator !=(const PIFlags & f) {return flags != f.flags;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator !=(const Enum & e) {return flags != e;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator !=(const int i) {return flags != i;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >(const PIFlags & f) {return flags > f.flags;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >(const Enum & e) {return flags > e;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >(const int i) {return flags > i;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <(const PIFlags & f) {return flags < f.flags;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <(const Enum & e) {return flags < e;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <(const int i) {return flags < i;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >=(const PIFlags & f) {return flags >= f.flags;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >=(const Enum & e) {return flags >= e;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >=(const int i) {return flags >= i;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <=(const PIFlags & f) {return flags <= f.flags;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <=(const Enum & e) {return flags <= e;}
|
||||
//! compare operator
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <=(const int i) {return flags <= i;}
|
||||
//! Bit-wise AND operator
|
||||
|
||||
//! \~english Bit-wise AND operator
|
||||
//! \~russian Оператор побитового И
|
||||
void operator &=(const PIFlags & f) {flags &= f.flags;}
|
||||
//! Bit-wise AND operator
|
||||
|
||||
//! \~english Bit-wise AND operator
|
||||
//! \~russian Оператор побитового И
|
||||
void operator &=(const Enum & e) {flags &= e;}
|
||||
//! Bit-wise AND operator
|
||||
|
||||
//! \~english Bit-wise AND operator
|
||||
//! \~russian Оператор побитового И
|
||||
void operator &=(const int i) {flags &= i;}
|
||||
//! Bit-wise OR operator
|
||||
|
||||
//! \~english Bit-wise OR operator
|
||||
//! \~russian Оператор побитового ИЛИ
|
||||
void operator |=(const PIFlags & f) {flags |= f.flags;}
|
||||
//! Bit-wise OR operator
|
||||
|
||||
//! \~english Bit-wise OR operator
|
||||
//! \~russian Оператор побитового ИЛИ
|
||||
void operator |=(const Enum & e) {flags |= e;}
|
||||
//! Bit-wise OR operator
|
||||
|
||||
//! \~english Bit-wise OR operator
|
||||
//! \~russian Оператор побитового ИЛИ
|
||||
void operator |=(const int i) {flags |= i;}
|
||||
//! Bit-wise XOR operator
|
||||
|
||||
//! \~english Bit-wise XOR operator
|
||||
//! \~russian Оператор побитового исключающего ИЛИ
|
||||
void operator ^=(const PIFlags & f) {flags ^= f.flags;}
|
||||
//! Bit-wise XOR operator
|
||||
|
||||
//! \~english Bit-wise XOR operator
|
||||
//! \~russian Оператор побитового исключающего ИЛИ
|
||||
void operator ^=(const Enum & e) {flags ^= e;}
|
||||
//! Bit-wise XOR operator
|
||||
|
||||
//! \~english Bit-wise XOR operator
|
||||
//! \~russian Оператор побитового исключающего ИЛИ
|
||||
void operator ^=(const int i) {flags ^= i;}
|
||||
//! Bit-wise AND operator
|
||||
|
||||
//! \~english Bit-wise AND operator
|
||||
//! \~russian Оператор побитового И
|
||||
PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
|
||||
//! Bit-wise AND operator
|
||||
|
||||
//! \~english Bit-wise AND operator
|
||||
//! \~russian Оператор побитового И
|
||||
PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
|
||||
//! Bit-wise AND operator
|
||||
|
||||
//! \~english Bit-wise AND operator
|
||||
//! \~russian Оператор побитового И
|
||||
PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
|
||||
//! Bit-wise OR operator
|
||||
|
||||
//! \~english Bit-wise OR operator
|
||||
//! \~russian Оператор побитового ИЛИ
|
||||
PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
|
||||
//! Bit-wise OR operator
|
||||
|
||||
//! \~english Bit-wise OR operator
|
||||
//! \~russian Оператор побитового ИЛИ
|
||||
PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
|
||||
//! Bit-wise OR operator
|
||||
|
||||
//! \~english Bit-wise OR operator
|
||||
//! \~russian Оператор побитового ИЛИ
|
||||
PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
|
||||
//! Bit-wise XOR operator
|
||||
|
||||
//! \~english Bit-wise XOR operator
|
||||
//! \~russian Оператор побитового исключающего ИЛИ
|
||||
PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
|
||||
//! Bit-wise XOR operator
|
||||
|
||||
//! \~english Bit-wise XOR operator
|
||||
//! \~russian Оператор побитового исключающего ИЛИ
|
||||
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
|
||||
//! Bit-wise XOR operator
|
||||
|
||||
//! \~english Bit-wise XOR operator
|
||||
//! \~russian Оператор побитового исключающего ИЛИ
|
||||
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
|
||||
//! Test flag operator
|
||||
|
||||
//! \~english Test flag operator
|
||||
//! \~russian Оператор проверки флага
|
||||
bool operator [](Enum e) const {return (flags & e) == e;}
|
||||
//! Implicity conversion to \c int
|
||||
|
||||
//! \~english Implicity conversion to \c int
|
||||
//! \~russian Оператор неявного преобразования в \c int
|
||||
operator int() const {return flags;}
|
||||
|
||||
private:
|
||||
int flags;
|
||||
|
||||
};
|
||||
|
||||
#endif // PIFLAGS_H
|
||||
|
||||
@@ -95,7 +95,10 @@ int randomi() {
|
||||
}
|
||||
|
||||
|
||||
/*! \mainpage What is PIP
|
||||
/*! \~english \mainpage What is PIP
|
||||
* \~russian \mainpage Что такое PIP
|
||||
*
|
||||
* \~english
|
||||
* PIP - Platform-Independent Primitives - is crossplatform library for C++ developers.
|
||||
* It is wrap around STL and pure C++. This library can help developers write non-GUI
|
||||
* projects much more quickly, efficiently and customizable than on pure C++.
|
||||
@@ -112,10 +115,16 @@ int randomi() {
|
||||
* * executor (\a PIThreadPoolExecutor)
|
||||
* * blocking dequeue (\a PIBlockingDequeue)
|
||||
* * timer (\a PITimer)
|
||||
* * console (information output) (\a PIConsole)
|
||||
* * stand-alone
|
||||
* * server
|
||||
* * client
|
||||
* * tiling console (with widgets) (\a PIScreen)
|
||||
* * simple text rows
|
||||
* * scroll bar
|
||||
* * list
|
||||
* * button
|
||||
* * buttons group
|
||||
* * check box
|
||||
* * progress bar
|
||||
* * PICout output
|
||||
* * text input
|
||||
* * I/O devices
|
||||
* * base class (\a PIIODevice)
|
||||
* * file (\a PIFile)
|
||||
@@ -134,15 +143,72 @@ int randomi() {
|
||||
* * peering net node (\a PIPeer)
|
||||
* * process (\a PIProcess)
|
||||
* * state machine (\a PIStateMachine)
|
||||
* \n \n Basic using of PIP described at page \ref using_basic */
|
||||
* \n \n Basic using of PIP described at page \ref using_basic
|
||||
*
|
||||
* \~russian
|
||||
* PIP - Platform-Independent Primitives - кроссплатформенная библиотека для разработчиков на C++.
|
||||
* It is wrap around STL and pure C++. This library can help developers write non-GUI
|
||||
* projects much more quickly, efficiently and customizable than on pure C++.
|
||||
* PIP предоставляет следующие классы:
|
||||
* * общение с консолью (\a PICout)
|
||||
* * контейнеры (\a PIVector, \a PIList, \a PIMap, \a PIStack)
|
||||
* * байтовый массив (\a PIByteArray)
|
||||
* * строка (\a PIString, \a PIStringList)
|
||||
* * базовый объект (события и обработчики) (\a PIObject)
|
||||
* * многопоточность
|
||||
* * поток (\a PIThread)
|
||||
* * исполнитель (\a PIThreadPoolExecutor)
|
||||
* * блокирующая очередь (\a PIBlockingDequeue)
|
||||
* * таймер (\a PITimer)
|
||||
* * тайлинговая консоль (с виджетами) (\a PIScreen)
|
||||
* * простой вывод строк
|
||||
* * скроллбар
|
||||
* * лист
|
||||
* * кнопка
|
||||
* * группа кнопок
|
||||
* * галочка
|
||||
* * прогрессбар
|
||||
* * вывод PICout
|
||||
* * текстовый ввод
|
||||
* * устройства ввода/вывода
|
||||
* * базовый класс (\a PIIODevice)
|
||||
* * файл (\a PIFile)
|
||||
* * последовательный порт (\a PISerial)
|
||||
* * ethernet (\a PIEthernet)
|
||||
* * USB (\a PIUSB)
|
||||
* * packets extractor (\a PIPacketExtractor)
|
||||
* * бинарный логфайл (\a PIBinaryLog)
|
||||
* * сложное составное устройство (\a PIConnection)
|
||||
* * поддержка библиотек времени выполнения
|
||||
* * базовая функциональность (\a PILibrary)
|
||||
* * плагин (\a PIPluginLoader)
|
||||
* * диагностика качества связи (\a PIDiagnostics)
|
||||
* * парсер аргументов командной строки (\a PICLI)
|
||||
* * вычислитель (\a PIEvaluator)
|
||||
* * пиринговая сеть (\a PIPeer)
|
||||
* * процесс (\a PIProcess)
|
||||
* * машина состояний (\a PIStateMachine)
|
||||
* \n \n Базовое использование PIP описано на странице \ref using_basic
|
||||
*/
|
||||
|
||||
|
||||
/*! \page using_basic Getting started
|
||||
/*! \~english \page using_basic Getting started
|
||||
* \~russian \page using_basic Простые начала
|
||||
*
|
||||
* \~english
|
||||
* Many novice programmers are solved many common task with system integrity: output to console,
|
||||
* keyboard buttons press detecting, working with serial ports, ethernet or files, and many other.
|
||||
* These tasks can solve this library, and code, based only on PIP will be compile and work
|
||||
* similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX.
|
||||
* Typical application on PIP looks like this: \n
|
||||
*
|
||||
* \~russian
|
||||
* Многие начинающие программисты решают общие задачи взаимодействия с операционной системой:
|
||||
* вывод в консоль, определение нажатия клавиш, работа с последовательными портами, сетью или файлами,
|
||||
* и многое другое. Эти задачи решены в библиотеке, и код, основанный на PIP будет компилироваться
|
||||
* и работать одинаково на многих системах: Windows, любой Linux, Red Hat, FreeBSD, MacOS X и QNX.
|
||||
* Типовое приложение на PIP выглядит примерно так: \n
|
||||
*
|
||||
\code{.cpp}
|
||||
#include <pip.h>
|
||||
|
||||
@@ -232,15 +298,32 @@ int main(int argc, char * argv[]) {
|
||||
return 0;
|
||||
};
|
||||
\endcode
|
||||
*
|
||||
* \~english
|
||||
* This code demonstrates simple interactive configurable program, which can be started with console
|
||||
* display or not, and with debug or not. \b MainClass is central class that also can be inherited from
|
||||
* \a PIThread and reimplement \a run() function.
|
||||
* \n Many PIP classes has events and event handlers, which can be connected one to another.
|
||||
* Details you can see at \a PIObject reference page (\ref PIObject_sec0).
|
||||
* \n To configure your program from file use \a PIConfig.
|
||||
* \n If you want more information see \ref using_advanced */
|
||||
* \n If you want more information see \ref using_advanced
|
||||
*
|
||||
* \~russian
|
||||
* Этот код демонстрирует простую конфигурируемую программу, которая может быть запущена с
|
||||
* This code demonstrates simple interactive configurable program, which can be started with console
|
||||
* display or not, and with debug or not. \b MainClass is central class that also can be inherited from
|
||||
* \a PIThread and reimplement \a run() function.
|
||||
* \n Many PIP classes has events and event handlers, which can be connected one to another.
|
||||
* Details you can see at \a PIObject reference page (\ref PIObject_sec0).
|
||||
* \n To configure your program from file use \a PIConfig.
|
||||
*/
|
||||
|
||||
|
||||
/*! \page using_advanced Advanced using
|
||||
* Sorry, creativity crysis xD
|
||||
*/
|
||||
|
||||
/*
|
||||
* \~english
|
||||
* \~russian
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
/*! \file piincludes.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Minimal PIP includes
|
||||
* \~russian Минимально-необходимые инклюды PIP
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Minimal PIP includes
|
||||
@@ -26,15 +32,15 @@
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
# include <iostream>
|
||||
#endif
|
||||
#include <atomic>
|
||||
|
||||
|
||||
class PIMutex;
|
||||
class PIMutexLocker;
|
||||
class PIObject;
|
||||
class PIString;
|
||||
class PIByteArray;
|
||||
#ifndef MICRO_PIP
|
||||
class PIInit;
|
||||
#endif
|
||||
class PIChar;
|
||||
class PICout;
|
||||
|
||||
@@ -42,10 +48,20 @@ struct lconv;
|
||||
|
||||
extern PIP_EXPORT lconv * currentLocale;
|
||||
|
||||
/*! \fn errorString()
|
||||
* @brief Return readable error description in format "code <number> - <description>" */
|
||||
//! \ingroup Core
|
||||
//! \brief
|
||||
//! \~english
|
||||
//! Return readable error description in format "code <number> - <description>"
|
||||
//! \~russian
|
||||
//! Возвращает читаемое описание ошибки в формате "code <номер> - <описание>"
|
||||
PIP_EXPORT PIString errorString();
|
||||
|
||||
//! \ingroup Core
|
||||
//! \brief
|
||||
//! \~english
|
||||
//! Reset last error
|
||||
//! \~russian
|
||||
//! Сброс последней ошибки
|
||||
PIP_EXPORT void errorClear();
|
||||
|
||||
PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
|
||||
@@ -53,7 +69,10 @@ PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const
|
||||
PIP_EXPORT void randomize();
|
||||
PIP_EXPORT int randomi();
|
||||
|
||||
/// Return readable version of PIP
|
||||
//! \ingroup Core
|
||||
//! \brief
|
||||
//! \~english Return readable version of PIP
|
||||
//! \~russian Возвращает читаемую версию PIP
|
||||
PIP_EXPORT PIString PIPVersion();
|
||||
|
||||
#endif // PIINCLUDES_H
|
||||
|
||||
@@ -40,6 +40,15 @@ typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef FREERTOS
|
||||
# ifdef ESP_PLATFORM
|
||||
# include "freertos/FreeRTOS.h"
|
||||
# include "freertos/task.h"
|
||||
# endif
|
||||
# ifdef ARDUINO_ARCH_STM32
|
||||
# include <STM32FreeRTOS.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // PIINCLUDES_P_H
|
||||
|
||||
@@ -19,15 +19,15 @@
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "piinit.h"
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
#include "pitime.h"
|
||||
#include "pisignals.h"
|
||||
#include "piobject.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "piresourcesstorage.h"
|
||||
#include "pidir.h"
|
||||
#ifndef FREERTOS
|
||||
# include "piprocess.h"
|
||||
#endif
|
||||
#include "piprocess.h"
|
||||
#ifdef ESP_PLATFORM
|
||||
# include "esp_system.h"
|
||||
#endif
|
||||
@@ -49,9 +49,7 @@ void __PISetTimerResolution() {
|
||||
}
|
||||
#else
|
||||
# include <pwd.h>
|
||||
# ifndef FREERTOS
|
||||
# include <sys/utsname.h>
|
||||
# endif
|
||||
# include <sys/utsname.h>
|
||||
# include <pthread.h>
|
||||
# ifdef BLACKBERRY
|
||||
# include <signal.h>
|
||||
@@ -84,7 +82,6 @@ ULONG prev_res;
|
||||
bool delete_locs;
|
||||
PRIVATE_DEFINITION_END(PIInit)
|
||||
|
||||
#ifndef FREERTOS
|
||||
void __sighandler__(PISignals::Signal s) {
|
||||
//piCout << Hex << int(s);
|
||||
if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput)
|
||||
@@ -92,7 +89,6 @@ void __sighandler__(PISignals::Signal s) {
|
||||
if (s == PISignals::UserDefined1)
|
||||
dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID()));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ANDROID
|
||||
@@ -107,7 +103,6 @@ PIInit::PIInit() {
|
||||
PISystemInfo * sinfo = PISystemInfo::instance();
|
||||
sinfo->execDateTime = PIDateTime::current();
|
||||
setFileCharset("UTF-8");
|
||||
#ifndef FREERTOS
|
||||
#ifndef ANDROID
|
||||
PISignals::setSlot(__sighandler__);
|
||||
PISignals::grabSignals(PISignals::UserDefined1);
|
||||
@@ -128,7 +123,7 @@ PIInit::PIInit() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
# else
|
||||
# else //WINDOWS
|
||||
// OS version
|
||||
DWORD dwVersion = GetVersion();
|
||||
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
|
||||
@@ -154,7 +149,7 @@ PIInit::PIInit() {
|
||||
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
|
||||
__PISetTimerResolution();
|
||||
}
|
||||
# endif
|
||||
# endif //WINDOWS
|
||||
# ifdef HAS_LOCALE
|
||||
//cout << "has locale" << endl;
|
||||
if (currentLocale_t != 0) {
|
||||
@@ -162,18 +157,18 @@ PIInit::PIInit() {
|
||||
currentLocale_t = 0;
|
||||
}
|
||||
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0);
|
||||
# else
|
||||
# else //HAS_LOCALE
|
||||
setlocale(LC_ALL, "");
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
# endif
|
||||
#else
|
||||
# endif //HAS_LOCALE
|
||||
#else //ANDROID
|
||||
struct sigaction actions;
|
||||
memset(&actions, 0, sizeof(actions));
|
||||
sigemptyset(&actions.sa_mask);
|
||||
actions.sa_flags = 0;
|
||||
actions.sa_handler = android_thread_exit_handler;
|
||||
sigaction(SIGTERM, &actions, 0);
|
||||
#endif
|
||||
#endif //ANDROID
|
||||
PRIVATE->delete_locs = false;
|
||||
__syslocname__ = __sysoemname__ = 0;
|
||||
__utf8name__ = const_cast<char*>("UTF-8");
|
||||
@@ -201,13 +196,13 @@ PIInit::PIInit() {
|
||||
# endif
|
||||
//piCout << __syslocname__;
|
||||
//piCout << __sysoemname__;
|
||||
#else
|
||||
#else //PIP_ICU
|
||||
# ifdef WINDOWS
|
||||
__syslocname__ = (char *)CP_ACP;
|
||||
__sysoemname__ = (char *)CP_OEMCP;
|
||||
__utf8name__ = (char *)CP_UTF8;
|
||||
# endif
|
||||
#endif
|
||||
#endif //PIP_ICU
|
||||
#ifdef MAC_OS
|
||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
|
||||
#endif
|
||||
@@ -236,7 +231,7 @@ PIInit::PIInit() {
|
||||
ulong unlen = 1023;
|
||||
if (GetUserName(cbuff, &unlen) != 0)
|
||||
sinfo->user = cbuff;
|
||||
#else
|
||||
#else //WINDOWS
|
||||
sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN)));
|
||||
passwd * ps = getpwuid(getuid());
|
||||
if (ps)
|
||||
@@ -252,8 +247,8 @@ PIInit::PIInit() {
|
||||
sinfo->OS_version = uns.release;
|
||||
sinfo->architecture = uns.machine;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
#endif //WINDOWS
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
@@ -275,6 +270,8 @@ PIInit::PIInit() {
|
||||
PIStringAscii("FreeBSD");
|
||||
#elif defined(FREERTOS)
|
||||
PIStringAscii("FreeRTOS");
|
||||
#elif defined(MICRO_PIP)
|
||||
PIStringAscii("MicroPIP");
|
||||
#else
|
||||
uns.sysname;
|
||||
#endif
|
||||
@@ -305,49 +302,49 @@ PIInit::~PIInit() {
|
||||
|
||||
bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
|
||||
switch (o) {
|
||||
case ICU: return
|
||||
case boICU: return
|
||||
#ifdef PIP_ICU
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case USB: return
|
||||
case boUSB: return
|
||||
#ifdef PIP_USB
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case Crypt: return
|
||||
case boCrypt: return
|
||||
#ifdef PIP_CRYPT
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case Introspection: return
|
||||
case boIntrospection: return
|
||||
#ifdef PIP_INTROSPECTION
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case FFTW: return
|
||||
case boFFTW: return
|
||||
#ifdef PIP_FFTW
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case Compress: return
|
||||
case boCompress: return
|
||||
#ifdef PIP_COMPRESS
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case OpenCL: return
|
||||
case boOpenCL: return
|
||||
#ifdef PIP_OPENCL
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case Cloud: return
|
||||
case boCloud: return
|
||||
#ifdef PIP_CLOUD
|
||||
true;
|
||||
#else
|
||||
@@ -361,14 +358,14 @@ bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
|
||||
|
||||
PIStringList PIInit::buildOptions() {
|
||||
PIStringList ret;
|
||||
if (isBuildOptionEnabled(ICU)) ret << "ICU";
|
||||
if (isBuildOptionEnabled(USB)) ret << "USB";
|
||||
if (isBuildOptionEnabled(Crypt)) ret << "Crypt";
|
||||
if (isBuildOptionEnabled(Introspection)) ret << "Introspection";
|
||||
if (isBuildOptionEnabled(FFTW)) ret << "FFTW";
|
||||
if (isBuildOptionEnabled(Compress)) ret << "Compress";
|
||||
if (isBuildOptionEnabled(OpenCL)) ret << "OpenCL";
|
||||
if (isBuildOptionEnabled(Cloud)) ret << "Cloud";
|
||||
if (isBuildOptionEnabled(boICU)) ret << "ICU";
|
||||
if (isBuildOptionEnabled(boUSB)) ret << "USB";
|
||||
if (isBuildOptionEnabled(boCrypt)) ret << "Crypt";
|
||||
if (isBuildOptionEnabled(boIntrospection)) ret << "Introspection";
|
||||
if (isBuildOptionEnabled(boFFTW)) ret << "FFTW";
|
||||
if (isBuildOptionEnabled(boCompress)) ret << "Compress";
|
||||
if (isBuildOptionEnabled(boOpenCL)) ret << "OpenCL";
|
||||
if (isBuildOptionEnabled(boCloud)) ret << "Cloud";
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -415,3 +412,6 @@ __PIInit_Initializer__::~__PIInit_Initializer__() {
|
||||
__instance__ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MICRO_PIP
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
/*! @file piinit.h
|
||||
* @brief Initialization
|
||||
/*! \file piinit.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Library initialization
|
||||
* \~russian Инициализация библиотеки
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -23,6 +26,10 @@
|
||||
#ifndef PIINIT_H
|
||||
#define PIINIT_H
|
||||
|
||||
#include "pibase.h"
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
|
||||
#include "piincludes.h"
|
||||
|
||||
|
||||
@@ -47,19 +54,29 @@ class PIP_EXPORT PIInit {
|
||||
public:
|
||||
~PIInit();
|
||||
|
||||
//! @brief Build options which PIP library was built
|
||||
//! \ingroup Core
|
||||
//! \~english Build options which PIP library was built
|
||||
//! \~russian Опции, с которыми был собран PIP
|
||||
enum BuildOption {
|
||||
ICU /*! Unicode support */ = 0x01,
|
||||
USB /*! USB support */ = 0x02,
|
||||
Crypt /*! Crypt support */ = 0x08,
|
||||
Introspection /*! Introspection */ = 0x010,
|
||||
FFTW /*! FFTW3 support */ = 0x40,
|
||||
Compress /*! Zlib compression support */ = 0x80,
|
||||
OpenCL /*! OpenCL support */ = 0x100,
|
||||
Cloud /*! Cloud transport support */ = 0x200,
|
||||
boICU /*! \~english Unicode support by ICU \~russian Поддержка юникода через ICU */ = 0x01,
|
||||
boUSB /*! \~english USB support \~russian Поддержка USB */ = 0x02,
|
||||
boCrypt /*! \~english Crypt support \~russian Поддержка шифрования */ = 0x08,
|
||||
boIntrospection /*! \~english Introspection \~russian Интроспекция */ = 0x010,
|
||||
boFFTW /*! \~english FFTW3 support \~russian Поддержка FFTW3 */ = 0x40,
|
||||
boCompress /*! \~english Zlib compression support \~russian Поддержка сжатия Zlib */ = 0x80,
|
||||
boOpenCL /*! \~english OpenCL support \~russian Поддержка OpenCL */ = 0x100,
|
||||
boCloud /*! \~english PICloud transport support \~russian Поддержка облачного транспорта PICloud */ = 0x200,
|
||||
};
|
||||
static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
|
||||
|
||||
//! \ingroup Core
|
||||
//! \~english Returns if build option was enabled
|
||||
//! \~russian Возвращает была ли включена опция при сборке
|
||||
static bool isBuildOptionEnabled(BuildOption o);
|
||||
|
||||
//! \ingroup Core
|
||||
//! \~english Returns build options as stringlist
|
||||
//! \~russian Возвращает опции сборки как список строк
|
||||
static PIStringList buildOptions();
|
||||
private:
|
||||
explicit PIInit();
|
||||
@@ -70,4 +87,5 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif // MICRO_PIP
|
||||
#endif // PIINIT_H
|
||||
|
||||
@@ -18,44 +18,96 @@
|
||||
*/
|
||||
|
||||
#include "piobject.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "pithread.h"
|
||||
#include "piconditionvar.h"
|
||||
#ifndef FREERTOS
|
||||
#ifndef MICRO_PIP
|
||||
# include "pisysteminfo.h"
|
||||
# include "pifile.h"
|
||||
#endif
|
||||
|
||||
/** \class PIObject
|
||||
* @brief This is base class for any classes which use events -> handlers mechanism.
|
||||
* \details
|
||||
* \section PIObject_sec0 Events and Event handlers
|
||||
* %PIObject provide notification mechanism similar Qt but implemented
|
||||
* on language capabilities without any special preprocessors or compilers.
|
||||
* Any class inherits PIObject should use macro \a PIOBJECT() immediate
|
||||
* after declaration to proper compile.
|
||||
*
|
||||
* Event is a some abstract event that can be raised at any time.
|
||||
* Event is a function but declared with special macro \a EVENT().
|
||||
* To raise event simply execute event function.
|
||||
*
|
||||
* Event handler is a function but declared with special macro
|
||||
* \a EVENT_HANDLER(). You can use event handlers as ordinary functions.
|
||||
*
|
||||
* Main goal of this mechanism is perform abstract connections between
|
||||
* various objects. This functionality provide macro \a CONNECT() which
|
||||
* connect some event of first object to some event handler or event of
|
||||
* second object. Each event can be connected any times to any event handlers.
|
||||
*
|
||||
* \image html events_handlers.png
|
||||
*
|
||||
* Example: \snippet piobject.cpp main
|
||||
* Result:
|
||||
\code{.cpp}
|
||||
handler B: 2 , 0.5
|
||||
handler A: event to handler
|
||||
handler A: event to event
|
||||
\endcode
|
||||
*/
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PIObject piobject.h
|
||||
//! \~\brief
|
||||
//! \~english This is base class for any classes which use events -> handlers mechanism
|
||||
//! \~russian Этот класс является базовым для использования механизма события -> обработчики
|
||||
//!
|
||||
//! \~\details
|
||||
//! \~english \section PIObject_sec0 Events and Event handlers
|
||||
//! \~russian \section PIObject_sec0 События и Обработчики событий
|
||||
//!
|
||||
//! \~english
|
||||
//! %PIObject provide notification mechanism similar Qt but implemented
|
||||
//! on language capabilities without any special preprocessors or compilers.
|
||||
//! Any class inherits %PIObject should use macro \a PIOBJECT() immediate
|
||||
//! after declaration to proper compile.
|
||||
//!
|
||||
//! Event is a some abstract event that can be raised at any time as common method.
|
||||
//! Event is a function but declared with special macro \a EVENT() and don`t need definition.
|
||||
//! To raise event simply execute event function.
|
||||
//!
|
||||
//! Event handler is a function but declared with special macro
|
||||
//! \a EVENT_HANDLER(). It need definition as common method.
|
||||
//! You can use event handlers as ordinary functions.
|
||||
//!
|
||||
//! Main goal of this mechanism is perform abstract connections between
|
||||
//! various objects. This functionality provide macro \a CONNECT(), \a CONNECTU() and \a CONNECTL() which
|
||||
//! connect some event of first object to some event handler or event of
|
||||
//! second object. Each event can be connected any times to any event handlers.
|
||||
//!
|
||||
//! * \a CONNECT() macros family work with explicit subclasses of %PIObject with compile-time check of events and handlers
|
||||
//! * \a CONNECTU() macro can work implicit subclasses of %PIObject with run-time check of events and handlers
|
||||
//! * \a CONNECTU_QUEUED() macro similar to \a CONNECTU() macro but queue execution with performer object instead of handler direct call
|
||||
//! * \a CONNECTL() macro work with implicit subclasses of %PIObject and lambda-function
|
||||
//!
|
||||
//! \~russian
|
||||
//! %PIObject предоставляет механизм событий и их обработчиков, реализованный без
|
||||
//! дополнительного препроцессора или метакомпилятора. Любой класс, наследованный
|
||||
//! от %PIObject должен использовать макрос \a PIOBJECT() сразу после объявления
|
||||
//! класса для корректной работы.
|
||||
//!
|
||||
//! Событием является сигнал, который может быть вызван как обычный метод в любое время.
|
||||
//! Это метод, объявленный с помощью макроса \a EVENT() и не требует описания.
|
||||
//! Для его вызова просто вызывается метод события.
|
||||
//!
|
||||
//! Обработчик события это метод, объявленный с помощью макроса \a EVENT_HANDLER()
|
||||
//! и он требует описания, как и обычный метод. Можно его использовать как обычный метод.
|
||||
//!
|
||||
//! Основной функцией этого механизма является реализация соединений между различными объектами.
|
||||
//! Её предоставляют макросы \a CONNECT(), \a CONNECTU() и \a CONNECTL(), которые соединяют
|
||||
//! события одних объектов с обработчиками или событиями других объектов. Каждое событие
|
||||
//! может быть присоеденино неограниченное количество раз к любым обработчикам.
|
||||
//!
|
||||
//! * \a CONNECT() семейство макросов работает с явными наследниками %PIObject, и проверяет соединение во время компиляции
|
||||
//! * \a CONNECTU() макрос может работать с неявными наследниками %PIObject, и проверяет соединение во время исполнения
|
||||
//! * \a CONNECTU_QUEUED() макрос подобен \a CONNECTU(), но планирует вызов обработчика у объекта performer вместо прямого вызова
|
||||
//! * \a CONNECTL() макрос может работать с неявными наследниками %PIObject и лямбда-функцией
|
||||
//!
|
||||
//! \~\image html events_handlers.png
|
||||
//!
|
||||
//! \~english Example:
|
||||
//! \~russian Пример:
|
||||
//!
|
||||
//! \~\snippet piobject.cpp main
|
||||
//! \~english Result:
|
||||
//! \~russian Результат:
|
||||
//! \~\code{.cpp}
|
||||
//! handler B: 2 , 0.5
|
||||
//! handler A: event to handler
|
||||
//! handler A: event to event
|
||||
//! event to lambda
|
||||
//! \endcode
|
||||
//! \}
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PIObject::Connection piobject.h
|
||||
//! \~\brief
|
||||
//! \~english Helper class for obtain info about if connection successful and disconnect single connection
|
||||
//! \~russian Вспомогательный класс для получения информации об успешности соединения и возможности его разрыва
|
||||
//! \}
|
||||
|
||||
|
||||
PIString PIObject::__MetaFunc::arguments() const {
|
||||
@@ -91,9 +143,11 @@ PIObject::~PIObject() {
|
||||
mutexObjects().lock();
|
||||
objects().removeAll(this);
|
||||
mutexObjects().unlock();
|
||||
piDisconnect(this);
|
||||
deleted(this);
|
||||
piDisconnectAll();
|
||||
}
|
||||
|
||||
|
||||
PIMap<PIString, PIVariant> PIObject::properties() const {
|
||||
PIMap<PIString, PIVariant> ret;
|
||||
piForeachC (PropertyHash p, properties_)
|
||||
@@ -141,50 +195,6 @@ bool PIObject::executeQueued(PIObject * performer, const PIString & method, cons
|
||||
}
|
||||
|
||||
|
||||
void PIObject::piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h) {
|
||||
PIObject * o = findByName(src);
|
||||
if (o == 0) {
|
||||
piCout << "[PIObject] Can`t find object with name \"" << src << "\"!";
|
||||
return;
|
||||
}
|
||||
PIMutexLocker _ml(o->mutex_connect);
|
||||
PIMutexLocker _mld(((PIObject*)dest)->mutex_connect, ((PIObject*)dest) != o);
|
||||
o->connections << __Connection(ev_h, 0, sig, (PIObject*)dest, dest);
|
||||
((PIObject*)dest)->connectors << o;
|
||||
}
|
||||
|
||||
|
||||
void PIObject::piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h) {
|
||||
PIObject * o = findByName(dest);
|
||||
if (o == 0) {
|
||||
piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!";
|
||||
return;
|
||||
}
|
||||
PIMutexLocker _ml(src->mutex_connect);
|
||||
PIMutexLocker _mld(o->mutex_connect, src != o);
|
||||
src->connections << __Connection(ev_h, 0, sig, o, o);
|
||||
((PIObject*)o)->connectors << src;
|
||||
}
|
||||
|
||||
|
||||
void PIObject::piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h) {
|
||||
PIObject * s = findByName(src);
|
||||
if (s == 0) {
|
||||
piCout << "[PIObject] Can`t find object with name \"" << src << "\"!";
|
||||
return;
|
||||
}
|
||||
PIObject * d = findByName(dest);
|
||||
if (d == 0) {
|
||||
piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!";
|
||||
return;
|
||||
}
|
||||
PIMutexLocker _ml(s->mutex_connect);
|
||||
PIMutexLocker _mld(d->mutex_connect, s != d);
|
||||
s->connections << __Connection(ev_h, 0, sig, d, d);
|
||||
d->connectors << s;
|
||||
}
|
||||
|
||||
|
||||
PIStringList PIObject::scopeList() const {
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
return __meta_data()[classNameID()].scope_list;
|
||||
@@ -256,31 +266,33 @@ PIObject::__MetaFunc PIObject::methodEH(const void * addr) const {
|
||||
}
|
||||
|
||||
|
||||
void PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc) {
|
||||
PIObject::Connection PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc) {
|
||||
//piCout << "piConnect ...";
|
||||
//piCout << "piConnect" << src << (void*)(dest) << sig;
|
||||
//piCout << "piConnect" << src->className() << "->" << ((PIObject*)dest)->className();
|
||||
PIMutexLocker _ml(src->mutex_connect);
|
||||
PIMutexLocker _mld(dest_o->mutex_connect, src != dest_o);
|
||||
|
||||
src->connections << __Connection(ev_h, e_h, sig, dest_o, dest, args);
|
||||
Connection conn(ev_h, e_h, sig, src, dest_o, dest, args);
|
||||
src->connections << conn;
|
||||
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s() << "...";
|
||||
//piCout << "addConnector" << dest_o << src;
|
||||
dest_o->connectors << src;
|
||||
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s();
|
||||
//piCout << "piConnect ok";
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
bool PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer) {
|
||||
if (src == 0 || dest_o == 0 || dest == 0) return false;
|
||||
PIObject::Connection PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer) {
|
||||
if (src == 0 || dest_o == 0 || dest == 0) return Connection();
|
||||
if (!src->isPIObject()) {
|
||||
piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")";
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
if (!dest_o->isPIObject()) {
|
||||
piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: destination object is not PIObject! (" << loc << ")";
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
PIMutexLocker mls(src->mutex_connect);
|
||||
@@ -288,11 +300,11 @@ bool PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_
|
||||
PIVector<__MetaFunc> m_src = src->findEH(sig), m_dest = dest_o->findEH(hname);
|
||||
if (m_src.isEmpty()) {
|
||||
piCout << "[piConnectU] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
if (m_dest.isEmpty()) {
|
||||
piCout << "[piConnectU] Error: can`t find handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
void * addr_src(0), * addr_dest(0);
|
||||
int args(0);
|
||||
@@ -311,25 +323,26 @@ bool PIObject::piConnectU(PIObject * src, const PIString & sig, PIObject * dest_
|
||||
if (addr_src == 0) {
|
||||
piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << sig << "\" in class \"" << src->className()
|
||||
<< "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
src->connections << PIObject::__Connection(addr_dest, addr_src, sig, dest_o, dest, args, performer);
|
||||
Connection conn(addr_dest, addr_src, sig, src, dest_o, dest, args, performer);
|
||||
src->connections << conn;
|
||||
if (que) performer->proc_event_queue = true;
|
||||
dest_o->connectors << src;
|
||||
//piCout << cc << cq << _ol.size();//"connect" << src << "->" << dest_o << ", dest.connectors.size() =" << dest_o->connectors.size();
|
||||
return true;
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc) {
|
||||
PIObject::Connection PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc) {
|
||||
if (src == 0) {
|
||||
delete f;
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
if (!src->isPIObject()) {
|
||||
piCout << "[piConnectLS] \"" << sig << "\" -> [lambda] error: source object is not PIObject! (" << loc << ")";
|
||||
delete f;
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
PIMutexLocker mls(src->mutex_connect);
|
||||
@@ -338,19 +351,19 @@ bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function<v
|
||||
if (m_src.isEmpty()) {
|
||||
piCout << "[piConnectLS] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
|
||||
delete f;
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
if (m_src.size() != 1) {
|
||||
piCout << "[piConnectLS] Error: can`t connect overloaded event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
|
||||
delete f;
|
||||
return false;
|
||||
return Connection();
|
||||
}
|
||||
PIObject::__Connection conn(0, m_src[0].addr, sig);
|
||||
PIObject::Connection conn(0, m_src[0].addr, sig, src);
|
||||
//piCout << "found";
|
||||
conn.functor = f;
|
||||
src->connections << conn;
|
||||
//piCout << "finished";
|
||||
return true;
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
@@ -358,7 +371,7 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * des
|
||||
PIMutexLocker _ml(src->mutex_connect);
|
||||
PIMutexLocker _mld(dest->mutex_connect, src != dest);
|
||||
for (int i = 0; i < src->connections.size_s(); ++i) {
|
||||
__Connection & cc(src->connections[i]);
|
||||
Connection & cc(src->connections[i]);
|
||||
if (cc.event == sig && cc.dest_o == dest && cc.slot == ev_h) {
|
||||
src->connections[i].destroy();
|
||||
src->connections.remove(i);
|
||||
@@ -373,7 +386,7 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * des
|
||||
PIMutexLocker _ml(src->mutex_connect);
|
||||
PIMutexLocker _mld(dest->mutex_connect, src != dest);
|
||||
for (int i = 0; i < src->connections.size_s(); ++i) {
|
||||
__Connection & cc(src->connections[i]);
|
||||
Connection & cc(src->connections[i]);
|
||||
if (cc.event == sig && cc.dest_o == dest) {
|
||||
src->connections[i].destroy();
|
||||
src->connections.remove(i);
|
||||
@@ -387,14 +400,14 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * des
|
||||
void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
|
||||
PIMutexLocker _ml(src->mutex_connect);
|
||||
for (int i = 0; i < src->connections.size_s(); ++i) {
|
||||
__Connection & cc(src->connections[i]);
|
||||
Connection & cc(src->connections[i]);
|
||||
if (cc.event == sig) {
|
||||
PIObject * dest = cc.dest_o;
|
||||
if (!dest) {
|
||||
src->connections[i].destroy();
|
||||
src->connections.remove(i);
|
||||
i--;
|
||||
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS)
|
||||
src->connections[i].destroy();
|
||||
src->connections.remove(i);
|
||||
i--;
|
||||
if (dest) {
|
||||
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
|
||||
PIMutexLocker _mld(dest->mutex_connect, src != dest);
|
||||
#endif
|
||||
dest->updateConnectors();
|
||||
@@ -404,37 +417,38 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
|
||||
}
|
||||
|
||||
|
||||
void PIObject::piDisconnect(PIObject * src) {
|
||||
src->deleted(src);
|
||||
PIMutexLocker _ml(src->mutex_connect);
|
||||
PIVector<PIObject * > cv = src->connectors.toVector();
|
||||
void PIObject::piDisconnectAll() {
|
||||
PIMutexLocker _ml(mutex_connect);
|
||||
PIVector<PIObject * > cv = connectors.toVector();
|
||||
// piCout << "disconnect connectors =" << connectors.size();
|
||||
piForeach (PIObject * o, cv) {
|
||||
//piCout << "disconnect"<< src->className()<< o->className();
|
||||
if (!o || (o == src)) continue;
|
||||
// piCout << "disconnect"<< src << o;
|
||||
if (!o || (o == this)) continue;
|
||||
if (!o->isPIObject()) continue;
|
||||
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS)
|
||||
PIMutexLocker _mld(o->mutex_connect, src != o);
|
||||
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
|
||||
PIMutexLocker _mld(o->mutex_connect, this != o);
|
||||
#endif
|
||||
PIVector<__Connection> & oc(o->connections);
|
||||
PIVector<Connection> & oc(o->connections);
|
||||
for (int i = 0; i < oc.size_s(); ++i) {
|
||||
if (oc[i].functor) continue;
|
||||
//piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src);
|
||||
if (oc[i].dest_o == src) {
|
||||
if (oc[i].dest_o == this) {
|
||||
oc[i].destroy();
|
||||
oc.remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
piForeachC (PIObject::__Connection & c, src->connections) {
|
||||
// piCout << "disconnect connections =" << connections.size();
|
||||
piForeachC (PIObject::Connection & c, connections) {
|
||||
if (c.functor) continue;
|
||||
if (!c.dest_o) continue;
|
||||
if (!c.dest_o->isPIObject()) continue;
|
||||
c.dest_o->connectors.remove(src);
|
||||
c.dest_o->connectors.remove(this);
|
||||
}
|
||||
for (int i = 0; i < src->connections.size_s(); ++i)
|
||||
src->connections[i].destroy();
|
||||
src->connections.clear();
|
||||
for (int i = 0; i < connections.size_s(); ++i)
|
||||
connections[i].destroy();
|
||||
connections.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -444,8 +458,8 @@ void PIObject::updateConnectors() {
|
||||
PIMutexLocker _ml(mutexObjects());
|
||||
piForeach (PIObject * o, objects()) {
|
||||
if (o == this) continue;
|
||||
PIVector<__Connection> & oc(o->connections);
|
||||
piForeach (__Connection & c, oc)
|
||||
PIVector<Connection> & oc(o->connections);
|
||||
piForeach (Connection & c, oc)
|
||||
if (c.dest == this)
|
||||
connectors << o;
|
||||
}
|
||||
@@ -492,6 +506,14 @@ void PIObject::callQueuedEvents() {
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english
|
||||
//! On first call background thread started to delete objects.
|
||||
//! Each object deletes when it`s outside from any events and hadlers.
|
||||
//! \~russian
|
||||
//! При первом вызове стартует фоновый поток для удаления объектов.
|
||||
//! Каждый объект из очереди удаляется только когда выйдет из всех
|
||||
//! событий и обработок.
|
||||
void PIObject::deleteLater() {
|
||||
Deleter::instance()->post(this);
|
||||
}
|
||||
@@ -606,7 +628,7 @@ void PIObject::dump(const PIString & line_prefix) const {
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " connections {";
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << connections.size_s();
|
||||
//printf("dump %d connections\n",connections.size());
|
||||
piForeachC (__Connection & c, connections) {
|
||||
piForeachC (Connection & c, connections) {
|
||||
PIObject * dst = c.dest_o;
|
||||
__MetaFunc ef = methodEH(c.signal);
|
||||
PIString src(c.event);
|
||||
@@ -627,6 +649,7 @@ void PIObject::dump(const PIString & line_prefix) const {
|
||||
}
|
||||
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
void dumpApplication() {
|
||||
PIMutexLocker _ml(PIObject::mutexObjects());
|
||||
//printf("dump application ...\n");
|
||||
@@ -653,7 +676,6 @@ void dumpApplication() {
|
||||
}
|
||||
|
||||
|
||||
#ifndef FREERTOS
|
||||
bool dumpApplicationToFile(const PIString & path) {
|
||||
PIFile f(path + "_tmp");
|
||||
f.setName("__S__DumpFile");
|
||||
@@ -679,41 +701,87 @@ void PIObject::__MetaData::addScope(const PIString & s, uint shash) {
|
||||
}
|
||||
|
||||
|
||||
void PIObject::__Connection::destroy() {
|
||||
|
||||
|
||||
void PIObject::Connection::destroy() {
|
||||
if (functor) delete functor;
|
||||
functor = nullptr;
|
||||
}
|
||||
|
||||
|
||||
PIObject::Connection::Connection() {
|
||||
slot = signal = dest = nullptr;
|
||||
src_o = dest_o = performer = nullptr;
|
||||
functor = nullptr;
|
||||
eventID = 0;
|
||||
args_count = 0;
|
||||
}
|
||||
|
||||
|
||||
bool PIObject::Connection::disconnect() {
|
||||
if (!isValid() || !src_o) return false;
|
||||
if (!src_o->isPIObject()) return false;
|
||||
bool ndm = dest_o && (src_o != dest_o), ret = false, found = false;
|
||||
if (dest_o) {
|
||||
if (!dest_o->isPIObject()) ndm = false;
|
||||
}
|
||||
PIMutexLocker _ml(src_o->mutex_connect);
|
||||
if (ndm) dest_o->mutex_connect.lock();
|
||||
for (int i = 0; i < src_o->connections.size_s(); ++i) {
|
||||
Connection & cc(src_o->connections[i]);
|
||||
if (cc.eventID == eventID) {
|
||||
if (dest_o && (cc.dest_o == dest_o)) {
|
||||
if (cc.slot == slot)
|
||||
found = true;
|
||||
}
|
||||
if (functor && (cc.functor == functor))
|
||||
found = true;
|
||||
}
|
||||
if (found) {
|
||||
src_o->connections[i].destroy();
|
||||
src_o->connections.remove(i);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dest_o) {
|
||||
if (dest_o->isPIObject())
|
||||
dest_o->updateConnectors();
|
||||
}
|
||||
if (ndm) dest_o->mutex_connect.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PIObject::Deleter)
|
||||
PIThread thread;
|
||||
PIConditionVariable cond_var;
|
||||
PIMutex cond_mutex, queue_mutex;
|
||||
PIVector<PIObject*> obj_queue;
|
||||
PRIVATE_DEFINITION_END(PIObject::Deleter)
|
||||
|
||||
|
||||
PIObject::Deleter::Deleter() {
|
||||
//piCout << "Deleter start ...";
|
||||
stopping = started = posted = false;
|
||||
CONNECTL(&(PRIVATE->thread), started, [this](){proc();});
|
||||
PRIVATE->thread.startOnce();
|
||||
while (!started)
|
||||
piMSleep(1);
|
||||
PRIVATE->thread.setSlot([this](){
|
||||
PIVector<PIObject*> oq;
|
||||
PRIVATE->thread.lock();
|
||||
while(PRIVATE->obj_queue.isEmpty()) PRIVATE->cond_var.wait(PRIVATE->thread.mutex());
|
||||
oq.swap(PRIVATE->obj_queue);
|
||||
PRIVATE->thread.unlock();
|
||||
for (PIObject * o : oq) deleteObject(o);
|
||||
});
|
||||
PRIVATE->thread.start();
|
||||
}
|
||||
|
||||
|
||||
PIObject::Deleter::~Deleter() {
|
||||
//piCout << "~Deleter ...";
|
||||
stopping = true;
|
||||
PRIVATE->thread.stop();
|
||||
PRIVATE->cond_var.notifyAll();
|
||||
#ifndef WINDOWS
|
||||
while (PRIVATE->thread.isRunning())
|
||||
piMSleep(1);
|
||||
#endif
|
||||
deleteAll();
|
||||
PRIVATE->thread.waitForFinish();
|
||||
for (PIObject * o : PRIVATE->obj_queue) deleteObject(o);
|
||||
//piCout << "~Deleter ok";
|
||||
}
|
||||
|
||||
@@ -727,46 +795,13 @@ PIObject::Deleter * PIObject::Deleter::instance() {
|
||||
void PIObject::Deleter::post(PIObject * o) {
|
||||
if (!o->isPIObject()) return;
|
||||
//piCout << "[Deleter] post" << o << "...";
|
||||
PRIVATE->queue_mutex.lock();
|
||||
if (!PRIVATE->obj_queue.contains(o))
|
||||
PRIVATE->thread.lock();
|
||||
if (!PRIVATE->obj_queue.contains(o)) {
|
||||
PRIVATE->obj_queue << o;
|
||||
PRIVATE->queue_mutex.unlock();
|
||||
PRIVATE->cond_var.notifyAll();
|
||||
posted = true;
|
||||
//piCout << "[Deleter] post" << o << "done";
|
||||
}
|
||||
|
||||
|
||||
void PIObject::Deleter::proc() {
|
||||
//piCout << "[Deleter] proc start";
|
||||
while (!stopping) {
|
||||
//piMSleep(1);
|
||||
//piCout << "[Deleter] proc wait ...";
|
||||
if (posted) {
|
||||
posted = false;
|
||||
started = true;
|
||||
} else {
|
||||
PRIVATE->cond_mutex.lock();
|
||||
started = true;
|
||||
PRIVATE->cond_var.wait(PRIVATE->cond_mutex);
|
||||
PRIVATE->cond_mutex.unlock();
|
||||
}
|
||||
//piCout << "[Deleter] proc wait done";
|
||||
deleteAll();
|
||||
PRIVATE->cond_var.notifyAll();
|
||||
}
|
||||
//piCout << "[Deleter] proc end ok";
|
||||
}
|
||||
|
||||
|
||||
void PIObject::Deleter::deleteAll() {
|
||||
PIVector<PIObject*> oq;
|
||||
PRIVATE->queue_mutex.lock();
|
||||
oq = PRIVATE->obj_queue;
|
||||
//piCout << "[Deleter] deleteAll" << oq.size_s() << "...";
|
||||
PRIVATE->obj_queue.clear();
|
||||
PRIVATE->queue_mutex.unlock();
|
||||
piForeach (PIObject * o, oq)
|
||||
deleteObject(o);
|
||||
PRIVATE->thread.unlock();
|
||||
//piCout << "[Deleter] post" << o << "done";
|
||||
}
|
||||
|
||||
|
||||
@@ -774,12 +809,9 @@ void PIObject::Deleter::deleteObject(PIObject * o) {
|
||||
//piCout << "[Deleter] delete" << (uintptr_t)o << "...";
|
||||
if (o->isPIObject()) {
|
||||
//piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic ...";
|
||||
while (o->isInEvent()) {
|
||||
piMSleep(1);
|
||||
}
|
||||
while (o->isInEvent()) piMinSleep();
|
||||
//piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic done";
|
||||
if (o->isPIObject())
|
||||
delete o;
|
||||
delete o;
|
||||
}
|
||||
//piCout << "[Deleter] delete" << (uintptr_t)o << "done";
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file piobject.h
|
||||
* @brief Base object
|
||||
*
|
||||
* This file declare PIObject class
|
||||
/*! \file piobject.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Base object
|
||||
* \~russian Базовый класс
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -37,28 +38,86 @@
|
||||
typedef void (*Handler)(void * );
|
||||
|
||||
class PIP_EXPORT PIObject {
|
||||
#ifndef MICRO_PIP
|
||||
friend class PIObjectManager;
|
||||
friend void dumpApplication();
|
||||
friend class PIIntrospection;
|
||||
#endif
|
||||
typedef PIObject __PIObject__;
|
||||
typedef void __Parent__;
|
||||
friend class PIIntrospection;
|
||||
public:
|
||||
NO_COPY_CLASS(PIObject)
|
||||
|
||||
//! Contructs PIObject with name "name"
|
||||
//! \~english Contructs %PIObject with name "name"
|
||||
//! \~russian Создает %PIObject с именем "name"
|
||||
explicit PIObject(const PIString & name = PIString());
|
||||
|
||||
virtual ~PIObject();
|
||||
|
||||
class PIP_EXPORT Connection {
|
||||
friend class PIObject;
|
||||
Connection(void * sl, void * si, const PIString & e = PIString(),
|
||||
PIObject * s_o = nullptr, PIObject * d_o = nullptr,
|
||||
void * d = nullptr, int ac = 0, PIObject * p = nullptr) {
|
||||
slot = sl;
|
||||
signal = si;
|
||||
event = e;
|
||||
eventID = e.hash();
|
||||
src_o = s_o;
|
||||
dest_o = d_o;
|
||||
dest = d;
|
||||
args_count = ac;
|
||||
performer = p;
|
||||
functor = 0;
|
||||
}
|
||||
void destroy();
|
||||
void * slot;
|
||||
void * signal;
|
||||
std::function<void()> * functor;
|
||||
PIString event;
|
||||
uint eventID;
|
||||
PIObject * src_o, * dest_o;
|
||||
PIObject * performer;
|
||||
void * dest;
|
||||
int args_count;
|
||||
public:
|
||||
|
||||
//! \~english Contructs invalid %Connection
|
||||
//! \~russian Создает недействительный %Connection
|
||||
Connection();
|
||||
|
||||
//! \~english Returns if %Connection is valid
|
||||
//! \~russian Возвращает успешен ли %Connection
|
||||
bool isValid() const {return signal;}
|
||||
|
||||
//! \~english Returns source object
|
||||
//! \~russian Возвращает объект-источник
|
||||
PIObject * sourceObject() const {return src_o;}
|
||||
|
||||
//! \~english Returns destination object or "nullptr" if this is lambda connection
|
||||
//! \~russian Возвращает объект-приемник или "nullptr" если это соединение на лямбда-функцию
|
||||
PIObject * destinationObject() const {return dest_o;}
|
||||
|
||||
//! \~english Returns performer object or "nullptr" if this is non-queued connection
|
||||
//! \~russian Возвращает объект-приемник или "nullptr" если это соединение не отложенное
|
||||
PIObject * performerObject() const {return performer;}
|
||||
|
||||
//! \~english Disconnect this %Connection, returns if operation successful
|
||||
//! \~russian Разрывает этот %Connection, возвращает успешен ли разрыв
|
||||
bool disconnect();
|
||||
};
|
||||
|
||||
private:
|
||||
uint _signature_;
|
||||
|
||||
public:
|
||||
|
||||
//! Returns object name
|
||||
//! \~english Returns object name
|
||||
//! \~russian Возвращает имя объекта
|
||||
PIString name() const {return property(PIStringAscii("name")).toString();}
|
||||
|
||||
//! Returns object class name
|
||||
//! \~english Returns object class name
|
||||
//! \~russian Возвращает имя класса объекта
|
||||
virtual const char * className() const {return "PIObject";}
|
||||
|
||||
virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
|
||||
@@ -66,36 +125,45 @@ public:
|
||||
static const PIString __classNameS() {return PIStringAscii("PIObject");}
|
||||
static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
|
||||
|
||||
//! Returns parent object class name
|
||||
//! \~english Returns parent class name
|
||||
//! \~russian Возвращает имя родительского класса
|
||||
virtual const char * parentClassName() const {return "";}
|
||||
|
||||
|
||||
//! Return if debug of this object is active
|
||||
//! \~english Return if debug of this object is active
|
||||
//! \~russian Возвращает включен ли вывод на консоль для этого объекта
|
||||
bool debug() const {return property(PIStringAscii("debug")).toBool();}
|
||||
|
||||
|
||||
//! Set object name
|
||||
//! \~english Set object name
|
||||
//! \~russian Устанавливает имя объекта
|
||||
void setName(const PIString & name) {setProperty(PIStringAscii("name"), name);}
|
||||
void setName(const char * name) {setName(PIStringAscii(name));}
|
||||
|
||||
//! Set object debug active
|
||||
//! \~english Set object debug active
|
||||
//! \~russian Включает или отключает вывод на консоль для этого объекта
|
||||
void setDebug(bool debug) {setProperty(PIStringAscii("debug"), debug);}
|
||||
|
||||
//! Returns properties of the object
|
||||
PIMap<PIString, PIVariant> properties() const;
|
||||
//! \~english Returns properties of the object
|
||||
//! \~russian Возвращает словарь свойств объекта
|
||||
PIMap<PIString, PIVariant> properties() const;
|
||||
|
||||
//! Returns properties count of the object
|
||||
//! \~english Returns properties count of the object
|
||||
//! \~russian Возвращает количество свойств объекта
|
||||
int propertiesCount() const {return properties_.size_s();}
|
||||
|
||||
//! Returns property with name "name"
|
||||
//! \~english Returns property with name "name"
|
||||
//! \~russian Возвращает свойство объекта по имени "name"
|
||||
PIVariant property(const PIString & name) const {return properties_.value(name.hash(), Property(PIString(), PIVariant())).second;}
|
||||
PIVariant property(const char * name) const {return property(PIStringAscii(name));}
|
||||
|
||||
//! Set property with name "name" to "value". If there is no such property in object it will be added
|
||||
//! \~english Set property with name "name" to "value". If there is no such property in object it will be added
|
||||
//! \~russian Устанавливает у объекта свойство по имени "name" в "value". Если такого свойства нет, оно добавляется
|
||||
void setProperty(const PIString & name, const PIVariant & value) {properties_[name.hash()] = Property(name, value); propertyChanged(name);}
|
||||
void setProperty(const char * name, const PIVariant & value) {setProperty(PIStringAscii(name), value);}
|
||||
|
||||
//! Returns if property with name "name" exists
|
||||
//! \~english Returns if property with name "name" exists
|
||||
//! \~russian Возвращает присутствует ли свойство по имени "name"
|
||||
bool isPropertyExists(const PIString & name) const {return properties_.contains(name.hash());}
|
||||
bool isPropertyExists(const char * name) const {return isPropertyExists(PIStringAscii(name));}
|
||||
|
||||
@@ -133,7 +201,10 @@ public:
|
||||
void dump(const PIString & line_prefix = PIString()) const;
|
||||
|
||||
|
||||
//! \~english Returns subclass scope of this object (including this class name)
|
||||
//! \~russian Возвращает цепочку наследования объекта (вместе с классом самого объекта)
|
||||
PIStringList scopeList() const;
|
||||
|
||||
PIStringList methodsEH() const;
|
||||
bool isMethodEHContains(const PIString & name) const;
|
||||
PIString methodEHArguments(const PIString & name) const;
|
||||
@@ -141,33 +212,44 @@ public:
|
||||
PIString methodEHFromAddr(const void * addr) const;
|
||||
|
||||
// / Direct connect
|
||||
static void piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
|
||||
static bool piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
|
||||
static bool piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc);
|
||||
template <typename INPUT, typename... TYPES>
|
||||
static std::function<void()> * __newFunctor(void(*stat_handler)(void*,TYPES...), INPUT functor) {
|
||||
return (std::function<void()>*)(new std::function<void(TYPES...)>(functor));
|
||||
static PIObject::Connection piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
|
||||
static PIObject::Connection piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
|
||||
static PIObject::Connection piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc);
|
||||
template <typename PIINPUT, typename... PITYPES>
|
||||
static std::function<void()> * __newFunctor(void(*stat_handler)(void*,PITYPES...), PIINPUT functor) {
|
||||
return (std::function<void()>*)(new std::function<void(PITYPES...)>(functor));
|
||||
}
|
||||
|
||||
// / Through names and mixed
|
||||
static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h);
|
||||
static void piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h);
|
||||
static void piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h);
|
||||
|
||||
|
||||
//! \~english Disconnect object from all connections with event name "sig", connected to destination object "dest" and handler "ev_h"
|
||||
//! \~russian Разрывает все соединения от события "sig" к объекту "dest" и обработчику "ev_h"
|
||||
void piDisconnect(const PIString & sig, PIObject * dest, void * ev_h) {piDisconnect(this, sig, dest, ev_h);}
|
||||
|
||||
//! \~english Disconnect object from all connections with event name "sig", connected to destination object "dest"
|
||||
//! \~russian Разрывает все соединения от события "sig" к объекту "dest"
|
||||
void piDisconnect(const PIString & sig, PIObject * dest) {piDisconnect(this, sig, dest);}
|
||||
|
||||
//! \~english Disconnect object from all connections with event name "sig"
|
||||
//! \~russian Разрывает все соединения от события "sig"
|
||||
void piDisconnect(const PIString & sig) {piDisconnect(this, sig);}
|
||||
|
||||
|
||||
//! \~english Disconnect object "src" from all connections with event name "sig", connected to destination object "dest" and handler "ev_h"
|
||||
//! \~russian Разрывает все соединения от события "sig" объекта "src" к объекту "dest" и обработчику "ev_h"
|
||||
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h);
|
||||
|
||||
//! \~english Disconnect object "src" from all connections with event name "sig", connected to destination object "dest"
|
||||
//! \~russian Разрывает все соединения от события "sig" объекта "src" к объекту "dest"
|
||||
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest);
|
||||
|
||||
//! Disconnect object "src" from all connections with event name "sig"
|
||||
//! \~english Disconnect object "src" from all connections with event name "sig"
|
||||
//! \~russian Разрывает все соединения от события "sig" объекта "src"
|
||||
static void piDisconnect(PIObject * src, const PIString & sig);
|
||||
|
||||
//! Disconnect object "src" from all connections, i.e. all connections where object "src" is emitter
|
||||
static void piDisconnect(PIObject * src);
|
||||
|
||||
|
||||
// / Raise events
|
||||
static void raiseEvent(PIObject * sender, const uint eventID) {
|
||||
for (int j = 0; j < sender->connections.size_s(); ++j) {
|
||||
__Connection i(sender->connections[j]);
|
||||
Connection i(sender->connections[j]);
|
||||
if (i.eventID != eventID) continue;
|
||||
if (i.functor) {
|
||||
(*(i.functor))();
|
||||
@@ -196,7 +278,7 @@ public:
|
||||
template <typename T0>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) {
|
||||
for (int j = 0; j < sender->connections.size_s(); ++j) {
|
||||
__Connection i(sender->connections[j]);
|
||||
Connection i(sender->connections[j]);
|
||||
if (i.eventID != eventID) continue;
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0)>*)i.functor))(v0);
|
||||
@@ -227,7 +309,7 @@ public:
|
||||
template <typename T0, typename T1>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1()) {
|
||||
for (int j = 0; j < sender->connections.size_s(); ++j) {
|
||||
__Connection i(sender->connections[j]);
|
||||
Connection i(sender->connections[j]);
|
||||
if (i.eventID != eventID) continue;
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0, T1)>*)i.functor))(v0, v1);
|
||||
@@ -262,7 +344,7 @@ public:
|
||||
template <typename T0, typename T1, typename T2>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
|
||||
for (int j = 0; j < sender->connections.size_s(); ++j) {
|
||||
__Connection i(sender->connections[j]);
|
||||
Connection i(sender->connections[j]);
|
||||
if (i.eventID != eventID) continue;
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0, T1, T2)>*)i.functor))(v0, v1, v2);
|
||||
@@ -299,7 +381,7 @@ public:
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) {
|
||||
for (int j = 0; j < sender->connections.size_s(); ++j) {
|
||||
__Connection i(sender->connections[j]);
|
||||
Connection i(sender->connections[j]);
|
||||
if (i.eventID != eventID) continue;
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0, T1, T2, T3)>*)i.functor))(v0, v1, v2, v3);
|
||||
@@ -343,23 +425,36 @@ public:
|
||||
if (i->name() != name) continue;
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//! \~english Returns if this is valid %PIObject (check signature)
|
||||
//! \~russian Возвращает действительный ли это %PIObject (проверяет подпись)
|
||||
bool isPIObject() const {return isPIObject(this);}
|
||||
|
||||
//! \~english Returns if this is valid %PIObject subclass "T" (check signature and classname)
|
||||
//! \~russian Возвращает действительный ли это наследник %PIObject типа "T" (проверяет подпись и имя класса)
|
||||
template<typename T>
|
||||
bool isTypeOf() const {
|
||||
if (!isPIObject()) return false;
|
||||
return scopeList().contains(T::__classNameS());
|
||||
}
|
||||
|
||||
//! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr"
|
||||
//! \~russian Возвращает преобразование к типу T если это действительный наследник типа "T" (проверяет через \a isTypeOf()), или "nullptr"
|
||||
template<typename T>
|
||||
T * cast() const {
|
||||
if (!isTypeOf<T>()) return (T*)0;
|
||||
if (!isTypeOf<T>()) return (T*)nullptr;
|
||||
return (T*)this;
|
||||
}
|
||||
|
||||
//! \~english Returns if "o" is valid %PIObject (check signature)
|
||||
//! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись)
|
||||
static bool isPIObject(const PIObject * o);
|
||||
static bool isPIObject(const void * o) {return isPIObject((PIObject*)o);}
|
||||
|
||||
//! \~english Returns if "o" is valid %PIObject subclass "T" (check signature and classname)
|
||||
//! \~russian Возвращает действительный ли "o" наследник %PIObject типа "T" (проверяет подпись и имя класса)
|
||||
template<typename T>
|
||||
static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();}
|
||||
template<typename T>
|
||||
@@ -390,17 +485,22 @@ public:
|
||||
};
|
||||
typedef PIPair<const void * , __MetaFunc> __EHPair;
|
||||
|
||||
//! @brief Execute all posted events from CONNECTU_QUEUED connections
|
||||
//! \~english Execute all posted events from CONNECTU_QUEUED connections
|
||||
//! \~russian Выполнить все отложенные события от CONNECTU_QUEUED соединений
|
||||
void callQueuedEvents();
|
||||
|
||||
//! @brief Check if any CONNECTU_QUEUED connections to this object and execute them
|
||||
//! \~english
|
||||
//! \brief Check if any CONNECTU_QUEUED connections to this object and execute them
|
||||
//! \details This function is more optimized than \a callQueuedEvents() for objects that doesn`t
|
||||
//! appears as \"performer\" target at CONNECTU_QUEUED
|
||||
//! \~russian
|
||||
//! \brief Если было хотя бы одно CONNECTU_QUEUED соединение с исполнителем this, то выполнить события
|
||||
//! \details Этот метод более оптимален, чем \a callQueuedEvents(), для объектов, которые не были в роли
|
||||
//! \"performer\" в макросе CONNECTU_QUEUED
|
||||
bool maybeCallQueuedEvents() {if (proc_event_queue) callQueuedEvents(); return proc_event_queue;}
|
||||
|
||||
//! @brief Mark object to delete
|
||||
//! \details On first call background thread started to delete objects.
|
||||
//! Each object deletes when it`s outside from any events and hadlers.
|
||||
//! \~english Mark object to delete
|
||||
//! \~russian Пометить объект на удаление
|
||||
void deleteLater();
|
||||
|
||||
static PIMutex & __meta_mutex();
|
||||
@@ -408,10 +508,12 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
//! Returns PIObject* which has raised an event. This value is correct only in definition of some event handler
|
||||
//! \~english Returns %PIObject* which has raised an event. This value is correct only in definition of some event handler
|
||||
//! \~russian Возвращает %PIObject* который вызвал это событие. Значение допустимо только из методов обработчиков событий
|
||||
PIObject * emitter() const {return emitter_;}
|
||||
|
||||
//! Virtual function executes after property with name "name" has been changed
|
||||
//! \~english Virtual function executes after property with name "name" has been changed
|
||||
//! \~russian Виртуальная функция, вызывается после изменения любого свойства.
|
||||
virtual void propertyChanged(const PIString & name) {}
|
||||
|
||||
EVENT1(deleted, PIObject *, o)
|
||||
@@ -419,39 +521,22 @@ protected:
|
||||
//! \events
|
||||
//! \{
|
||||
|
||||
/** \fn void deleted(PIObject * o)
|
||||
* @brief Raise before object delete
|
||||
* \note This event raised from destructor, so use only "o" value,
|
||||
* don`t try to cast deleted object to some subclass! */
|
||||
//! \fn void deleted(PIObject * o)
|
||||
//! \brief
|
||||
//! \~english Raise before object delete
|
||||
//! \~russian Вызывается перед удалением объекта
|
||||
//! \~\warning
|
||||
//! \~english
|
||||
//! This event raised from destructor, so use only "o" numeric value,
|
||||
//! don`t try to cast deleted object to some subclass!
|
||||
//! \~russian
|
||||
//! Это событие вызывается из деструктора, поэтому используйте
|
||||
//! только численное значение "o", не надо кастовать его в другие типы!
|
||||
|
||||
//! \}
|
||||
|
||||
private:
|
||||
|
||||
struct __Connection {
|
||||
__Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), PIObject * d_o = 0, void * d = 0, int ac = 0, PIObject * p = 0) {
|
||||
slot = sl;
|
||||
signal = si;
|
||||
event = e;
|
||||
eventID = e.hash();
|
||||
dest_o = d_o;
|
||||
dest = d;
|
||||
args_count = ac;
|
||||
performer = p;
|
||||
functor = 0;
|
||||
}
|
||||
void destroy();
|
||||
void * slot;
|
||||
void * signal;
|
||||
std::function<void()> * functor;
|
||||
PIString event;
|
||||
uint eventID;
|
||||
PIObject * dest_o;
|
||||
PIObject * performer;
|
||||
void * dest;
|
||||
int args_count;
|
||||
};
|
||||
|
||||
struct __QueuedEvent {
|
||||
__QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariantSimple> & v = PIVector<PIVariantSimple>()) {
|
||||
slot = sl;
|
||||
@@ -474,10 +559,7 @@ private:
|
||||
static Deleter * instance();
|
||||
void post(PIObject * o);
|
||||
private:
|
||||
void proc();
|
||||
void deleteAll();
|
||||
void deleteObject(PIObject * o);
|
||||
std::atomic_bool stopping, started, posted;
|
||||
PRIVATE_DECLARATION(PIP_EXPORT)
|
||||
};
|
||||
|
||||
@@ -488,6 +570,8 @@ private:
|
||||
PIVector<__MetaFunc> findEH(const PIString & name) const;
|
||||
__MetaFunc methodEH(const void * addr) const;
|
||||
void updateConnectors();
|
||||
void piDisconnectAll();
|
||||
|
||||
void postQueuedEvent(const __QueuedEvent & e);
|
||||
void eventBegin() {in_event_cnt++;}
|
||||
void eventEnd () {in_event_cnt--;}
|
||||
@@ -500,7 +584,7 @@ private:
|
||||
static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariantSimple> & vl);
|
||||
|
||||
|
||||
PIVector<__Connection> connections;
|
||||
PIVector<Connection> connections;
|
||||
PIMap<uint, PIPair<PIString, PIVariant> > properties_;
|
||||
PISet<PIObject * > connectors;
|
||||
PIVector<__QueuedEvent> events_queue;
|
||||
@@ -511,8 +595,9 @@ private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
PIP_EXPORT void dumpApplication();
|
||||
PIP_EXPORT bool dumpApplicationToFile(const PIString & path);
|
||||
#endif
|
||||
|
||||
#endif // PIOBJECT_H
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file piobject_macros.h
|
||||
* @brief Base object
|
||||
*
|
||||
* This file declare macros for PIObject
|
||||
/*! \file piobject_macros.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english PIObject macros
|
||||
* \~russian Макросы PIObject
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -29,67 +30,127 @@
|
||||
#ifdef DOXYGEN
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english You should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output
|
||||
//! \~russian Необходимо использовать этот макрос после объявления класса для использования событийной системы и корректного вывода piCoutObj
|
||||
#define PIOBJECT(name)
|
||||
|
||||
/// \relatesalso PIObject @brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER of parent class, and \a scopeList()
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english You should use this macro after class declaration to use EVENT and EVENT_HANDLER of parent class, and \a scopeList()
|
||||
//! \~russian
|
||||
#define PIOBJECT_SUBCLASS(name, parent)
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name()
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name()
|
||||
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name()
|
||||
#define EVENT_HANDLER0(ret, name) ret name()
|
||||
|
||||
/// \relatesalso PIObject @brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0)
|
||||
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0)
|
||||
#define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0)
|
||||
|
||||
/// \relatesalso PIObject @brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1)
|
||||
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1)
|
||||
#define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1)
|
||||
|
||||
/// \relatesalso PIObject @brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2)
|
||||
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1, type2 var2)
|
||||
#define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)
|
||||
|
||||
/// \relatesalso PIObject @brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event handler with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
//! \~russian Объявляет обработчик событий с именем \"name\" и возвращаемым типом \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
#define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
|
||||
/// \relatesalso PIObject @brief EVENT_HANDLER is synonym of EVENT_HANDLER0
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Synonym of EVENT_HANDLER0
|
||||
//! \~russian Аналог EVENT_HANDLER0
|
||||
#define EVENT_HANDLER EVENT_HANDLER0
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name()
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name()
|
||||
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name()
|
||||
#define EVENT_VHANDLER0(ret, name) virtual ret name()
|
||||
|
||||
/// \relatesalso PIObject @brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0)
|
||||
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0)
|
||||
#define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0)
|
||||
|
||||
/// \relatesalso PIObject @brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1)
|
||||
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1 var1)
|
||||
#define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1)
|
||||
|
||||
/// \relatesalso PIObject @brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
|
||||
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
|
||||
#define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)
|
||||
|
||||
/// \relatesalso PIObject @brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare virtual event handler with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
//! \~russian Объявляет виртуальный обработчик событий с именем \"name\" и возвращаемым типом \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
#define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
|
||||
|
||||
/// \relatesalso PIObject @brief EVENT_VHANDLER is synonym of EVENT_VHANDLER0
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Synonym of EVENT_VHANDLER0
|
||||
//! \~russian Аналог EVENT_VHANDLER0
|
||||
#define EVENT_VHANDLER EVENT_VHANDLER0
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief declare event \"event\" with name \"name\", void name();
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event with name \"name\", void name();
|
||||
//! \~russian Объявляет событие с именем \"name\", void name();
|
||||
#define EVENT0(name) void name();
|
||||
|
||||
/// \relatesalso PIObject @brief declare event \"event\" with name \"name\", void name(type0 var0);
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event with name \"name\", void name(type0 var0);
|
||||
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0);
|
||||
#define EVENT1(name, type0, var0) void name(type0 var0);
|
||||
|
||||
/// \relatesalso PIObject @brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1);
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event with name \"name\", void name(type0 var0, type1 var1);
|
||||
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1);
|
||||
#define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1);
|
||||
|
||||
/// \relatesalso PIObject @brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2);
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event with name \"name\", void name(type0 var0, type1 var1, type2 var2);
|
||||
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1, type2 var2);
|
||||
#define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2);
|
||||
|
||||
/// \relatesalso PIObject @brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Declare event with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
|
||||
//! \~russian Объявляет событие с именем \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
|
||||
#define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);
|
||||
|
||||
/// \relatesalso PIObject @brief EVENT is synonym of EVENT0
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Synonym of EVENT0
|
||||
//! \~russian Аналог EVENT0
|
||||
#define EVENT EVENT0
|
||||
|
||||
|
||||
@@ -101,81 +162,217 @@
|
||||
#define RAISE_EVENT RAISE_EVENT0
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\". \"Event\" and \"handler\" must has equal argument lists.
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler or event \"handler\" of object \"dest\".
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\".
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! \"handler\" can handle subset arguments of \"event\".
|
||||
//! Returns \a PIObject::Connection
|
||||
//! \~russian
|
||||
//! \"handler\" может принимать не все аргументы от \"event\".
|
||||
//! Возвращает \a PIObject::Connection
|
||||
#define CONNECTU(src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\".
|
||||
/// Event handler will be executed by \"performer\". \"Event\" and \"handler\" must has equal argument lists.
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler or event \"handler\" of object \"dest\".
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" объекта \"dest\".
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! \"handler\" can handle subset arguments of \"event\".
|
||||
//! Event handler will be executed by \"performer\" when \a PIObject::callQueuedEvents() called.
|
||||
//! All argument types should be registered by \a REGISTER_VARIANT() macro, but many
|
||||
//! common and PIP types already done.
|
||||
//! Returns \a PIObject::Connection
|
||||
//! \~russian
|
||||
//! \"handler\" может принимать не все аргументы от \"event\".
|
||||
//! Обработчик будет вызван объектом \"performer\" при вызове \a PIObject::callQueuedEvents().
|
||||
//! Все типы аргументов должны быть зарегистрированы с помощью макроса \a REGISTER_VARIANT(),
|
||||
//! однако многие стандартные и PIP типы уже там.
|
||||
//! Возвращает \a PIObject::Connection
|
||||
#define CONNECTU_QUEUED(src, event, dest, handler, performer)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to lambda-expression \"functor\". \"Event\" and \"functor\" must has equal argument lists.
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to lambda-expression \"functor\".
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к лямбда-функции \"functor\".
|
||||
//! \~\details
|
||||
//! \~english
|
||||
//! \"event\" and \"functor\" must has equal argument lists.
|
||||
//! You should parentness \"functor\" with () if this is complex lambda.
|
||||
//! Returns \a PIObject::Connection
|
||||
//! \~russian
|
||||
//! \"event\" и \"functor\" должны иметь одинаковые аргументы.
|
||||
//! В случае сложной лямбда-функции оберните её ().
|
||||
//! Возвращает \a PIObject::Connection
|
||||
#define CONNECTL(src, event, functor)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
|
||||
//! \~\details
|
||||
//! Returns PIObject::Connection
|
||||
#define CONNECT0(ret, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
|
||||
//! \~\details
|
||||
//! Returns PIObject::Connection
|
||||
#define CONNECT1(ret, type0, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
|
||||
//! \~\details
|
||||
//! Returns PIObject::Connection
|
||||
#define CONNECT2(ret, type0, type1, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
|
||||
//! \~\details
|
||||
//! Returns PIObject::Connection
|
||||
#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists.
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" с проверкой наличия события и обработчика.
|
||||
//! \~\details
|
||||
//! Returns PIObject::Connection
|
||||
#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief CONNECT is synonym of CONNECT0
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Synonym of \a CONNECT0
|
||||
//! \~russian Аналог \a CONNECT0
|
||||
#define CONNECT CONNECT0
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
|
||||
#define WEAK_CONNECT0(ret, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
|
||||
#define WEAK_CONNECT1(ret, type0, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
|
||||
#define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
|
||||
#define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
|
||||
//! \~russian Соединяет событие \"event\" объекта \"src\" к обработчику или событию \"handler\" с возвращаемым типом \"ret\" объекта \"dest\" без проверки наличия события и обработчика.
|
||||
#define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief WEAK_CONNECT is synonym of WEAK_CONNECT0
|
||||
//! \relatesalso PIObject
|
||||
//! \deprecated
|
||||
//! \~english Use \a CONNECTU() instead
|
||||
//! \~russian Используйте \a CONNECTU()
|
||||
//! \~\brief
|
||||
//! \~english Synonym of \a WEAK_CONNECT0
|
||||
//! \~russian Аналог \a WEAK_CONNECT0
|
||||
#define WEAK_CONNECT WEAK_CONNECT0
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
|
||||
#define DISCONNECT0(ret, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
|
||||
#define DISCONNECT1(ret, type0, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
|
||||
#define DISCONNECT2(ret, type0, type1, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
|
||||
#define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
|
||||
//! \~russian piDisconnect событие \"event\" объекта \"src\" от обработчика или события \"handler\" с возвращаемым типом \"ret\" объекта \"dest\"
|
||||
#define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
|
||||
|
||||
/// \relatesalso PIObject @brief DISCONNECT is synonym of DISCONNECT0
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Synonym of \a DISCONNECT0
|
||||
//! \~russian Аналог \a DISCONNECT0
|
||||
#define DISCONNECT DISCONNECT0
|
||||
|
||||
|
||||
/// \relatesalso PIObject @brief Returns pointer to events handler \"handler\"
|
||||
//! \relatesalso PIObject
|
||||
//! \~\brief
|
||||
//! \~english Returns pointer to events handler \"handler\"
|
||||
//! \~russian Возвращает указатель на обработчик события \"handler\"
|
||||
#define HANDLER(handler)
|
||||
|
||||
|
||||
#define PIOBJECT(name)
|
||||
#define PIOBJECT_SUBCLASS(name)
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,62 @@
|
||||
#include "pipropertystorage.h"
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PIPropertyStorage pipropertystorage.h
|
||||
//! \~\brief
|
||||
//! \~english This class provides key-value properties storage
|
||||
//! \~russian Этот класс предоставляет ключ-значение хранение свойств
|
||||
//!
|
||||
//! \~\details
|
||||
//! \~english \section PIPropertyStorage_sec0 Synopsis
|
||||
//! \~russian \section PIPropertyStorage_sec0 Краткий обзор
|
||||
//!
|
||||
//! \~english
|
||||
//! Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector
|
||||
//! contains unique name. You can access property by name with \a propertyValueByName() or \a propertyByName().
|
||||
//! You can add or replace property by \a addProperty(const Property&) or \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
|
||||
//!
|
||||
//! \~russian
|
||||
//! Хранилище свойств ключ-значние, основанный на PIVector с элементами PIPropertyStorage::Property.
|
||||
//! Каждый элемент имеет уникальное имя. Доступ к свойствам через \a propertyValueByName() или \a propertyByName().
|
||||
//! Добавление и перезапись свойств через \a addProperty(const Property&) или \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
|
||||
//!
|
||||
//! \~english Example:
|
||||
//! \~russian Пример:
|
||||
//! \~\code{.cpp}
|
||||
//! \endcode
|
||||
//! \}
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PIPropertyStorage::Property pipropertystorage.h
|
||||
//! \~\brief
|
||||
//! \~english PIPropertyStorage element
|
||||
//! \~russian Элемент PIPropertyStorage
|
||||
//!
|
||||
//! \~\details
|
||||
//! \~english \section PIPropertyStorage_sec0 Synopsis
|
||||
//! \~russian \section PIPropertyStorage_sec0 Краткий обзор
|
||||
//!
|
||||
//! \~english
|
||||
//! Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector
|
||||
//! contains unique name. You can access property by name with \a propertyValueByName() or \a propertyByName().
|
||||
//! You can add or replace property by \a addProperty(const Property&) or \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
|
||||
//!
|
||||
//! \~russian
|
||||
//! Хранилище свойств ключ-значние, основанный на PIVector с элементами PIPropertyStorage::Property.
|
||||
//! Каждый элемент имеет уникальное имя. Доступ к свойствам через \a propertyValueByName() или \a propertyByName().
|
||||
//! Добавление и перезапись свойств через \a addProperty(const Property&) или \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
|
||||
//!
|
||||
//! \~english Example:
|
||||
//! \~russian Пример:
|
||||
//! \~\code{.cpp}
|
||||
//! \endcode
|
||||
//! \}
|
||||
|
||||
|
||||
bool PIPropertyStorage::isPropertyExists(const PIString & _name) const {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
if (props[i].name == _name)
|
||||
@@ -28,6 +84,9 @@ bool PIPropertyStorage::isPropertyExists(const PIString & _name) const {
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english Returns "true" if new property added, else if update existing property return "false"
|
||||
//! \~russian Возвращает истину если новое свойство добавлено, в случае обновления "ложь"
|
||||
bool PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) {
|
||||
for (uint i = 0; i < props.size(); ++i)
|
||||
if (props[i].name == p.name) {
|
||||
@@ -50,6 +109,9 @@ bool PIPropertyStorage::addProperty(PIPropertyStorage::Property && p) {
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english Returns "true" if new property added, else if update existing property return "false"
|
||||
//! \~russian Возвращает истину если новое свойство добавлено, в случае обновления "ложь"
|
||||
bool PIPropertyStorage::addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment, int _flags) {
|
||||
return addProperty(Property(_name, _comment, _def_value, _flags));
|
||||
}
|
||||
@@ -66,6 +128,9 @@ bool PIPropertyStorage::removeProperty(const PIString & _name) {
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english "flag" checked as bitfield
|
||||
//! \~russian "flag" проверяется как битовое поле
|
||||
int PIPropertyStorage::removePropertiesByFlag(int flag) {
|
||||
int ret = 0;
|
||||
for (int i = 0; i < props.size_s(); ++i) {
|
||||
@@ -79,6 +144,9 @@ int PIPropertyStorage::removePropertiesByFlag(int flag) {
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english "flag_ignore" is bitfield to ignore property in merge process
|
||||
//! \~russian "flag_ignore" - битовое поле для исключения свойств из процесса слияния
|
||||
void PIPropertyStorage::updateProperties(const PIVector<PIPropertyStorage::Property> & properties_, int flag_ignore) {
|
||||
PIMap<PIString, PIVariant> values;
|
||||
piForeachC(Property & p, props)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/*! @file pipropertystorage.h
|
||||
* @brief Storage of properties for GUI usage
|
||||
*
|
||||
* This file declare PIPropertyStorage
|
||||
*/
|
||||
/*! \file pipropertystorage.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Properties array
|
||||
* \~russian Массив свойств
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Storage of properties for GUI usage
|
||||
@@ -27,25 +28,28 @@
|
||||
|
||||
#include "pivariant.h"
|
||||
|
||||
/**
|
||||
* @brief Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector
|
||||
* contains unique name and you can identify property by name with propertyValueByName(), propertyByName().
|
||||
* You can add property using addProperty(const Property&), addProperty(const PIString&, const PIVariant&, const PIString&, int).
|
||||
*/
|
||||
|
||||
class PIP_EXPORT PIPropertyStorage {
|
||||
public:
|
||||
|
||||
//! \~english Contructs an empty %PIPropertyStorage
|
||||
//! \~russian Создает пустой %PIPropertyStorage
|
||||
PIPropertyStorage() {}
|
||||
|
||||
/**
|
||||
* @brief PIPropertyStorage element.
|
||||
*/
|
||||
struct PIP_EXPORT Property {
|
||||
Property(const PIString & n = PIString(), const PIString & c = PIString(), const PIVariant & v = PIVariant(), int f = 0):
|
||||
name(n), comment(c), value(v), flags(f) {}
|
||||
Property(const Property & o):
|
||||
name(o.name), comment(o.comment), value(o.value), flags(o.flags) {}
|
||||
|
||||
//! \~english Contructs %PIPropertyStorage::Property with name "n", comment "c", value "v" and flags "f"
|
||||
//! \~russian Создает %PIPropertyStorage::Property с именем "n", комментарием "c", значением "v" и флагами "f"
|
||||
Property(const PIString & n = PIString(), const PIString & c = PIString(), const PIVariant & v = PIVariant(), int f = 0): name(n), comment(c), value(v), flags(f) {}
|
||||
|
||||
//! \~english Contructs copy of another %PIPropertyStorage::Property "o"
|
||||
//! \~russian Создает копию %PIPropertyStorage::Property "o"
|
||||
Property(const Property & o): name(o.name), comment(o.comment), value(o.value), flags(o.flags) {}
|
||||
|
||||
Property(Property && o) {swap(o);}
|
||||
|
||||
//! \~english Assign operator
|
||||
//! \~russian Оператор присваивания
|
||||
Property & operator =(const Property & v) {
|
||||
name = v.name;
|
||||
comment = v.comment;
|
||||
@@ -56,10 +60,24 @@ public:
|
||||
Property & operator =(Property && v) {swap(v); return *this;}
|
||||
|
||||
|
||||
//! \~english Returns value as boolean
|
||||
//! \~russian Возвращает значение как логическое
|
||||
bool toBool() const {return value.toBool();}
|
||||
|
||||
//! \~english Returns value as integer
|
||||
//! \~russian Возвращает значение как целое
|
||||
int toInt() const {return value.toInt();}
|
||||
|
||||
//! \~english Returns value as float
|
||||
//! \~russian Возвращает значение как float
|
||||
float toFloat() const {return value.toFloat();}
|
||||
|
||||
//! \~english Returns value as double
|
||||
//! \~russian Возвращает значение как double
|
||||
double toDouble() const {return value.toDouble();}
|
||||
|
||||
//! \~english Returns value as string
|
||||
//! \~russian Возвращает значение как строку
|
||||
PIString toString() const {return value.toString();}
|
||||
|
||||
void swap(Property & o) {
|
||||
@@ -69,22 +87,30 @@ public:
|
||||
piSwap(flags, o.flags);
|
||||
}
|
||||
|
||||
/*! Uniqueue id of property */
|
||||
//! \~english Property name (uniqueue for %PIPropertyStorage)
|
||||
//! \~russian Имя свойства (уникальное для %PIPropertyStorage)
|
||||
PIString name;
|
||||
|
||||
/*! Optional description of property */
|
||||
//! \~english Optional description of property
|
||||
//! \~russian Опциональный комментарий свойства
|
||||
PIString comment;
|
||||
|
||||
/*! Custom value of property */
|
||||
//! \~english Property value
|
||||
//! \~russian Значение свойства
|
||||
PIVariant value;
|
||||
|
||||
/*! Abstract flags which may be used for user needs */
|
||||
//! \~english Abstract flags which may be used for user needs
|
||||
//! \~russian Абстрактные флаги, могут быть использованы для своих нужд
|
||||
int flags;
|
||||
};
|
||||
|
||||
//! \~english Contructs %PIPropertyStorage with "pl" properties
|
||||
//! \~russian Создает %PIPropertyStorage со свойствами "pl"
|
||||
PIPropertyStorage(const PIVector<Property> & pl) {props = pl;}
|
||||
|
||||
PIPropertyStorage(PIVector<Property> && pl): props(std::move(pl)) {}
|
||||
//! \~english Contructs %PIPropertyStorage from another "o"
|
||||
//! \~russian Создает %PIPropertyStorage из другого "o"
|
||||
PIPropertyStorage(PIVector<Property> && o): props(std::move(o)) {}
|
||||
|
||||
typedef PIVector<Property>::const_iterator const_iterator;
|
||||
typedef PIVector<Property>::iterator iterator;
|
||||
@@ -95,115 +121,140 @@ public:
|
||||
iterator end() {return props.end();}
|
||||
const_iterator end() const {return props.end();}
|
||||
|
||||
//! \~english Returns properties count
|
||||
//! \~russian Возвращает количество свойств
|
||||
int length() const {return props.length();}
|
||||
|
||||
//! \~english Returns properties count
|
||||
//! \~russian Возвращает количество свойств
|
||||
int size() const {return props.size();}
|
||||
|
||||
//! \~english Returns if no properties
|
||||
//! \~russian Возвращает нет ли свойств
|
||||
bool isEmpty() const {return props.isEmpty();}
|
||||
|
||||
//! \~english Returns if properties
|
||||
//! \~russian Возвращает есть ли свойства
|
||||
bool isNotEmpty() const {return props.isNotEmpty();}
|
||||
|
||||
//! \~english Returns first property
|
||||
//! \~russian Возвращает первое свойство
|
||||
Property & front() {return props.front();}
|
||||
|
||||
//! \~english Returns first property as const
|
||||
//! \~russian Возвращает первое свойство как константу
|
||||
const Property & front() const {return props.front();}
|
||||
|
||||
//! \~english Returns last property
|
||||
//! \~russian Возвращает последнее свойство
|
||||
Property & back() {return props.back();}
|
||||
|
||||
//! \~english Returns last property as const
|
||||
//! \~russian Возвращает последнее свойство как константу
|
||||
const Property & back() const {return props.back();}
|
||||
|
||||
//! \~english Remove property at index "i"
|
||||
//! \~russian Удаляет свойство по индексу "i"
|
||||
void removeAt(int i) {props.remove(i);}
|
||||
|
||||
//! \~english Remove all properties
|
||||
//! \~russian Удаляет все свойства
|
||||
void clear() {props.clear();}
|
||||
|
||||
|
||||
//! \~english Returns copy of this %PIPropertyStorage
|
||||
//! \~russian Возвращает копию этого %PIPropertyStorage
|
||||
PIPropertyStorage copy() const {return PIPropertyStorage(*this);}
|
||||
|
||||
//! \~english Returns properties count
|
||||
//! \~russian Возвращает количество свойств
|
||||
int propertiesCount() const {return props.size();}
|
||||
|
||||
//! \~english Returns properties as PIVector
|
||||
//! \~russian Возвращает свойства как PIVector
|
||||
PIVector<Property> & properties() {return props;}
|
||||
|
||||
//! \~english Returns properties as const PIVector
|
||||
//! \~russian Возвращает свойства как константный PIVector
|
||||
const PIVector<Property> & properties() const {return props;}
|
||||
|
||||
const PIPropertyStorage & propertyStorage() const {return *this;}
|
||||
|
||||
/**
|
||||
* @brief Check if property with \a name exists
|
||||
* @return "true" if property exists
|
||||
*/
|
||||
bool isPropertyExists(const PIString & _name) const;
|
||||
//! \~english Returns if properties with name "name" exists
|
||||
//! \~russian Возвращает присутствует ли свойство с именем "name"
|
||||
bool isPropertyExists(const PIString & name) const;
|
||||
|
||||
/**
|
||||
* @brief Remove all properties
|
||||
*/
|
||||
//! \~english Remove all properties
|
||||
//! \~russian Удаляет все свойства
|
||||
void clearProperties() {props.clear();}
|
||||
|
||||
/**
|
||||
* @brief Add property if name isn't present in storage, otherwrise update existing property with same name.
|
||||
* @return "true" if new property added, else if update existing property return "false"
|
||||
* @param p to copy in storage
|
||||
*/
|
||||
//! \~english Add property if name isn't present in storage, otherwrise update existing property with same name
|
||||
//! \~russian Добавляет новое свойство, если его имени не было в контейнере, иначе обновляет существующее свойство с этим именем
|
||||
bool addProperty(const Property & p);
|
||||
bool addProperty(Property && p);
|
||||
|
||||
/**
|
||||
* @brief First of all construct Property with method params. After then add property if name isn't present
|
||||
* in storage, otherwrise update existing property with same name.
|
||||
* @return "true" if new property added, else if update existing property return "false"
|
||||
*/
|
||||
//! \~english Add property if name isn't present in storage, otherwrise update existing property with same name
|
||||
//! \~russian Добавляет новое свойство, если его имени не было в контейнере, иначе обновляет существующее свойство с этим именем
|
||||
bool addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0);
|
||||
|
||||
/**
|
||||
* @brief Remove property with \a name
|
||||
* @return "true" if property exists and removed
|
||||
*/
|
||||
bool removeProperty(const PIString & _name);
|
||||
//! \~english Remove property with name "name", returns if property removed
|
||||
//! \~russian Удаляет свойство с именем "name", возвращает было ли оно удалено
|
||||
bool removeProperty(const PIString & name);
|
||||
|
||||
/**
|
||||
* @brief Remove properties wich has \a flag set
|
||||
* @return removed properties count
|
||||
*/
|
||||
//! \~english Remove all properties with flag "flag" set, returns removed properties count
|
||||
//! \~russian Удаляет все свойства с флагом "flag", возвращает количество удаленных свойств
|
||||
int removePropertiesByFlag(int flag);
|
||||
|
||||
/**
|
||||
* @brief Merge other \a properties_ into this
|
||||
* @param flag_ignore - properties wich has this flag set will be ignored in merge
|
||||
*/
|
||||
void updateProperties(const PIVector<Property> & properties_, int flag_ignore = 0);
|
||||
//! \~english Merge other "properties" into this
|
||||
//! \~russian Объединяет "properties" с текущим контейнером
|
||||
void updateProperties(const PIVector<Property> & properties, int flag_ignore = 0);
|
||||
|
||||
/**
|
||||
* @brief Search property by name and return it.
|
||||
*
|
||||
* @param name of property
|
||||
* @return property value or default constructed Property
|
||||
*/
|
||||
//! \~english Returns property with name "name" or default-constructed %PIPropertyStorage::Property
|
||||
//! \~russian Возвращает свойство с именем "name" или пустое %PIPropertyStorage::Property
|
||||
Property propertyByName(const PIString & name) const;
|
||||
|
||||
/**
|
||||
* @brief Search property by name and return property value.
|
||||
*
|
||||
* @param name of property
|
||||
* @return property value or invalid PIVariant if name unknown
|
||||
*/
|
||||
//! \~english Returns property value with name "name" or invalid %PIVariant
|
||||
//! \~russian Возвращает значение свойства с именем "name" или недействительный %PIVariant
|
||||
PIVariant propertyValueByName(const PIString & name) const;
|
||||
|
||||
/**
|
||||
* @brief Set value of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set value
|
||||
* @param value to set
|
||||
* @return "true" if property exists and updated
|
||||
*/
|
||||
//! \~english Set value of property with name "name" to "value", returns if property exists
|
||||
//! \~russian Устанавливает значение "value" свойству с именем "name", возвращает существует ли такое свойство
|
||||
bool setPropertyValue(const PIString & name, const PIVariant & value);
|
||||
|
||||
/**
|
||||
* @brief Set comment of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set comment
|
||||
* @param comment to set
|
||||
* @return "true" if property exists and updated
|
||||
*/
|
||||
//! \~english Set comment of property with name "name" to "comment", returns if property exists
|
||||
//! \~russian Устанавливает комментарий "comment" свойству с именем "name", возвращает существует ли такое свойство
|
||||
bool setPropertyComment(const PIString & name, const PIString & comment);
|
||||
|
||||
/**
|
||||
* @brief Set flags of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set flags
|
||||
* @param flags to set
|
||||
* @return "true" if property exists and updated
|
||||
*/
|
||||
//! \~english Set flags of property with name "name" to "flags", returns if property exists
|
||||
//! \~russian Устанавливает флаги "flags" свойству с именем "name", возвращает существует ли такое свойство
|
||||
bool setPropertyFlags(const PIString & name, int flags);
|
||||
|
||||
//! \~english Add property "p"
|
||||
//! \~russian Добавляет свойство "p"
|
||||
PIPropertyStorage & operator <<(const PIPropertyStorage::Property & p) {props << p; return *this;}
|
||||
|
||||
//! \~english Add properties "p"
|
||||
//! \~russian Добавляет свойства "p"
|
||||
PIPropertyStorage & operator <<(const PIVector<Property> & p) {props << p; return *this;}
|
||||
|
||||
//! \~english Add properties "p"
|
||||
//! \~russian Добавляет свойства "p"
|
||||
PIPropertyStorage & operator <<(const PIPropertyStorage & p) {props << p.props; return *this;}
|
||||
|
||||
//! \~english Returns property with index "i"
|
||||
//! \~russian Возвращает свойство по индексу "i"
|
||||
Property & operator[](int i) {return props[i];}
|
||||
|
||||
//! \~english Returns property with index "i" as const
|
||||
//! \~russian Возвращает свойство по индексу "i" как константу
|
||||
const Property & operator[](int i) const {return props[i];}
|
||||
|
||||
//! \~english Returns property with name "name"
|
||||
//! \~russian Возвращает свойство с именем "name"
|
||||
Property & operator[](const PIString & name);
|
||||
|
||||
//! \~english Returns property with name "name" as const
|
||||
//! \~russian Возвращает свойство с именем "name" как константу
|
||||
const Property operator[](const PIString & name) const;
|
||||
|
||||
static Property parsePropertyLine(PIString l);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#endif
|
||||
|
||||
/*! \class PIString
|
||||
* @brief String class
|
||||
* \brief String class
|
||||
* \details PIP use this class for use string information.
|
||||
*
|
||||
* \section PIString_sec0 Synopsis
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
/*! \fn int versionCompare(const PIString & v0, const PIString & v1, int components = 6)
|
||||
* \relatesalso PIString
|
||||
* @brief Compare two version strings in free notation and returns 0, -1 or 1
|
||||
* \brief Compare two version strings in free notation and returns 0, -1 or 1
|
||||
* \details This function parse version to number codes and labels. Then it
|
||||
* compare no more than "components" codes. If there is no difference, compare
|
||||
* labels. Each label has corresponding integer value, so
|
||||
@@ -95,7 +95,7 @@
|
||||
*
|
||||
* \fn PIString versionNormalize(const PIString & v)
|
||||
* \relatesalso PIString
|
||||
* @brief Converts version string in free notation to classic view
|
||||
* \brief Converts version string in free notation to classic view
|
||||
* \details Parse version as described in \a versionCompare() and
|
||||
* returns classic view of codes and labels: major.minor.revision[-build][_label].
|
||||
* Example:
|
||||
@@ -139,26 +139,23 @@ const float PIString::ElideRight = 1.f;
|
||||
|
||||
|
||||
#ifndef CC_VC
|
||||
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf(ch, f, v);
|
||||
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf(ch, f, v); return PIString(ch);
|
||||
#else
|
||||
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf_s(ch, 256, f, v);
|
||||
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf_s(ch, 256, f, v); return PIString(ch);
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
//int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
|
||||
#endif
|
||||
PIString PIString::itos(const int num) {pisprintf("%d", num); return PIString(ch);}
|
||||
PIString PIString::ltos(const long num) {pisprintf("%ld", num); return PIString(ch);}
|
||||
PIString PIString::lltos(const llong num) {pisprintf("%lld", num); return PIString(ch);}
|
||||
PIString PIString::uitos(const uint num) {pisprintf("%u", num); return PIString(ch);}
|
||||
PIString PIString::ultos(const ulong num) {pisprintf("%lu", num); return PIString(ch);}
|
||||
PIString PIString::ulltos(const ullong num) {pisprintf("%llu", num); return PIString(ch);}
|
||||
|
||||
PIString PIString::itos(const int num) {pisprintf("%d", num);}
|
||||
PIString PIString::ltos(const long num) {pisprintf("%ld", num);}
|
||||
PIString PIString::lltos(const llong num) {pisprintf("%lld", num);}
|
||||
PIString PIString::uitos(const uint num) {pisprintf("%u", num);}
|
||||
PIString PIString::ultos(const ulong num) {pisprintf("%lu", num);}
|
||||
PIString PIString::ulltos(const ullong num) {pisprintf("%llu", num);}
|
||||
PIString PIString::ftos(const float num, char format, int precision) {
|
||||
char f[8] = "%.";
|
||||
int wr = sprintf(&(f[2]), "%d", precision);
|
||||
f[2 + wr] = format;
|
||||
f[3 + wr] = 0;
|
||||
pisprintf(f, num);
|
||||
return PIString(ch);
|
||||
}
|
||||
PIString PIString::dtos(const double num, char format, int precision) {
|
||||
char f[8] = "%.";
|
||||
@@ -166,7 +163,6 @@ PIString PIString::dtos(const double num, char format, int precision) {
|
||||
f[2 + wr] = format;
|
||||
f[3 + wr] = 0;
|
||||
pisprintf(f, num);
|
||||
return PIString(ch);
|
||||
}
|
||||
#undef pisprintf
|
||||
|
||||
@@ -174,7 +170,10 @@ PIString PIString::dtos(const double num, char format, int precision) {
|
||||
|
||||
PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) {
|
||||
if (value == 0LL) return PIString('0');
|
||||
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
|
||||
if (base < 2 || base > 40) {
|
||||
if (ok != 0) *ok = false;
|
||||
return PIString();
|
||||
}
|
||||
if (ok != 0) *ok = true;
|
||||
if (base == 10) return lltos(value);
|
||||
PIString ret;
|
||||
@@ -193,7 +192,10 @@ PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) {
|
||||
|
||||
PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) {
|
||||
if (value == 0ULL) return PIString('0');
|
||||
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
|
||||
if (base < 2 || base > 40) {
|
||||
if (ok != 0) *ok = false;
|
||||
return PIString();
|
||||
}
|
||||
if (ok != 0) *ok = true;
|
||||
if (base == 10) return ulltos(value);
|
||||
PIString ret;
|
||||
@@ -215,17 +217,26 @@ llong PIString::toNumberBase(const PIString & value, int base, bool * ok) {
|
||||
PIString v = value.trimmed();
|
||||
if (base < 0) {
|
||||
int ind = v.find(s_0x);
|
||||
if (ind == 0 || ind == 1) {v.remove(ind, 2); base = 16;}
|
||||
else base = 10;
|
||||
} else
|
||||
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return 0;}
|
||||
if (ind == 0 || ind == 1) {
|
||||
v.remove(ind, 2);
|
||||
base = 16;
|
||||
} else {
|
||||
base = 10;
|
||||
}
|
||||
} else if (base < 2 || base > 40) {
|
||||
if (ok != 0) *ok = false;
|
||||
return 0;
|
||||
}
|
||||
if (ok) *ok = true;
|
||||
PIVector<int> digits;
|
||||
llong ret = 0, m = 1;
|
||||
bool neg = false;
|
||||
int cs;
|
||||
for (int i = 0; i < v.size_s(); ++i) {
|
||||
if (v[i] == PIChar('-')) {neg = !neg; continue;}
|
||||
if (v[i] == PIChar('-')) {
|
||||
neg = !neg;
|
||||
continue;
|
||||
}
|
||||
cs = fromBaseN[int(v[i].toAscii())];
|
||||
if (cs < 0 || cs >= base) {
|
||||
if (ok) *ok = false;
|
||||
@@ -252,12 +263,13 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) {
|
||||
UChar * ucs = new UChar[s];
|
||||
memset(ucs, 0, s * sizeof(UChar));
|
||||
e = (UErrorCode)0;
|
||||
int sz = ucnv_toUChars(cc, ucs, s, c, s, &e);
|
||||
sz = ucnv_toUChars(cc, ucs, s, c, s, &e);
|
||||
//printf("appendFromChars %d -> %d\n", s, sz);
|
||||
//printf("PIString %d -> %d\n", c[0], ucs[0]);
|
||||
reserve(size_s() + sz);
|
||||
for (int i = 0; i < sz; ++i)
|
||||
push_back(PIChar(ucs[i]));
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
push_back(PIChar((ushort)ucs[i]));
|
||||
}
|
||||
delete[] ucs;
|
||||
ucnv_close(cc);
|
||||
return;
|
||||
@@ -280,7 +292,7 @@ void PIString::appendFromChars(const char * c, int s, const char * codepage) {
|
||||
sz = mbtowc(&wc, c, s);
|
||||
//qDebug() << "1" << sz;
|
||||
if (sz < 1) break;
|
||||
push_back(PIChar(int(wc)));
|
||||
push_back(PIChar(wc));
|
||||
c += sz; s -= sz;
|
||||
//qDebug() << "2" << c;
|
||||
}
|
||||
@@ -339,8 +351,10 @@ PIString PIString::fromAscii(const char * s) {
|
||||
|
||||
PIString PIString::fromAscii(const char * s, int len) {
|
||||
PIString ret;
|
||||
for (int l = 0; l < len; ++l)
|
||||
ret.reserve(len);
|
||||
for (int l = 0; l < len; ++l) {
|
||||
ret.push_back(PIChar(s[l]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -379,13 +393,14 @@ void PIString::buildData(const char * cp) const {
|
||||
char uc[8];
|
||||
data_.reserve(size_s());
|
||||
for (int i = 0; i < size_s(); ++i) {
|
||||
if (at(i).isAscii())
|
||||
if (at(i).isAscii()) {
|
||||
data_.push_back(uchar(at(i).unicode16Code()));
|
||||
else {
|
||||
} else {
|
||||
e = (UErrorCode)0;
|
||||
sz = ucnv_fromUChars(cc, uc, 8, (const UChar*)(PIDeque<PIChar>::data(i)), 1, &e);
|
||||
for (int j = 0; j < sz; ++j)
|
||||
for (int j = 0; j < sz; ++j) {
|
||||
data_.push_back(uc[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
ucnv_close(cc);
|
||||
@@ -416,8 +431,9 @@ void PIString::buildData(const char * cp) const {
|
||||
}
|
||||
wc = at(i).toWChar();
|
||||
sz = wctomb(tc, wc);
|
||||
for (int b = 0; b < sz; ++b)
|
||||
for (int b = 0; b < sz; ++b) {
|
||||
data_.push_back(uchar(tc[b]));
|
||||
}
|
||||
}
|
||||
data_.push_back(uchar('\0'));
|
||||
# endif
|
||||
@@ -426,13 +442,19 @@ void PIString::buildData(const char * cp) const {
|
||||
|
||||
|
||||
void PIString::trimsubstr(int &st, int &fn) const {
|
||||
for (int i = 0; i < length(); ++i)
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0))
|
||||
{st = i; break;}
|
||||
for (int i = 0; i < length(); ++i) {
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) {
|
||||
st = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (st < 0) return;
|
||||
for (int i = length() - 1; i >= 0; --i)
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0))
|
||||
{fn = i; break;}
|
||||
for (int i = length() - 1; i >= 0; --i) {
|
||||
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12) && at(i) != uchar(0)) {
|
||||
fn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -450,8 +472,9 @@ const char * PIString::dataUTF8() const {
|
||||
|
||||
const char * PIString::dataAscii() const {
|
||||
data_.clear();
|
||||
for (int i = 0; i < size_s(); ++i)
|
||||
for (int i = 0; i < size_s(); ++i) {
|
||||
data_.push_back(uchar(at(i).ch));
|
||||
}
|
||||
data_.push_back(uchar('\0'));
|
||||
return (const char *)data_.data();
|
||||
}
|
||||
@@ -497,8 +520,9 @@ PIString & PIString::operator +=(const char * str) {
|
||||
PIString & PIString::operator +=(const wchar_t * str) {
|
||||
if (!str) return *this;
|
||||
int i = -1;
|
||||
while (str[++i])
|
||||
push_back(PIChar(ushort(str[i])));
|
||||
while (str[++i]) {
|
||||
push_back(PIChar(str[i]));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -512,9 +536,9 @@ PIString & PIString::operator +=(const PIString & str) {
|
||||
bool PIString::operator ==(const PIString & str) const {
|
||||
uint l = str.size();
|
||||
if (size() != l) return false;
|
||||
for (uint i = 0; i < l; ++i)
|
||||
if (str[i] != at(i))
|
||||
return false;
|
||||
for (uint i = 0; i < l; ++i) {
|
||||
if (str[i] != at(i)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -522,9 +546,9 @@ bool PIString::operator ==(const PIString & str) const {
|
||||
bool PIString::operator !=(const PIString & str) const {
|
||||
uint l = str.size();
|
||||
if (size() != l) return true;
|
||||
for (uint i = 0; i < l; ++i)
|
||||
if (str[i] != at(i))
|
||||
return true;
|
||||
for (uint i = 0; i < l; ++i) {
|
||||
if (str[i] != at(i)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -566,8 +590,7 @@ PIString PIString::mid(const int start, const int len) const {
|
||||
if (l < 0) {
|
||||
return PIString(&(at(s)), size_s() - s);
|
||||
} else {
|
||||
if (l > length() - s)
|
||||
l = length() - s;
|
||||
if (l > length() - s) l = length() - s;
|
||||
return PIString(&(at(s)), l);
|
||||
}
|
||||
return PIString();
|
||||
@@ -581,11 +604,10 @@ PIString & PIString::cutMid(const int start, const int len) {
|
||||
l += s;
|
||||
s = 0;
|
||||
}
|
||||
if (l < 0)
|
||||
if (l < 0) {
|
||||
remove(s, size() - s);
|
||||
else {
|
||||
if (l > length() - s)
|
||||
l = length() - s;
|
||||
} else {
|
||||
if (l > length() - s) l = length() - s;
|
||||
remove(s, l);
|
||||
}
|
||||
return *this;
|
||||
@@ -615,9 +637,9 @@ PIString PIString::trimmed() const {
|
||||
|
||||
PIString & PIString::replace(int from, int count, const PIString & with) {
|
||||
count = piMini(count, length() - from);
|
||||
if (count == with.size_s())
|
||||
if (count == with.size_s()) {
|
||||
memcpy(PIDeque<PIChar>::data(from), static_cast<PIDeque<PIChar>>(with).data(), count * sizeof(PIChar));
|
||||
else {
|
||||
} else {
|
||||
remove(from, count);
|
||||
PIDeque<PIChar>::insert(from, with);
|
||||
}
|
||||
@@ -639,8 +661,9 @@ PIString & PIString::replace(const PIString & what, const PIString & with, bool
|
||||
|
||||
PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
|
||||
if (what.isEmpty() || what == with) return *this;
|
||||
if (with.isEmpty()) removeAll(what);
|
||||
else {
|
||||
if (with.isEmpty()) {
|
||||
removeAll(what);
|
||||
} else {
|
||||
int l = what.length(), dl = with.length() - what.length();
|
||||
for (int i = 0; i < length() - l + 1; ++i) {
|
||||
bool match = true;
|
||||
@@ -654,7 +677,6 @@ PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
|
||||
if (dl > 0) PIDeque<PIChar>::insert(i, PIDeque<PIChar>((size_t)dl));
|
||||
if (dl < 0) PIDeque<PIChar>::remove(i, -dl);
|
||||
memcpy(PIDeque<PIChar>::data(i), &(with.at(0)), with.length() * sizeof(PIChar));
|
||||
//i -= l;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
@@ -675,7 +697,6 @@ PIString & PIString::replaceAll(const PIString & what, const char with) {
|
||||
if (!match) continue;
|
||||
if (dl > 0) PIDeque<PIChar>::remove(i, dl);
|
||||
(*this)[i] = PIChar(with);
|
||||
//i -= l;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -684,8 +705,7 @@ PIString & PIString::replaceAll(const PIString & what, const char with) {
|
||||
PIString & PIString::replaceAll(const char what, const char with) {
|
||||
int l = length();
|
||||
for (int i = 0; i < l; ++i) {
|
||||
if (at(i) == what)
|
||||
(*this)[i] = with;
|
||||
if (at(i) == what) (*this)[i] = with;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -748,35 +768,35 @@ PIStringList PIString::split(const PIString & delim) const {
|
||||
|
||||
|
||||
int PIString::find(const char c, const int start) const {
|
||||
for (int i = start; i < length(); ++i)
|
||||
if (at(i) == c)
|
||||
return i;
|
||||
for (int i = start; i < length(); ++i) {
|
||||
if (at(i) == c) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::find(const PIString & str, const int start) const {
|
||||
int l = str.length();
|
||||
for (int i = start; i < length() - l + 1; ++i)
|
||||
if (mid(i, l) == str)
|
||||
return i;
|
||||
for (int i = start; i < length() - l + 1; ++i) {
|
||||
if (mid(i, l) == str) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::findLast(const char c, const int start) const {
|
||||
for (int i = length() - 1; i >= start; --i)
|
||||
if (at(i) == c)
|
||||
return i;
|
||||
for (int i = length() - 1; i >= start; --i) {
|
||||
if (at(i) == c) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::findLast(const PIString & str, const int start) const {
|
||||
int l = str.length();
|
||||
for (int i = length() - l; i >= start; --i)
|
||||
if (mid(i, l) == str)
|
||||
return i;
|
||||
for (int i = length() - l; i >= start; --i) {
|
||||
if (mid(i, l) == str) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -786,8 +806,20 @@ int PIString::findWord(const PIString & word, const int start) const {
|
||||
while ((f = find(word, f + 1)) >= 0) {
|
||||
bool ok = true;
|
||||
PIChar c;
|
||||
if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}}
|
||||
if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}}
|
||||
if (f > 0) {
|
||||
c = (*this)[f - 1];
|
||||
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (f + wl < tl) {
|
||||
c = (*this)[f + wl];
|
||||
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ok) return f;
|
||||
}
|
||||
return -1;
|
||||
@@ -799,8 +831,20 @@ int PIString::findCWord(const PIString & word, const int start) const {
|
||||
while ((f = find(word, f + 1)) >= 0) {
|
||||
bool ok = true;
|
||||
PIChar c;
|
||||
if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}}
|
||||
if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}}
|
||||
if (f > 0) {
|
||||
c = (*this)[f - 1];
|
||||
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (f + wl < tl) {
|
||||
c = (*this)[f + wl];
|
||||
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ok) return f;
|
||||
}
|
||||
return -1;
|
||||
@@ -813,7 +857,10 @@ int PIString::findRange(const PIChar start, const PIChar end, const PIChar shiel
|
||||
int sz = size_s(), ls = -1, le = -1, cnt = 0;
|
||||
for (int i = start_index; i < sz; ++i) {
|
||||
PIChar c = at(i);
|
||||
if (c == shield) {++i; continue;}
|
||||
if (c == shield) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (trim_) {
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
continue;
|
||||
@@ -845,25 +892,26 @@ int PIString::findRange(const PIChar start, const PIChar end, const PIChar shiel
|
||||
|
||||
|
||||
int PIString::findAny(const PIString & str, const int start) const {
|
||||
for (int i = start; i < length(); ++i)
|
||||
if (str.contains(at(i)))
|
||||
return i;
|
||||
for (int i = start; i < length(); ++i) {
|
||||
if (str.contains(at(i))) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::findAnyLast(const PIString & str, const int start) const {
|
||||
for (int i = length() - 1; i >= start; --i)
|
||||
if (str.contains(at(i)))
|
||||
return i;
|
||||
for (int i = length() - 1; i >= start; --i) {
|
||||
if (str.contains(at(i))) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::entries(const PIChar c) const {
|
||||
int sz = size_s(), ret = 0;
|
||||
for (int i = 0; i < sz; ++i)
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
if (at(i) == c) ++ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -898,8 +946,7 @@ PIString PIString::takeSymbol() {
|
||||
int sz = size_s(), ss = -1;
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
PIChar c = at(i);
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
continue;
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
|
||||
ss = i;
|
||||
break;
|
||||
}
|
||||
@@ -942,10 +989,11 @@ PIString PIString::takeCWord() {
|
||||
}
|
||||
} else {
|
||||
if (ws < 0) {
|
||||
if (c.isAlpha() || c == '_')
|
||||
if (c.isAlpha() || c == '_') {
|
||||
ws = i;
|
||||
else
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
if (!c.isAlpha() && !c.isDigit() && c != '_') {
|
||||
we = i;
|
||||
@@ -971,9 +1019,11 @@ PIString PIString::takeLine() {
|
||||
}
|
||||
}
|
||||
PIString ret = left(le);
|
||||
if (!ret.isEmpty())
|
||||
if (ret.back() == '\r')
|
||||
if (!ret.isEmpty()) {
|
||||
if (ret.back() == '\r') {
|
||||
ret.cutRight(1);
|
||||
}
|
||||
}
|
||||
cutLeft(le < 0 ? sz : le + 1);
|
||||
return ret;
|
||||
}
|
||||
@@ -988,37 +1038,75 @@ PIString PIString::takeNumber() {
|
||||
//piCout << "char " << c << "phase" << phase;
|
||||
switch (phase) {
|
||||
case 0: // trim
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||||
continue;
|
||||
}
|
||||
phase = 7;
|
||||
case 7: // sign
|
||||
if (c == '-' || c == '+') {ls = i; phase = 1; break;}
|
||||
if (c == '-' || c == '+') {
|
||||
ls = i;
|
||||
phase = 1;
|
||||
break;
|
||||
}
|
||||
case 1: // search start
|
||||
if (c >= '0' && c <= '9') {le = i; if (ls < 0) ls = i; phase = 2; break;}
|
||||
if (c == '.') {le = i; if (ls < 0) ls = i; phase = 3; break;}
|
||||
if ((c >= '0' && c <= '9') || c == '.') {
|
||||
le = i;
|
||||
if (ls < 0) ls = i;
|
||||
if (c == '.') phase = 3;
|
||||
else phase = 2;
|
||||
break;
|
||||
}
|
||||
phase = 9;
|
||||
break;
|
||||
case 2: // integer
|
||||
if (c == '.') {le = i; phase = 3; break;}
|
||||
if (c == 'e' || c == 'E') {le = i; phase = 4; break;}
|
||||
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == 'x') {le = i; break;}
|
||||
if (c == '.') {
|
||||
le = i;
|
||||
phase = 3;
|
||||
break;
|
||||
}
|
||||
if (c == 'e' || c == 'E') {
|
||||
le = i;
|
||||
phase = 4;
|
||||
break;
|
||||
}
|
||||
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == 'x') {
|
||||
le = i;
|
||||
break;
|
||||
}
|
||||
phase = 6;
|
||||
break;
|
||||
case 3: // point
|
||||
if (c == 'e' || c == 'E') {le = i; phase = 4; break;}
|
||||
if (c >= '0' && c <= '9') {le = i; break;}
|
||||
if (c == 'e' || c == 'E') {
|
||||
le = i;
|
||||
phase = 4;
|
||||
break;
|
||||
}
|
||||
if (c >= '0' && c <= '9') {
|
||||
le = i;
|
||||
break;
|
||||
}
|
||||
phase = 6;
|
||||
break;
|
||||
case 4: // exp
|
||||
if ((c >= '0' && c <= '9') || c == '-' || c == '+') {le = i; phase = 5; break;}
|
||||
if ((c >= '0' && c <= '9') || c == '-' || c == '+') {
|
||||
le = i;
|
||||
phase = 5;
|
||||
break;
|
||||
}
|
||||
phase = 6;
|
||||
break;
|
||||
case 5: // power
|
||||
if (c >= '0' && c <= '9') {le = i; break;}
|
||||
if (c >= '0' && c <= '9') {
|
||||
le = i;
|
||||
break;
|
||||
}
|
||||
phase = 6;
|
||||
break;
|
||||
case 6: // suffix
|
||||
if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') {le = i; break;}
|
||||
if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') {
|
||||
le = i;
|
||||
break;
|
||||
}
|
||||
phase = 9;
|
||||
break;
|
||||
}
|
||||
@@ -1041,16 +1129,25 @@ PIString PIString::takeRange(const PIChar start, const PIChar end, const PIChar
|
||||
int sz = size_s(), ls = -1, le = -1, cnt = 0;
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
PIChar c = at(i);
|
||||
if (c == shield) {++i; continue;}
|
||||
if (c == shield) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (trim_) {
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||||
continue;
|
||||
}
|
||||
trim_ = false;
|
||||
}
|
||||
if (eq) {
|
||||
if (c == start) {
|
||||
if (cnt == 0) ls = i;
|
||||
else {le = i; cnt = 0; break;}
|
||||
if (cnt == 0) {
|
||||
ls = i;
|
||||
} else {
|
||||
le = i;
|
||||
cnt = 0;
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
} else {
|
||||
@@ -1095,7 +1192,9 @@ PIString PIString::inBrackets(const PIChar start, const PIChar end) const {
|
||||
PIString PIString::toUpperCase() const {
|
||||
PIString str(*this);
|
||||
int l = str.size();
|
||||
for (int i = 0; i < l; ++i) str[i] = str[i].toUpper();
|
||||
for (int i = 0; i < l; ++i) {
|
||||
str[i] = str[i].toUpper();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -1103,7 +1202,9 @@ PIString PIString::toUpperCase() const {
|
||||
PIString PIString::toLowerCase() const {
|
||||
PIString str(*this);
|
||||
int l = str.size();
|
||||
for (int i = 0; i < l; ++i) str[i] = str[i].toLower();
|
||||
for (int i = 0; i < l; ++i) {
|
||||
str[i] = str[i].toLower();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -1144,23 +1245,38 @@ ldouble PIString::toLDouble() const {
|
||||
|
||||
PIString & PIString::setReadableSize(llong bytes) {
|
||||
clear();
|
||||
if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + PIStringAscii(" B")); return *this;}
|
||||
if (bytes < 1024) {
|
||||
*this += (PIString::fromNumber(bytes) + PIStringAscii(" B"));
|
||||
return *this;
|
||||
}
|
||||
double fres = bytes / 1024.;
|
||||
llong res = bytes / 1024;
|
||||
fres -= res;
|
||||
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" kB")); return *this;}
|
||||
if (res < 1024) {
|
||||
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" kB"));
|
||||
return *this;
|
||||
}
|
||||
fres = res / 1024.;
|
||||
res /= 1024;
|
||||
fres -= res;
|
||||
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" MB")); return *this;}
|
||||
if (res < 1024) {
|
||||
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" MB"));
|
||||
return *this;
|
||||
}
|
||||
fres = res / 1024.;
|
||||
res /= 1024;
|
||||
fres -= res;
|
||||
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" GB")); return *this;}
|
||||
if (res < 1024) {
|
||||
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" GB"));
|
||||
return *this;
|
||||
}
|
||||
fres = res / 1024.;
|
||||
res /= 1024;
|
||||
fres -= res;
|
||||
if (res < 1024) {*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" TB")); return *this;}
|
||||
if (res < 1024) {
|
||||
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" TB"));
|
||||
return *this;
|
||||
}
|
||||
fres = res / 1024.;
|
||||
res /= 1024;
|
||||
fres -= res;
|
||||
@@ -1183,11 +1299,11 @@ void parseVersion(PIString s, PIVector<int> & codes, PIStringList & strs) {
|
||||
int ind = s.findLast('.') + 1;
|
||||
while (!_versionDelims_.contains(s[ind])) {
|
||||
++ind;
|
||||
if (ind > s.size_s() - 1)
|
||||
break;
|
||||
if (ind > s.size_s() - 1) break;
|
||||
}
|
||||
for (int i = 0; i < mccnt; ++i)
|
||||
for (int i = 0; i < mccnt; ++i) {
|
||||
s.insert(ind, PIStringAscii(".0"));
|
||||
}
|
||||
}
|
||||
PIStringList comps;
|
||||
while (!s.isEmpty()) {
|
||||
@@ -1201,8 +1317,7 @@ void parseVersion(PIString s, PIVector<int> & codes, PIStringList & strs) {
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < comps.size_s(); ++i) {
|
||||
if (comps[i].isEmpty())
|
||||
comps[i] = '0';
|
||||
if (comps[i].isEmpty()) comps[i] = '0';
|
||||
bool ok = false;
|
||||
int val = comps[i].toInt(-1, &ok);
|
||||
if (ok) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file pistring.h
|
||||
* @brief String
|
||||
*
|
||||
* This file declare string and string list classes
|
||||
/*! \file pistring.h
|
||||
* \ingroup Core
|
||||
* \brief
|
||||
* \~english String class
|
||||
* \~russian Класс строки
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -59,12 +60,12 @@ public:
|
||||
PIString(const PIChar c): PIDeque<PIChar>() {*this += c;}
|
||||
PIString(const char c): PIDeque<PIChar>() {*this += PIChar(c);}
|
||||
|
||||
/*! @brief Contructs string from c-string "str"
|
||||
/*! \brief Contructs string from c-string "str"
|
||||
* \details "str" should be null-terminated\n
|
||||
* Example: \snippet pistring.cpp PIString(char * ) */
|
||||
PIString(const char * str): PIDeque<PIChar>() {*this += str;}
|
||||
|
||||
/*! @brief Contructs string from \c wchar_t c-string "str"
|
||||
/*! \brief Contructs string from \c wchar_t c-string "str"
|
||||
* \details "str" should be null-terminated\n
|
||||
* Example: \snippet pistring.cpp PIString(wchar_t * ) */
|
||||
PIString(const wchar_t * str): PIDeque<PIChar>() {*this += str;}
|
||||
@@ -72,18 +73,18 @@ public:
|
||||
//! Contructs string from byte array "ba"
|
||||
PIString(const PIByteArray & ba): PIDeque<PIChar>() {*this += ba;}
|
||||
|
||||
//! @brief Contructs string from "len" characters of buffer "str"
|
||||
//! \brief Contructs string from "len" characters of buffer "str"
|
||||
PIString(const PIChar * str, const int len): PIDeque<PIChar>(str, size_t(len)) {}
|
||||
|
||||
/*! @brief Contructs string from "len" characters of buffer "str"
|
||||
/*! \brief Contructs string from "len" characters of buffer "str"
|
||||
* \details Example: \snippet pistring.cpp PIString(char * , int) */
|
||||
PIString(const char * str, const int len): PIDeque<PIChar>() {appendFromChars(str, len);}
|
||||
|
||||
/*! @brief Contructs string as sequence of characters "c" of buffer with length "len"
|
||||
/*! \brief Contructs string as sequence of characters "c" of buffer with length "len"
|
||||
* \details Example: \snippet pistring.cpp PIString(int, char) */
|
||||
PIString(const int len, const char c): PIDeque<PIChar>() {for (int i = 0; i < len; ++i) push_back(c);}
|
||||
|
||||
/*! @brief Contructs string as sequence of symbols "c" of buffer with length "len"
|
||||
/*! \brief Contructs string as sequence of symbols "c" of buffer with length "len"
|
||||
* \details Example: \snippet pistring.cpp PIString(int, PIChar) */
|
||||
PIString(const int len, const PIChar c): PIDeque<PIChar>() {for (int i = 0; i < len; ++i) push_back(c);}
|
||||
|
||||
@@ -148,32 +149,32 @@ public:
|
||||
//! Compare operator
|
||||
bool operator >=(const char * str) const {return *this >= PIString(str);}
|
||||
|
||||
/*! @brief Append string "str" at the end of string
|
||||
/*! \brief Append string "str" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(PIString) */
|
||||
PIString & operator <<(const PIString & str) {*this += str; return *this;}
|
||||
|
||||
/*! @brief Append symbol "c" at the end of string
|
||||
/*! \brief Append symbol "c" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(PIChar) */
|
||||
PIString & operator <<(const PIChar c) {*this += c; return *this;}
|
||||
|
||||
/*! @brief Append symbol "c" at the end of string
|
||||
/*! \brief Append symbol "c" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(PIChar) */
|
||||
PIString & operator <<(const char c) {*this += PIChar(c); return *this;}
|
||||
|
||||
/*! @brief Append c-string "str" at the end of string
|
||||
/*! \brief Append c-string "str" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(char * ) */
|
||||
PIString & operator <<(const char * str) {*this += str; return *this;}
|
||||
|
||||
/*! @brief Append \c wchar_t c-string "str" at the end of string
|
||||
/*! \brief Append \c wchar_t c-string "str" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(wchar_t * ) */
|
||||
PIString & operator <<(const wchar_t * str) {*this += str; return *this;}
|
||||
|
||||
/*! @brief Append string representation of "num" at the end of string
|
||||
/*! \brief Append string representation of "num" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(int) */
|
||||
PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
/*! @brief Append string representation of "num" at the end of string
|
||||
/*! \brief Append string representation of "num" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(int) */
|
||||
PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
@@ -181,101 +182,101 @@ public:
|
||||
PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
/*! @brief Append string representation of "num" at the end of string
|
||||
/*! \brief Append string representation of "num" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(int) */
|
||||
PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
/*! @brief Append string representation of "num" at the end of string
|
||||
/*! \brief Append string representation of "num" at the end of string
|
||||
* \details Example: \snippet pistring.cpp PIString::<<(int) */
|
||||
PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;}
|
||||
|
||||
|
||||
//! @brief Insert string "str" at the begin of string
|
||||
//! \brief Insert string "str" at the begin of string
|
||||
PIString & prepend(const PIString & str) {insert(0, str); return *this;}
|
||||
|
||||
//! @brief Insert string "str" at the end of string
|
||||
//! \brief Insert string "str" at the end of string
|
||||
PIString & append(const PIString & str) {*this += str; return *this;}
|
||||
|
||||
|
||||
/*! @brief Return part of string from symbol at index "start" and maximum length "len"
|
||||
/*! \brief Return part of string from symbol at index "start" and maximum length "len"
|
||||
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid
|
||||
* \sa \a left(), \a right() */
|
||||
PIString mid(const int start, const int len = -1) const;
|
||||
|
||||
/*! @brief Return sub-string of string from symbol at index "start" and maximum length "len" */
|
||||
/*! \brief Return sub-string of string from symbol at index "start" and maximum length "len" */
|
||||
PIString subString(const int start, const int len = -1) const {return mid(start, len);}
|
||||
|
||||
/*! @brief Return part of string from left and maximum length "len"
|
||||
/*! \brief Return part of string from left and maximum length "len"
|
||||
* \details Example: \snippet pistring.cpp PIString::left
|
||||
* \sa \a mid(), \a right() */
|
||||
PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);}
|
||||
|
||||
/*! @brief Return part of string from right and maximum length "len"
|
||||
/*! \brief Return part of string from right and maximum length "len"
|
||||
* \details Example: \snippet pistring.cpp PIString::right
|
||||
* \sa \a mid(), \a left() */
|
||||
PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);}
|
||||
|
||||
/*! @brief Remove part of string from symbol as index "start" and maximum length "len"
|
||||
/*! \brief Remove part of string from symbol as index "start" and maximum length "len"
|
||||
* and return this string
|
||||
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::cutMid
|
||||
* \sa \a cutLeft(), \a cutRight() */
|
||||
PIString & cutMid(const int start, const int len);
|
||||
|
||||
/*! @brief Remove part of string from left and maximum length "len" and return this string
|
||||
/*! \brief Remove part of string from left and maximum length "len" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::cutLeft
|
||||
* \sa \a cutMid(), \a cutRight() */
|
||||
PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);}
|
||||
|
||||
/*! @brief Remove part of string from right and maximum length "len" and return this string
|
||||
/*! \brief Remove part of string from right and maximum length "len" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::cutRight
|
||||
* \sa \a cutMid(), \a cutLeft() */
|
||||
PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);}
|
||||
|
||||
/*! @brief Remove spaces at the start and at the end of string and return this string
|
||||
/*! \brief Remove spaces at the start and at the end of string and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::trim
|
||||
* \sa \a trimmed() */
|
||||
PIString & trim();
|
||||
|
||||
/*! @brief Return copy of this string without spaces at the start and at the end
|
||||
/*! \brief Return copy of this string without spaces at the start and at the end
|
||||
* \details Example: \snippet pistring.cpp PIString::trimmed
|
||||
* \sa \a trim() */
|
||||
PIString trimmed() const;
|
||||
|
||||
/*! @brief Replace part of string from index "from" and maximum length "len"
|
||||
/*! \brief Replace part of string from index "from" and maximum length "len"
|
||||
* with string "with" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::replace_0
|
||||
* \sa \a replaced(), \a replaceAll() */
|
||||
PIString & replace(const int from, const int count, const PIString & with);
|
||||
|
||||
/*! @brief Replace part copy of this string from index "from" and maximum length "len"
|
||||
/*! \brief Replace part copy of this string from index "from" and maximum length "len"
|
||||
* with string "with" and return copied string
|
||||
* \details Example: \snippet pistring.cpp PIString::replaced_0
|
||||
* \sa \a replace(), \a replaceAll() */
|
||||
PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;}
|
||||
|
||||
/*! @brief Replace first founded substring "what" with string "with" and return this string
|
||||
/*! \brief Replace first founded substring "what" with string "with" and return this string
|
||||
* \details If "ok" is not null, it set to "true" if something was replaced\n
|
||||
* Example: \snippet pistring.cpp PIString::replace_1
|
||||
* \sa \a replaced(), \a replaceAll() */
|
||||
PIString & replace(const PIString & what, const PIString & with, bool * ok = 0);
|
||||
|
||||
/*! @brief Replace first founded substring "what" with string "with" and return copied string
|
||||
/*! \brief Replace first founded substring "what" with string "with" and return copied string
|
||||
* \details If "ok" is not null, it set to "true" if something was replaced\n
|
||||
* Example: \snippet pistring.cpp PIString::replaced_1
|
||||
* \sa \a replaced(), \a replaceAll() */
|
||||
PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;}
|
||||
|
||||
/*! @brief Replace all founded substrings "what" with strings "with" and return this string
|
||||
/*! \brief Replace all founded substrings "what" with strings "with" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::replaceAll
|
||||
* \sa \a replace(), \a replaced() */
|
||||
PIString & replaceAll(const PIString & what, const PIString & with);
|
||||
|
||||
/*! @brief Replace all founded substrings "what" with symbol "with" and return this string
|
||||
/*! \brief Replace all founded substrings "what" with symbol "with" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::replaceAll
|
||||
* \sa \a replace(), \a replaced() */
|
||||
PIString & replaceAll(const PIString & what, const char with);
|
||||
|
||||
/*! @brief Replace all founded symbols "what" with symbol "with" and return this string
|
||||
/*! \brief Replace all founded symbols "what" with symbol "with" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::replaceAll
|
||||
* \sa \a replace(), \a replaced() */
|
||||
PIString & replaceAll(const char what, const char with);
|
||||
@@ -288,119 +289,119 @@ public:
|
||||
|
||||
PIString & removeAll(char c) {PIDeque<PIChar>::removeAll(PIChar(c)); return *this;}
|
||||
|
||||
/*! @brief Repeat content of string "times" times and return this string
|
||||
/*! \brief Repeat content of string "times" times and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::repeat */
|
||||
PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;}
|
||||
|
||||
/*! @brief Returns repeated "times" times string
|
||||
/*! \brief Returns repeated "times" times string
|
||||
* \details Example: \snippet pistring.cpp PIString::repeated */
|
||||
PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);}
|
||||
|
||||
/*! @brief Insert symbol "c" after index "index" and return this string
|
||||
/*! \brief Insert symbol "c" after index "index" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::insert_0 */
|
||||
PIString & insert(const int index, const PIChar c) {PIDeque<PIChar>::insert(index, c); return *this;}
|
||||
|
||||
/*! @brief Insert symbol "c" after index "index" and return this string
|
||||
/*! \brief Insert symbol "c" after index "index" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::insert_1 */
|
||||
PIString & insert(const int index, const char c) {return insert(index, PIChar(c));}
|
||||
|
||||
/*! @brief Insert string "str" after index "index" and return this string
|
||||
/*! \brief Insert string "str" after index "index" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::insert_2 */
|
||||
PIString & insert(const int index, const PIString & str);
|
||||
|
||||
/*! @brief Insert string "str" after index "index" and return this string
|
||||
/*! \brief Insert string "str" after index "index" and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::insert_2 */
|
||||
PIString & insert(const int index, const char * c) {return insert(index, PIString(c));}
|
||||
|
||||
/*! @brief Enlarge string to length "len" by addition sequence of symbols
|
||||
/*! \brief Enlarge string to length "len" by addition sequence of symbols
|
||||
* "c" at the end of string, and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::expandRightTo
|
||||
* \sa \a expandLeftTo() */
|
||||
PIString & expandRightTo(const int len, const PIChar c) {if (len > length()) resize(len, c); return *this;}
|
||||
|
||||
/*! @brief Enlarge string to length "len" by addition sequence of symbols
|
||||
/*! \brief Enlarge string to length "len" by addition sequence of symbols
|
||||
* "c" at the beginning of string, and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::expandLeftTo
|
||||
* \sa \a expandRightTo() */
|
||||
PIString & expandLeftTo(const int len, const PIChar c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;}
|
||||
|
||||
/*! @brief Enlarge and returns copy of this string to length "len"
|
||||
/*! \brief Enlarge and returns copy of this string to length "len"
|
||||
* by addition sequence of symbols "c" at the end of string
|
||||
* \sa \a expandRightTo() */
|
||||
PIString expandedRightTo(const int len, const PIChar c) const {return PIString(*this).expandRightTo(len, c);}
|
||||
|
||||
/*! @brief Enlarge and returns copy of this string to length "len"
|
||||
/*! \brief Enlarge and returns copy of this string to length "len"
|
||||
* by addition sequence of symbols "c" at the beginning of string
|
||||
* \sa \a expandLeftTo() */
|
||||
PIString expandedLeftTo(const int len, const PIChar c) const {return PIString(*this).expandLeftTo(len, c);}
|
||||
|
||||
/*! @brief Add "c" symbols at the beginning and end of the string, and return this string
|
||||
/*! \brief Add "c" symbols at the beginning and end of the string, and return this string
|
||||
* \sa \a quoted() */
|
||||
PIString & quote(PIChar c = PIChar('"')) {insert(0, c); *this += c; return *this;}
|
||||
|
||||
/*! @brief Return quoted copy of this string
|
||||
/*! \brief Return quoted copy of this string
|
||||
* \sa \a quote() */
|
||||
PIString quoted(PIChar c = PIChar('"')) {return PIString(*this).quote(c);}
|
||||
|
||||
/*! @brief Reverse string and return this string
|
||||
/*! \brief Reverse string and return this string
|
||||
* \details Example: \snippet pistring.cpp PIString::reverse
|
||||
* \sa \a reversed() */
|
||||
PIString & reverse() {PIString str(*this); clear(); piForeachCR (PIChar c, str) push_back(c); return *this;}
|
||||
|
||||
/*! @brief Reverse copy of this string and return it
|
||||
/*! \brief Reverse copy of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::reversed
|
||||
* \sa \a reverse() */
|
||||
PIString reversed() const {PIString str(*this); str.reverse(); return str;}
|
||||
|
||||
/*! @brief Elide string to maximum size \"size\" and return this string
|
||||
/*! \brief Elide string to maximum size \"size\" and return this string
|
||||
* \sa \a elided() */
|
||||
PIString & elide(int size, float pos = ElideCenter);
|
||||
|
||||
/*! @brief Elide copy of this string to maximum size \"size\" and return it
|
||||
/*! \brief Elide copy of this string to maximum size \"size\" and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::elided
|
||||
* \sa \a elide() */
|
||||
PIString elided(int size, float pos = ElideCenter) const {PIString str(*this); str.elide(size, pos); return str;}
|
||||
|
||||
|
||||
/*! @brief Take a part of string from symbol at index "start" and maximum length "len" and return it
|
||||
/*! \brief Take a part of string from symbol at index "start" and maximum length "len" and return it
|
||||
* \sa \a takeLeft, \a takeRight() */
|
||||
PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;}
|
||||
|
||||
/*! @brief Take a part from the begin of string with maximum length "len" and return it
|
||||
/*! \brief Take a part from the begin of string with maximum length "len" and return it
|
||||
* \sa \a takeMid(), \a takeRight() */
|
||||
PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;}
|
||||
|
||||
/*! @brief Take a part from the end of string with maximum length "len" and return it
|
||||
/*! \brief Take a part from the end of string with maximum length "len" and return it
|
||||
* \sa \a takeMid(), \a takeLeft() */
|
||||
PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;}
|
||||
|
||||
/*! @brief Take a symbol from the begin of this string and return it
|
||||
/*! \brief Take a symbol from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeSymbol
|
||||
* \sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeSymbol();
|
||||
|
||||
/*! @brief Take a word from the begin of this string and return it
|
||||
/*! \brief Take a word from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeWord
|
||||
* \sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeWord();
|
||||
|
||||
/*! @brief Take a word with letters, numbers and '_' symbols from the
|
||||
/*! \brief Take a word with letters, numbers and '_' symbols from the
|
||||
* begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeCWord
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeCWord();
|
||||
|
||||
/*! @brief Take a line from the begin of this string and return it
|
||||
/*! \brief Take a line from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeLine
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange() */
|
||||
PIString takeLine();
|
||||
|
||||
/*! @brief Take a number with C-format from the begin of this string and return it
|
||||
/*! \brief Take a number with C-format from the begin of this string and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::takeNumber
|
||||
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange() */
|
||||
PIString takeNumber();
|
||||
|
||||
/*! @brief Take a range between "start" and "end" symbols from the begin of this
|
||||
/*! \brief Take a range between "start" and "end" symbols from the begin of this
|
||||
* string and return it.
|
||||
* \details "Shield" symbol prevent analysis of the next symbol.
|
||||
* Example: \snippet pistring.cpp PIString::takeRange
|
||||
@@ -408,19 +409,19 @@ public:
|
||||
PIString takeRange(const PIChar start, const PIChar end, const PIChar shield = '\\');
|
||||
|
||||
|
||||
/*! @brief Return a string in brackets "start" and "end" symbols from the begin of this
|
||||
/*! \brief Return a string in brackets "start" and "end" symbols from the begin of this
|
||||
* string and return it.
|
||||
* \details Example: string = "a(b(c)d)e"; inBrackets('(', ')') = "b(c)d"; */
|
||||
PIString inBrackets(const PIChar start, const PIChar end) const;
|
||||
|
||||
/*! @brief Return real bytes count of this string
|
||||
/*! \brief Return real bytes count of this string
|
||||
* \details It`s equivalent length of char sequence
|
||||
* returned by function \a data() - 1, without terminating null-char \n
|
||||
* Example: \snippet pistring.cpp PIString::lengthAscii
|
||||
* \sa \a data() */
|
||||
int lengthAscii() const {buildData(__syslocname__); return data_.size_s() - 1;}
|
||||
|
||||
/*! @brief Return \c char * representation of this string in system codepage
|
||||
/*! \brief Return \c char * representation of this string in system codepage
|
||||
* \details This function fill buffer by sequence
|
||||
* of chars. Minimum length of this buffer is count
|
||||
* of symbols. Returned \c char * is valid until next
|
||||
@@ -429,7 +430,7 @@ public:
|
||||
* \sa \a dataConsole(), \a dataUTF8() */
|
||||
const char * data() const {buildData(__syslocname__); return (const char *)(data_.data());}
|
||||
|
||||
/*! @brief Return \c char * representation of this string in terminal codepage
|
||||
/*! \brief Return \c char * representation of this string in terminal codepage
|
||||
* \details This function fill buffer by sequence
|
||||
* of chars. Minimum length of this buffer is count
|
||||
* of symbols. Returned \c char * is valid until next
|
||||
@@ -437,7 +438,7 @@ public:
|
||||
* \sa \a data(), \a dataUTF8() */
|
||||
const char * dataConsole() const;
|
||||
|
||||
/*! @brief Return \c char * representation of this string in UTF-8
|
||||
/*! \brief Return \c char * representation of this string in UTF-8
|
||||
* \details This function fill buffer by sequence
|
||||
* of chars. Minimum length of this buffer is count
|
||||
* of symbols. Returned \c char * is valid until next
|
||||
@@ -445,7 +446,7 @@ public:
|
||||
* \sa \a data(), \a dataConsole() */
|
||||
const char * dataUTF8() const;
|
||||
|
||||
/*! @brief Return \c char * representation of this string in ASCII
|
||||
/*! \brief Return \c char * representation of this string in ASCII
|
||||
* \details This function fill buffer by sequence
|
||||
* of chars. Minimum length of this buffer is count
|
||||
* of symbols. Returned \c char * is valid until next
|
||||
@@ -455,277 +456,277 @@ public:
|
||||
//! Returns hash
|
||||
uint hash() const;
|
||||
|
||||
//! @brief Return \a PIByteArray contains \a data() of this string without terminating null-char
|
||||
//! \brief Return \a PIByteArray contains \a data() of this string without terminating null-char
|
||||
PIByteArray toByteArray() const {buildData(__utf8name__); return data_.resized(data_.size_s() - 1);}
|
||||
|
||||
//! @brief Return \a PIByteArray contains UTF-8 \a data() of this string without terminating null-char
|
||||
//! \brief Return \a PIByteArray contains UTF-8 \a data() of this string without terminating null-char
|
||||
PIByteArray toUTF8() const;
|
||||
|
||||
//! @brief Return \a PIByteArray contains custom charset representation of this string without terminating null-char
|
||||
//! \brief Return \a PIByteArray contains custom charset representation of this string without terminating null-char
|
||||
PIByteArray toCharset(const char * c) const;
|
||||
|
||||
/*! @brief Split string with delimiter "delim" to \a PIStringList and return it
|
||||
/*! \brief Split string with delimiter "delim" to \a PIStringList and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::split */
|
||||
PIStringList split(const PIString & delim) const;
|
||||
|
||||
|
||||
//! @brief Convert each symbol in copyed string to upper case and return it
|
||||
//! \brief Convert each symbol in copyed string to upper case and return it
|
||||
PIString toUpperCase() const;
|
||||
|
||||
//! @brief Convert each symbol in copyed string to lower case and return it
|
||||
//! \brief Convert each symbol in copyed string to lower case and return it
|
||||
PIString toLowerCase() const;
|
||||
|
||||
PIString toNativeDecimalPoints() const;
|
||||
|
||||
|
||||
//! @brief Returns if string contains "c"
|
||||
//! \brief Returns if string contains "c"
|
||||
bool contains(const char c) const {return PIDeque<PIChar>::contains(PIChar(c));}
|
||||
|
||||
//! @brief Returns if string contains "str"
|
||||
//! \brief Returns if string contains "str"
|
||||
bool contains(const char * str) const {return contains(PIString(str));}
|
||||
|
||||
//! @brief Returns if string contains "str"
|
||||
//! \brief Returns if string contains "str"
|
||||
bool contains(const PIString & str) const {return find(str) >= 0;}
|
||||
|
||||
|
||||
//! @brief Search symbol "c" from symbol at index "start" and return first occur position
|
||||
//! \brief Search symbol "c" from symbol at index "start" and return first occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::find
|
||||
int find(const char c, const int start = 0) const;
|
||||
|
||||
//! @brief Search substring "str" from symbol at index "start" and return first occur position
|
||||
//! \brief Search substring "str" from symbol at index "start" and return first occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::find
|
||||
int find(const PIString & str, const int start = 0) const;
|
||||
|
||||
//! @brief Search substring "str" from symbol at index "start" and return first occur position
|
||||
//! \brief Search substring "str" from symbol at index "start" and return first occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::find
|
||||
int find(const char * str, const int start = 0) const {return find(PIString(str), start);}
|
||||
|
||||
//! @brief Search symbol "c" from symbol at index "start" and return last occur position
|
||||
//! \brief Search symbol "c" from symbol at index "start" and return last occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findLast
|
||||
int findLast(const char c, const int start = 0) const;
|
||||
|
||||
//! @brief Search substring "str" from symbol at index "start" and return last occur position
|
||||
//! \brief Search substring "str" from symbol at index "start" and return last occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findLast
|
||||
int findLast(const PIString & str, const int start = 0) const;
|
||||
|
||||
//! @brief Search substring "str" from symbol at index "start" and return last occur position
|
||||
//! \brief Search substring "str" from symbol at index "start" and return last occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findLast
|
||||
int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);}
|
||||
|
||||
//! @brief Search word "word" from symbol at index "start" and return first occur position.
|
||||
//! \brief Search word "word" from symbol at index "start" and return first occur position.
|
||||
//! \details Example: \snippet pistring.cpp PIString::findWord
|
||||
int findWord(const PIString & word, const int start = 0) const;
|
||||
|
||||
//! @brief Search C-style word "word" from symbol at index "start" and return first occur position.
|
||||
//! \brief Search C-style word "word" from symbol at index "start" and return first occur position.
|
||||
//! \details Example: \snippet pistring.cpp PIString::findCWord
|
||||
int findCWord(const PIString & word, const int start = 0) const;
|
||||
|
||||
//! @brief Search range between "start" and "end" symbols at index "start_index" and return first occur position.
|
||||
//! \brief Search range between "start" and "end" symbols at index "start_index" and return first occur position.
|
||||
//! \details Example: \snippet pistring.cpp PIString::findRange
|
||||
int findRange(const PIChar start, const PIChar end, const PIChar shield = '\\', const int start_index = 0, int * len = 0) const;
|
||||
|
||||
//! @brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAny
|
||||
int findAny(const PIString & str, const int start = 0) const;
|
||||
|
||||
//! @brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAny
|
||||
int findAny(const char * str, const int start = 0) const {return findAny(PIString(str), start);}
|
||||
|
||||
//! @brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
|
||||
int findAnyLast(const PIString & str, const int start = 0) const;
|
||||
|
||||
//! @brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
|
||||
int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);}
|
||||
|
||||
//! @brief Returns number of occurrences of symbol "c"
|
||||
//! \brief Returns number of occurrences of symbol "c"
|
||||
int entries(const PIChar c) const;
|
||||
|
||||
//! @brief Returns number of occurrences of symbol "c"
|
||||
//! \brief Returns number of occurrences of symbol "c"
|
||||
int entries(char c) const {return entries(PIChar(c));}
|
||||
|
||||
//! @brief Return if string starts with "str"
|
||||
//! \brief Return if string starts with "str"
|
||||
bool startsWith(const PIString & str) const;
|
||||
|
||||
//! @brief Return if string ends with "str"
|
||||
//! \brief Return if string ends with "str"
|
||||
bool endsWith(const PIString & str) const;
|
||||
|
||||
//! @brief Return symbols length of string
|
||||
//! \brief Return symbols length of string
|
||||
int length() const {return size();}
|
||||
|
||||
//! @brief Return \c true if string is empty, i.e. length = 0
|
||||
//! \brief Return \c true if string is empty, i.e. length = 0
|
||||
bool isEmpty() const {return (size() == 0 || *this == "");}
|
||||
|
||||
|
||||
//! @brief Return \c true if string equal "true", "yes", "on" or positive not null numeric value
|
||||
//! \brief Return \c true if string equal "true", "yes", "on" or positive not null numeric value
|
||||
bool toBool() const;
|
||||
|
||||
//! @brief Return \c char numeric value of string
|
||||
//! \brief Return \c char numeric value of string
|
||||
char toChar() const;
|
||||
|
||||
//! @brief Return \c short numeric value of string in base "base"
|
||||
//! \brief Return \c short numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));}
|
||||
|
||||
//! @brief Return \c ushort numeric value of string in base "base"
|
||||
//! \brief Return \c ushort numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));}
|
||||
|
||||
//! @brief Return \c int numeric value of string in base "base"
|
||||
//! \brief Return \c int numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));}
|
||||
|
||||
//! @brief Return \c uint numeric value of string in base "base"
|
||||
//! \brief Return \c uint numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));}
|
||||
|
||||
//! @brief Return \c long numeric value of string in base "base"
|
||||
//! \brief Return \c long numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));}
|
||||
|
||||
//! @brief Return \c ulong numeric value of string in base "base"
|
||||
//! \brief Return \c ulong numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));}
|
||||
|
||||
//! @brief Return \c llong numeric value of string in base "base"
|
||||
//! \brief Return \c llong numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);}
|
||||
|
||||
//! @brief Return \c ullong numeric value of string in base "base"
|
||||
//! \brief Return \c ullong numeric value of string in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::toNumber
|
||||
ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));}
|
||||
|
||||
//! @brief Return \c float numeric value of string
|
||||
//! \brief Return \c float numeric value of string
|
||||
//! \details Example: \snippet pistring.cpp PIString::toFloat
|
||||
float toFloat() const;
|
||||
|
||||
//! @brief Return \c double numeric value of string
|
||||
//! \brief Return \c double numeric value of string
|
||||
//! \details Example: \snippet pistring.cpp PIString::toFloat
|
||||
double toDouble() const;
|
||||
|
||||
//! @brief Return \c ldouble numeric value of string
|
||||
//! \brief Return \c ldouble numeric value of string
|
||||
//! \details Example: \snippet pistring.cpp PIString::toFloat
|
||||
ldouble toLDouble() const;
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \brief Set string content to numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setNumber
|
||||
PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value"
|
||||
//! \brief Set string content to numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setFloat
|
||||
PIString & setNumber(const float value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value"
|
||||
//! \brief Set string content to numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setFloat
|
||||
PIString & setNumber(const double & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
|
||||
|
||||
//! @brief Set string content to numeric representation of "value"
|
||||
//! \brief Set string content to numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setFloat
|
||||
PIString & setNumber(const ldouble & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
|
||||
|
||||
//! @brief Set string content to human readable size in B/kB/MB/GB/TB
|
||||
//! \brief Set string content to human readable size in B/kB/MB/GB/TB
|
||||
//! \details Example: \snippet pistring.cpp PIString::setReadableSize
|
||||
PIString & setReadableSize(llong bytes);
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \brief Return string contains numeric representation of "value" in base "base"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromNumber
|
||||
static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value"
|
||||
//! \brief Return string contains numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromFloat
|
||||
static PIString fromNumber(const float value, char format = 'f', int precision = 8) {return ftos(value, format, precision);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value"
|
||||
//! \brief Return string contains numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromFloat
|
||||
static PIString fromNumber(const double & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
|
||||
|
||||
//! @brief Return string contains numeric representation of "value"
|
||||
//! \brief Return string contains numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromFloat
|
||||
static PIString fromNumber(const ldouble & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
|
||||
|
||||
//! @brief Return "true" or "false"
|
||||
//! \brief Return "true" or "false"
|
||||
static PIString fromBool(const bool value) {return PIString(value ? "true" : "false");}
|
||||
|
||||
//! @brief Return string constructed from terminal codepage
|
||||
//! \brief Return string constructed from terminal codepage
|
||||
static PIString fromConsole(const char * s);
|
||||
|
||||
//! @brief Return string constructed from system codepage
|
||||
//! \brief Return string constructed from system codepage
|
||||
static PIString fromSystem(const char * s);
|
||||
|
||||
//! @brief Return string constructed from UTF-8
|
||||
//! \brief Return string constructed from UTF-8
|
||||
static PIString fromUTF8(const char * s);
|
||||
|
||||
//! @brief Return string constructed from UTF-8
|
||||
//! \brief Return string constructed from UTF-8
|
||||
static PIString fromUTF8(const PIByteArray &ba);
|
||||
|
||||
//! @brief Return string constructed from ASCII
|
||||
//! \brief Return string constructed from ASCII
|
||||
static PIString fromAscii(const char * s);
|
||||
|
||||
//! @brief Return string constructed from "len" chars ASCII
|
||||
//! \brief Return string constructed from "len" chars ASCII
|
||||
static PIString fromAscii(const char * s, int len);
|
||||
|
||||
//! @brief Return string constructed from "c" codepage
|
||||
//! \brief Return string constructed from "c" codepage
|
||||
static PIString fromCodepage(const char * s, const char * c);
|
||||
|
||||
//! @brief Return string contains human readable size in B/kB/MB/GB/TB
|
||||
//! \brief Return string contains human readable size in B/kB/MB/GB/TB
|
||||
//! \details Example: \snippet pistring.cpp PIString::readableSize
|
||||
static PIString readableSize(llong bytes);
|
||||
|
||||
@@ -751,30 +752,30 @@ private:
|
||||
};
|
||||
|
||||
|
||||
//! \relatesalso PICout @brief Output operator to PICout
|
||||
//! \relatesalso PICout \brief Output operator to PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIString & v);
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray @brief Output operator to PIByteArray
|
||||
//! \relatesalso PIByteArray \brief Output operator to PIByteArray
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << *(PIDeque<PIChar>*)&v; return s;}
|
||||
|
||||
//! \relatesalso PIByteArray @brief Input operator from PIByteArray
|
||||
//! \relatesalso PIByteArray \brief Input operator from PIByteArray
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {v.clear(); s >> *(PIDeque<PIChar>*)&v; return s;}
|
||||
|
||||
|
||||
//! @brief Return concatenated string
|
||||
//! \brief Return concatenated string
|
||||
inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;}
|
||||
|
||||
//! @brief Return concatenated string
|
||||
//! \brief Return concatenated string
|
||||
inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;}
|
||||
|
||||
//! @brief Return concatenated string
|
||||
//! \brief Return concatenated string
|
||||
inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;}
|
||||
|
||||
//! \relatesalso PIString @brief Return concatenated string
|
||||
//! \relatesalso PIString \brief Return concatenated string
|
||||
inline PIString operator +(const char c, const PIString & f) {return PIChar(c) + f;}
|
||||
|
||||
//! @brief Return concatenated string
|
||||
//! \brief Return concatenated string
|
||||
inline PIString operator +(const PIString & f, const char c) {return f + PIChar(c);}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file pistring_std.h
|
||||
* @brief STD for PIString
|
||||
*
|
||||
* This file declare std operators and string conversions
|
||||
/*! \file pistring_std.h
|
||||
* \ingroup Core
|
||||
* \brief
|
||||
* \~english STD convertions for PIString
|
||||
* \~russian Преобразования в/из STD для строки
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -34,13 +35,13 @@
|
||||
|
||||
inline std::string PIString2StdString(const PIString & v) {
|
||||
std::string s;
|
||||
uint wc;
|
||||
ushort wc;
|
||||
uchar tc;
|
||||
if (v.size() > 0) {
|
||||
for (int i = 0; i < v.length(); ++i) {
|
||||
wc = uint(v.at(i).unicode16Code());
|
||||
wc = v[i].unicode16Code();
|
||||
while (tc = wc & 0xFF, tc) {
|
||||
s.push_back(char(tc));
|
||||
s.push_back(tc);
|
||||
wc >>= 8;
|
||||
}
|
||||
}
|
||||
@@ -48,46 +49,74 @@ inline std::string PIString2StdString(const PIString & v) {
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
inline PIString StdString2PIString(const std::string & v) {
|
||||
return PIString(v.c_str(), v.length());
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAS_LOCALE
|
||||
inline std::wstring PIString2StdWString(const PIString & v) {
|
||||
std::wstring s;
|
||||
for (int i = 0; i < v.length(); ++i)
|
||||
s.push_back(v.at(i).toWChar());
|
||||
for (int i = 0; i < v.length(); ++i) {
|
||||
s.push_back(v[i].toWChar());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
inline PIString StdWString2PIString(const std::wstring & v) {
|
||||
PIString s;
|
||||
uint l = v.size();
|
||||
for (uint i = 0; i < l; ++i) s.push_back(v[i]);
|
||||
for (uint i = 0; i < l; ++i) {
|
||||
s.push_back(PIChar(v[i]));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//! \relatesalso PIChar @brief Output operator to \c std::ostream
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;}
|
||||
|
||||
//! \relatesalso PIString @brief Return concatenated string
|
||||
inline PIString operator +(const PIString & f, const std::string & str) {PIString s(f); s += StdString2PIString(str); return s;}
|
||||
|
||||
//! \relatesalso PIString @brief Return concatenated string
|
||||
inline PIString operator +(const std::string & str, const PIString & f) {return StdString2PIString(str) + f;}
|
||||
//! \relatesalso PIChar \brief Output operator to \c std::ostream
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {
|
||||
s << v.toCharPtr();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIString @brief Output operator to std::ostream (cout)
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
|
||||
|
||||
//! \relatesalso PIString @brief Input operator from std::istream (cin)
|
||||
inline std::istream & operator >>(std::istream & s, PIString & v) {std::string ss; s >> ss; v = StdString2PIString(ss); return s;}
|
||||
//! \relatesalso PIString \brief Return concatenated string
|
||||
inline PIString operator +(const PIString & f, const std::string & str) {
|
||||
PIString s(f);
|
||||
s += StdString2PIString(str);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIStringList @brief Output operator to std::ostream (cout)
|
||||
//! \relatesalso PIString \brief Return concatenated string
|
||||
inline PIString operator +(const std::string & str, const PIString & f) {
|
||||
return StdString2PIString(str) + f;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIString \brief Output operator to std::ostream (cout)
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIString & v) {
|
||||
for (int i = 0; i < v.length(); ++i) {
|
||||
s << v[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIString \brief Input operator from std::istream (cin)
|
||||
inline std::istream & operator >>(std::istream & s, PIString & v) {
|
||||
std::string ss;
|
||||
s >> ss;
|
||||
v = StdString2PIString(ss);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \relatesalso PIStringList \brief Output operator to std::ostream (cout)
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) {
|
||||
s << PIChar("{");
|
||||
for (uint i = 0; i < v.size(); ++i) {
|
||||
|
||||
@@ -20,6 +20,52 @@
|
||||
#include "pistringlist.h"
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \~\class PIStringList pistringlist.h
|
||||
//! \~\brief
|
||||
//! \~english Based on \a PIDeque<PIString> strings list
|
||||
//! \~russian Основанный на \a PIDeque<PIString> массив строк
|
||||
//!
|
||||
//! \~\details
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english Example:
|
||||
//! \~russian Пример:
|
||||
//! \~\snippet pistring.cpp PIStringList::join
|
||||
PIString PIStringList::join(const PIString & delim) const {
|
||||
PIString s;
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
s += at(i);
|
||||
if (i < size() - 1)
|
||||
s += delim;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english Example:
|
||||
//! \~russian Пример:
|
||||
//! \~\snippet pistring.cpp PIStringList::removeStrings
|
||||
PIStringList & PIStringList::removeStrings(const PIString & value) {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
if (at(i) == value) {
|
||||
remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english Example:
|
||||
//! \~russian Пример:
|
||||
//! \~\snippet pistring.cpp PIStringList::removeDuplicates
|
||||
PIStringList& PIStringList::removeDuplicates() {
|
||||
PIStringList l;
|
||||
PIString s;
|
||||
@@ -40,3 +86,14 @@ PIStringList& PIStringList::removeDuplicates() {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english Example:
|
||||
//! \~russian Пример:
|
||||
//! \~\snippet pistring.cpp PIStringList::trim
|
||||
PIStringList & PIStringList::trim() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i].trim();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*! @brief Strings array class
|
||||
* \details This class is based on \a PIDeque<PIString> and
|
||||
* expand it functionality. */
|
||||
/*! \file pistringlist.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english Based on \a PIDeque<PIString> strings list
|
||||
* \~russian Основанный на \a PIDeque<PIString> массив строк
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Strings array class
|
||||
@@ -30,80 +33,108 @@ class PIP_EXPORT PIStringList: public PIDeque<PIString>
|
||||
{
|
||||
public:
|
||||
|
||||
//! Contructs empty strings list
|
||||
//! \~english Contructs an empty strings list
|
||||
//! \~russian Создает пустой список строк
|
||||
PIStringList() {;}
|
||||
|
||||
~PIStringList() {;}
|
||||
|
||||
//! Contructs strings list with one string "str"
|
||||
//! \~english Contructs strings list with one string "str"
|
||||
//! \~russian Создает список строк с одной строкой "str"
|
||||
PIStringList(const PIString & str) {push_back(str);}
|
||||
PIStringList(PIString && str) {push_back(std::move(str));}
|
||||
|
||||
//! Contructs empty strings list with strings "s0" and "s1"
|
||||
//! \~english Contructs strings list with strings "s0" and "s1"
|
||||
//! \~russian Создает список строк со строками "s0" и "s1"
|
||||
PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);}
|
||||
PIStringList(PIString && s0, PIString && s1) {push_back(std::move(s0)); push_back(std::move(s1));}
|
||||
|
||||
//! Contructs empty strings list with strings "s0", "s1" and "s2"
|
||||
//! \~english Contructs strings list with strings "s0", "s1" and "s2"
|
||||
//! \~russian Создает список строк со строками "s0", "s1" и "s2"
|
||||
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);}
|
||||
PIStringList(PIString && s0, PIString && s1, PIString && s2) {push_back(std::move(s0)); push_back(std::move(s1)); push_back(std::move(s2));}
|
||||
|
||||
//! Contructs empty strings list with strings "s0", "s1", "s2" and "s3"
|
||||
//! \~english Contructs strings list with strings "s0", "s1", "s2" and "s3"
|
||||
//! \~russian Создает список строк со строками "s0", "s1", "s2" и "s3"
|
||||
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);}
|
||||
PIStringList(PIString && s0, PIString && s1, PIString && s2, PIString && s3) {push_back(std::move(s0)); push_back(std::move(s1)); push_back(std::move(s2)); push_back(std::move(s3));}
|
||||
|
||||
//! \~english Contructs strings list with strings "o"
|
||||
//! \~russian Создает список строк со строками "o"
|
||||
PIStringList(const PIStringList & o): PIDeque<PIString>(o) {}
|
||||
PIStringList(PIStringList && o): PIDeque<PIString>(std::move(o)) {}
|
||||
|
||||
//! \~english Contructs strings list with strings "o"
|
||||
//! \~russian Создает список строк со строками "o"
|
||||
PIStringList(const PIVector<PIString> & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
|
||||
|
||||
//! \~english Contructs strings list with strings "o"
|
||||
//! \~russian Создает список строк со строками "o"
|
||||
PIStringList(const PIDeque<PIString> & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
|
||||
|
||||
//! Contructs strings list with std::initializer_list
|
||||
//! \~english Contructs strings list with strings "init_list" in std::initializer_list format
|
||||
//! \~russian Создает список строк со строками "init_list" в формате std::initializer_list
|
||||
PIStringList(std::initializer_list<PIString> init_list): PIDeque<PIString>(init_list) {}
|
||||
|
||||
|
||||
//! @brief Join all strings in one with delimiter "delim" and return it
|
||||
//! \details Example: \snippet pistring.cpp PIStringList::join
|
||||
PIString join(const PIString & delim) const {PIString s; for (uint i = 0; i < size(); ++i) {s += at(i); if (i < size() - 1) s += delim;} return s;}
|
||||
//! \~english Join all strings in one with delimiter "delim" and returns it
|
||||
//! \~russian Соединяет все строки в одну через разделитель "delim" и возвращает её
|
||||
PIString join(const PIString & delim) const;
|
||||
|
||||
//! @brief Remove all strings equal "value" and return this
|
||||
//! \details Example: \snippet pistring.cpp PIStringList::removeStrings
|
||||
PIStringList & removeStrings(const PIString & value) {for (uint i = 0; i < size(); ++i) {if (at(i) == value) {remove(i); --i;}} return *this;}
|
||||
//! \~english Remove all strings equal "value" and returns reference to this
|
||||
//! \~russian Удаляет все строки равные "value" и возвращает ссылку на этот список строк
|
||||
PIStringList & removeStrings(const PIString & value);
|
||||
|
||||
PIStringList & remove(uint num) {PIDeque<PIString>::remove(num); return *this;}
|
||||
PIStringList & remove(uint num, uint count) {PIDeque<PIString>::remove(num, count); return *this;}
|
||||
|
||||
//! @brief Remove duplicated strings and return this
|
||||
//! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates
|
||||
//! \~english Remove duplicated strings and returns reference to this
|
||||
//! \~russian Удаляет все дублированные строки и возвращает ссылку на этот список строк
|
||||
PIStringList & removeDuplicates();
|
||||
|
||||
//! @brief Trim all strings
|
||||
//! \details Example: \snippet pistring.cpp PIString::trim
|
||||
PIStringList & trim() {for (uint i = 0; i < size(); ++i) (*this)[i].trim(); return *this;}
|
||||
//! \~english Trim all strings and returns reference to this
|
||||
//! \~russian Подчищает у всех строк пробельные символы в начале и в конце и возвращает ссылку на этот список строк
|
||||
PIStringList & trim();
|
||||
|
||||
//! Return sum of lengths of all strings
|
||||
//! \~english Returns sum of lengths of all strings
|
||||
//! \~russian Возвращает сумму длин всех строк
|
||||
uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;}
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator ==(const PIStringList & o) const {if (size() != o.size()) return false; for (size_t i = 0; i < size(); ++i) if (o[i] != (*this)[i]) return false; return true;}
|
||||
|
||||
//! Compare operator
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator !=(const PIStringList & o) const {return !(o == (*this));}
|
||||
|
||||
//! \~english Assign operator
|
||||
//! \~russian Оператор присваивания
|
||||
PIStringList & operator =(const PIStringList & o) {PIDeque<PIString>::operator=(o); return *this;}
|
||||
|
||||
//! \~english Append string "str"
|
||||
//! \~russian Добавляет строку "str"
|
||||
PIStringList & operator <<(const PIString & str) {append(str); return *this;}
|
||||
PIStringList & operator <<(PIString && str) {append(std::move(str)); return *this;}
|
||||
|
||||
//! \~english Append strings list "sl"
|
||||
//! \~russian Добавляет список строк "sl"
|
||||
PIStringList & operator <<(const PIStringList & sl) {append(sl); return *this;}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! \relatesalso PIByteArray @brief Output operator to PIByteArray
|
||||
//! \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 PIByteArray @brief Input operator from PIByteArray
|
||||
//! \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 @brief Output operator to PICout
|
||||
//! \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;}
|
||||
|
||||
#endif // PISTRINGLIST_H
|
||||
|
||||
231
libs/main/core/pisystemtime.cpp
Normal file
231
libs/main/core/pisystemtime.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Unix time
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "pisystemtime.h"
|
||||
#include "pitime.h"
|
||||
#include <ctime>
|
||||
#ifdef QNX
|
||||
# include <time.h>
|
||||
#endif
|
||||
#ifndef MICRO_PIP
|
||||
# include "pisystemtests.h"
|
||||
#elif defined(ARDUINO)
|
||||
# include <Arduino.h>
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
extern FILETIME __pi_ftjan1970;
|
||||
long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
//# include <mach/mach_traps.h>
|
||||
//# include <mach/mach.h>
|
||||
# include <mach/clock.h>
|
||||
//# include <crt_externs.h>
|
||||
extern clock_serv_t __pi_mac_clock;
|
||||
#endif
|
||||
#ifdef MICRO_PIP
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \class PISystemTime pisystemtime.h
|
||||
//! \brief
|
||||
//! \~english System time with nanosecond precision
|
||||
//! \~russian Системное время с точностью до наносекунд
|
||||
//!
|
||||
//! \~english \section PISystemTime_sec0 Synopsis
|
||||
//! \~russian \section PISystemTime_sec0 Краткий обзор
|
||||
//! \~english
|
||||
//! This class provide arithmetic functions for POSIX system time.
|
||||
//! This time represents as seconds and nanosecons in integer formats.
|
||||
//! You can take current system time with function \a PISystemTime::current(),
|
||||
//! compare times, sum or subtract two times, convert time to/from
|
||||
//! seconds, milliseconds, microseconds or nanoseconds.
|
||||
//!
|
||||
//! \~russian
|
||||
//! Этот класс предоставляет арифметику для системного времени в формате POSIX.
|
||||
//! Это время представлено в виде целочисленных секунд и наносекунд.
|
||||
//! Можно взять текущее время с помощью метода \a PISystemTime::current(),
|
||||
//! сравнивать, суммировать и вычитать времена, преобразовывать в/из
|
||||
//! секунд, миллисекунд, микросекунд и наносекунд.
|
||||
//!
|
||||
//! \~english \section PISystemTime_sec1 Example
|
||||
//! \~russian \section PISystemTime_sec1 Пример
|
||||
//! \~\snippet pitimer.cpp system_time
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
//! \addtogroup Core
|
||||
//! \{
|
||||
//! \class PITimeMeasurer pisystemtime.h
|
||||
//! \brief
|
||||
//! \~english Time measurements
|
||||
//! \~russian Измерение времени
|
||||
//!
|
||||
//! \~english \section PITimeMeasurer_sec0 Usage
|
||||
//! \~russian \section PITimeMeasurer_sec0 Использование
|
||||
//! \~english
|
||||
//! Function \a reset() set time mark to current
|
||||
//! system time, then functions "double elapsed_*()" returns time elapsed from this mark.
|
||||
//! These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m"
|
||||
//! and "s"
|
||||
//!
|
||||
//! \~russian
|
||||
//! Метод \a reset() устанавливает текущую метку системного времени. Далее методы
|
||||
//! "double elapsed_*()" возвращают время, прошедшее от установленной метки.
|
||||
//! Эти методы возвращают нано, микро, милли и секунды с приставками
|
||||
//! "n", "u", "m" и "s".
|
||||
//!
|
||||
//! \}
|
||||
|
||||
|
||||
|
||||
|
||||
//! \details
|
||||
//! \warning
|
||||
//! \~english
|
||||
//! Use this function to sleep for difference of system times or constructs system time.
|
||||
//! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever
|
||||
//! \~russian
|
||||
//! Используйте этот метод для ожидания разниц системных времен или своего времени.
|
||||
//! Если метод будет вызван для системного времени \a PISystemTime::current(), то
|
||||
//! ожидание будет почти бесконечным
|
||||
void PISystemTime::sleep() {
|
||||
piUSleep(piFloord(toMicroseconds()));
|
||||
}
|
||||
|
||||
|
||||
void PISystemTime::toTimespec(void * ts) {
|
||||
#ifndef WINDOWS
|
||||
((timespec*)ts)->tv_sec = seconds;
|
||||
((timespec*)ts)->tv_nsec = nanoseconds;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PISystemTime::abs() const {
|
||||
if (seconds < 0)
|
||||
return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds));
|
||||
else
|
||||
return PISystemTime(piAbsl(seconds), piAbsl(nanoseconds));
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PISystemTime::current(bool precise_but_not_system) {
|
||||
#ifdef WINDOWS
|
||||
if (precise_but_not_system) {
|
||||
llong qpc(0);
|
||||
if (__pi_perf_freq > 0) {
|
||||
qpc = __PIQueryPerformanceCounter();
|
||||
return PISystemTime::fromSeconds(qpc / double(__pi_perf_freq));
|
||||
}
|
||||
return PISystemTime();
|
||||
} else {
|
||||
FILETIME ft, sft;
|
||||
# if (_WIN32_WINNT >= 0x0602)
|
||||
GetSystemTimePreciseAsFileTime(&ft);
|
||||
# else
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
# endif
|
||||
sft.dwHighDateTime = ft.dwHighDateTime - __pi_ftjan1970.dwHighDateTime;
|
||||
if (ft.dwLowDateTime < __pi_ftjan1970.dwLowDateTime) {
|
||||
sft.dwLowDateTime = ft.dwLowDateTime + (0xFFFFFFFF - __pi_ftjan1970.dwLowDateTime);
|
||||
sft.dwHighDateTime--;
|
||||
} else
|
||||
sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime;
|
||||
ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime);
|
||||
return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U);
|
||||
}
|
||||
#elif defined(MAC_OS)
|
||||
mach_timespec_t t_cur;
|
||||
clock_get_time(__pi_mac_clock, &t_cur);
|
||||
#elif defined(MICRO_PIP)
|
||||
timespec t_cur;
|
||||
# ifdef ARDUINO
|
||||
static const uint32_t offSetSinceEpoch_s = 1581897605UL;
|
||||
uint32_t mt = millis();
|
||||
t_cur.tv_sec = offSetSinceEpoch_s + (mt / 1000);
|
||||
t_cur.tv_nsec = (mt - (mt / 1000)) * 1000000UL;
|
||||
# else
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
gettimeofday(&tv, NULL);
|
||||
t_cur.tv_sec = tv.tv_sec;
|
||||
t_cur.tv_nsec = tv.tv_usec * 1000;
|
||||
# endif
|
||||
#else
|
||||
timespec t_cur;
|
||||
clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur);
|
||||
#endif
|
||||
#ifndef WINDOWS
|
||||
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
PITimeMeasurer::PITimeMeasurer() {
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_n() const {
|
||||
return (PISystemTime::current(true) - t_st).toNanoseconds()
|
||||
#ifndef MICRO_PIP
|
||||
- PISystemTests::time_elapsed_ns
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_u() const {
|
||||
return (PISystemTime::current(true) - t_st).toMicroseconds()
|
||||
#ifndef MICRO_PIP
|
||||
- PISystemTests::time_elapsed_ns / 1.E+3
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_m() const {
|
||||
return (PISystemTime::current(true) - t_st).toMilliseconds()
|
||||
#ifndef MICRO_PIP
|
||||
- PISystemTests::time_elapsed_ns / 1.E+6
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_s() const {
|
||||
return (PISystemTime::current(true) - t_st).toSeconds()
|
||||
#ifndef MICRO_PIP
|
||||
- PISystemTests::time_elapsed_ns / 1.E+9
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PITimeMeasurer::elapsed() const {
|
||||
return (PISystemTime::current(true) - t_st);
|
||||
}
|
||||
245
libs/main/core/pisystemtime.h
Normal file
245
libs/main/core/pisystemtime.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/*! \file pisystemtime.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english System time structs and methods
|
||||
* \~russian Типы и методы системного времени
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Time structs
|
||||
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 PISYSTEMTIME_H
|
||||
#define PISYSTEMTIME_H
|
||||
|
||||
|
||||
#include "pistring.h"
|
||||
|
||||
|
||||
class PIP_EXPORT PISystemTime {
|
||||
public:
|
||||
|
||||
//! \~english Contructs time with seconds and nanoseconds = 0
|
||||
//! \~russian Создает время с секундами и наносекундами = 0
|
||||
PISystemTime() {seconds = nanoseconds = 0;}
|
||||
|
||||
//! \~english Contructs time with "s" seconds and "ns" nanoseconds
|
||||
//! \~russian Создает время с секундами "s" и наносекундами "ns"
|
||||
PISystemTime(int s, int ns) {seconds = s; nanoseconds = ns; checkOverflows();}
|
||||
|
||||
|
||||
//! \~english Returns time value in seconds
|
||||
//! \~russian Возвращает значение времени в секундах
|
||||
double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;}
|
||||
|
||||
//! \~english Returns time value in milliseconds
|
||||
//! \~russian Возвращает значение времени в миллисекундах
|
||||
double toMilliseconds() const {return seconds * 1.e+3 + nanoseconds / 1.e+6;}
|
||||
|
||||
//! \~english Returns time value in microseconds
|
||||
//! \~russian Возвращает значение времени в микросекундах
|
||||
double toMicroseconds() const {return seconds * 1.e+6 + nanoseconds / 1.e+3;}
|
||||
|
||||
//! \~english Returns time value in nanoseconds
|
||||
//! \~russian Возвращает значение времени в наносекундах
|
||||
double toNanoseconds() const {return seconds * 1.e+9 + double(nanoseconds);}
|
||||
|
||||
|
||||
//! \~english Add to time "v" seconds
|
||||
//! \~russian Добавляет ко времени "v" секунд
|
||||
PISystemTime & addSeconds(double v) {*this += fromSeconds(v); return *this;}
|
||||
|
||||
//! \~english Add to time "v" milliseconds
|
||||
//! \~russian Добавляет ко времени "v" миллисекунд
|
||||
PISystemTime & addMilliseconds(double v) {*this += fromMilliseconds(v); return *this;}
|
||||
|
||||
//! \~english Add to time "v" microseconds
|
||||
//! \~russian Добавляет ко времени "v" микросекунд
|
||||
PISystemTime & addMicroseconds(double v) {*this += fromMicroseconds(v); return *this;}
|
||||
|
||||
//! \~english Add to time "v" nanoseconds
|
||||
//! \~russian Добавляет ко времени "v" наносекунд
|
||||
PISystemTime & addNanoseconds(double v) {*this += fromNanoseconds(v); return *this;}
|
||||
|
||||
|
||||
//! \~english Sleep for this time
|
||||
//! \~russian Ожидать это время
|
||||
void sleep();
|
||||
|
||||
//! \~english On *nix system assign current value to timespec struct
|
||||
//! \~russian На *nix системах присваивает время к timespec структуре
|
||||
void toTimespec(void * ts);
|
||||
|
||||
//! \~english Returns copy of this time with absolutely values of s and ns
|
||||
//! \~russian Возвращает копию времени с модулем значения
|
||||
PISystemTime abs() const;
|
||||
|
||||
//! \~english Returns sum of this time with "t"
|
||||
//! \~russian Возвращает сумму этого времени с "t"
|
||||
PISystemTime operator +(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds += t.seconds; tt.nanoseconds += t.nanoseconds; tt.checkOverflows(); return tt;}
|
||||
|
||||
//! \~english Returns difference between this time and "t"
|
||||
//! \~russian Возвращает разницу между этим временем и "t"
|
||||
PISystemTime operator -(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds -= t.seconds; tt.nanoseconds -= t.nanoseconds; tt.checkOverflows(); return tt;}
|
||||
|
||||
//! \~english Returns multiplication between this time and "t"
|
||||
//! \~russian Возвращает это временя умноженное на "t"
|
||||
PISystemTime operator *(const double & v) const {return fromMilliseconds(toMilliseconds() * v);}
|
||||
|
||||
//! \~english Returns division between this time and "t"
|
||||
//! \~russian Возвращает это временя поделённое на "t"
|
||||
PISystemTime operator /(const double & v) const {return fromMilliseconds(toMilliseconds() / v);}
|
||||
|
||||
//! \~english Add to time "t"
|
||||
//! \~russian Добавляет ко времени "t"
|
||||
PISystemTime & operator +=(const PISystemTime & t) {seconds += t.seconds; nanoseconds += t.nanoseconds; checkOverflows(); return *this;}
|
||||
|
||||
//! \~english Subtract from time "t"
|
||||
//! \~russian Вычитает из времени "t"
|
||||
PISystemTime & operator -=(const PISystemTime & t) {seconds -= t.seconds; nanoseconds -= t.nanoseconds; checkOverflows(); return *this;}
|
||||
|
||||
//! \~english Multiply time by "v"
|
||||
//! \~russian Умножает время на "v"
|
||||
PISystemTime & operator *=(const double & v) {*this = fromMilliseconds(toMilliseconds() * v); return *this;}
|
||||
|
||||
//! \~english Divide time by "v"
|
||||
//! \~russian Делит время на "v"
|
||||
PISystemTime & operator /=(const double & v) {*this = fromMilliseconds(toMilliseconds() / v); return *this;}
|
||||
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator ==(const PISystemTime & t) const {return ((seconds == t.seconds) && (nanoseconds == t.nanoseconds));}
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator !=(const PISystemTime & t) const {return ((seconds != t.seconds) || (nanoseconds != t.nanoseconds));}
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds > t.nanoseconds; return seconds > t.seconds;}
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds < t.nanoseconds; return seconds < t.seconds;}
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator >=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds >= t.nanoseconds; return seconds >= t.seconds;}
|
||||
|
||||
//! \~english Compare operator
|
||||
//! \~russian Оператор сравнения
|
||||
bool operator <=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds <= t.nanoseconds; return seconds <= t.seconds;}
|
||||
|
||||
|
||||
//! \~english Contructs time from seconds "v"
|
||||
//! \~russian Создает время из "v" секунд
|
||||
static PISystemTime fromSeconds(double v) {int s = piFloord(v); return PISystemTime(s, int((v - s) * 1000000000.));}
|
||||
|
||||
//! \~english Contructs time from milliseconds "v"
|
||||
//! \~russian Создает время из "v" миллисекунд
|
||||
static PISystemTime fromMilliseconds(double v) {int s = piFloord(v / 1000.); return PISystemTime(s, int((v / 1000. - s) * 1000000000.));}
|
||||
|
||||
//! \~english Contructs time from microseconds "v"
|
||||
//! \~russian Создает время из "v" микросекунд
|
||||
static PISystemTime fromMicroseconds(double v) {int s = piFloord(v / 1000000.); return PISystemTime(s, int((v / 1000000. - s) * 1000000000.));}
|
||||
|
||||
//! \~english Contructs time from nanoseconds "v"
|
||||
//! \~russian Создает время из "v" наносекунд
|
||||
static PISystemTime fromNanoseconds(double v) {int s = piFloord(v / 1000000000.); return PISystemTime(s, int((v / 1000000000. - s) * 1000000000.));}
|
||||
|
||||
//! \~english Returns current system time
|
||||
//! \~russian Возвращает текущее системное время
|
||||
static PISystemTime current(bool precise_but_not_system = false);
|
||||
|
||||
//! \~english Seconds time part
|
||||
//! \~russian Секунды времени
|
||||
int seconds;
|
||||
|
||||
//! \~english Nanoseconds time part
|
||||
//! \~russian Наносекунды времени
|
||||
int nanoseconds;
|
||||
|
||||
private:
|
||||
void checkOverflows() {while (nanoseconds >= 1000000000) {nanoseconds -= 1000000000; seconds++;} while (nanoseconds < 0) {nanoseconds += 1000000000; seconds--;}}
|
||||
|
||||
};
|
||||
|
||||
//! \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;}
|
||||
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT PITimeMeasurer {
|
||||
public:
|
||||
PITimeMeasurer();
|
||||
|
||||
/** \brief Set internal time mark to current system time
|
||||
* \details This function used for set start time mark. Later
|
||||
* you can find out elapsed time from this time mark to any
|
||||
* moment of time with \a elapsed_s(), \a elapsed_m(),
|
||||
* \a elapsed_u() or \a elapsed_n() functions.
|
||||
* \sa \a elapsed_s(), \a elapsed_m(), \a elapsed_u(), \a elapsed_n() */
|
||||
void reset() {t_st = PISystemTime::current(true);}
|
||||
|
||||
//! \brief Returns nanoseconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_n() const;
|
||||
|
||||
//! \brief Returns microseconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_u() const;
|
||||
|
||||
//! \brief Returns milliseconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_m() const;
|
||||
|
||||
//! \brief Returns seconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_s() const;
|
||||
|
||||
//! \brief Returns PISystemTime elapsed from last \a reset() execution or from timer measurer creation.
|
||||
PISystemTime elapsed() const;
|
||||
|
||||
double reset_time_n() const {return t_st.toNanoseconds();}
|
||||
double reset_time_u() const {return t_st.toMicroseconds();}
|
||||
double reset_time_m() const {return t_st.toMilliseconds();}
|
||||
double reset_time_s() const {return t_st.toSeconds();}
|
||||
|
||||
//! \brief Returns time mark of last \a reset() execution or timer measurer creation.
|
||||
PISystemTime reset_time() {return t_st;}
|
||||
|
||||
//! \brief Returns nanoseconds representation of current system time.
|
||||
static double elapsed_system_n() {return PISystemTime::current(true).toNanoseconds();}
|
||||
|
||||
//! \brief Returns microseconds representation of current system time.
|
||||
static double elapsed_system_u() {return PISystemTime::current(true).toMicroseconds();}
|
||||
|
||||
//! \brief Returns milliseconds representation of current system time.
|
||||
static double elapsed_system_m() {return PISystemTime::current(true).toMilliseconds();}
|
||||
|
||||
//! \brief Returns seconds representation of current system time.
|
||||
static double elapsed_system_s() {return PISystemTime::current(true).toSeconds();}
|
||||
|
||||
//! \brief Returns time mark of current system time.
|
||||
static PISystemTime elapsed_system() {return PISystemTime::current(true);}
|
||||
|
||||
private:
|
||||
PISystemTime t_st, t_cur;
|
||||
|
||||
};
|
||||
|
||||
#endif // PITIME_H
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Timer
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -19,48 +18,32 @@
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "pitime.h"
|
||||
#include "pisystemtests.h"
|
||||
#ifdef WINDOWS
|
||||
extern FILETIME __pi_ftjan1970;
|
||||
long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
|
||||
#ifdef QNX
|
||||
# include <time.h>
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
//# include <mach/mach_traps.h>
|
||||
//# include <mach/mach.h>
|
||||
# include <mach/clock.h>
|
||||
//# include <crt_externs.h>
|
||||
extern clock_serv_t __pi_mac_clock;
|
||||
#ifndef MICRO_PIP
|
||||
# include "pisystemtests.h"
|
||||
#elif defined(ARDUINO)
|
||||
# include <Arduino.h>
|
||||
#endif
|
||||
#ifdef FREERTOS
|
||||
# include "freertos/FreeRTOS.h"
|
||||
# include "freertos/task.h"
|
||||
#ifdef MICRO_PIP
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/*! \class PISystemTime
|
||||
* @brief System time
|
||||
*
|
||||
* \section PISystemTime_sec0 Synopsis
|
||||
* This class provide arithmetic functions for POSIX system time.
|
||||
* This time represents as seconds and nanosecons in integer formats.
|
||||
* You can take current system time with function \a PISystemTime::current(),
|
||||
* compare times, sum or subtract two times, convert time to/from
|
||||
* seconds, milliseconds, microseconds or nanoseconds.
|
||||
* \section PISystemTime_sec1 Example
|
||||
* \snippet pitimer.cpp system_time
|
||||
*/
|
||||
|
||||
|
||||
/*! \class PITimeMeasurer
|
||||
* @brief Time measurements
|
||||
*
|
||||
* \section PITimeMeasurer_sec0 Synopsis
|
||||
* Function \a reset() set time mark to current
|
||||
* system time, then functions double elapsed_*() returns time elapsed from this mark.
|
||||
* These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m"
|
||||
* and "s"
|
||||
*/
|
||||
|
||||
|
||||
//! \details
|
||||
//! \~english
|
||||
//! This function consider \c "usleep" offset
|
||||
//! on QNX/Linux/Mac, which is calculated with
|
||||
//! \a pip_sys_test program. If this is correct
|
||||
//! offset value in system config, this function
|
||||
//! wait \b exactly "usecs" microseconds.
|
||||
//! \~russian
|
||||
//! Этот метод учитывает смещение \c "usleep"
|
||||
//! на QNX/Linux/Mac, которое расчитывается с помощью
|
||||
//! утилиты \a pip_sys_test. Если это значение в системном
|
||||
//! конфиге действительно, то этот метод будет ожидать
|
||||
//! \b точно "usecs" микросекунд.
|
||||
void piUSleep(int usecs) {
|
||||
if (usecs <= 0) return;
|
||||
#ifdef WINDOWS
|
||||
@@ -76,406 +59,3 @@ void piUSleep(int usecs) {
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool operator ==(const PITime & t0, const PITime & t1) {
|
||||
return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
|
||||
}
|
||||
|
||||
|
||||
bool operator <(const PITime & t0, const PITime & t1) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds < t1.seconds;
|
||||
} else return t0.minutes < t1.minutes;
|
||||
} else return t0.hours < t1.hours;
|
||||
}
|
||||
|
||||
|
||||
bool operator >(const PITime & t0, const PITime & t1) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds > t1.seconds;
|
||||
} else return t0.minutes > t1.minutes;
|
||||
} else return t0.hours > t1.hours;
|
||||
}
|
||||
|
||||
bool operator ==(const PIDate & t0, const PIDate & t1) {
|
||||
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day);
|
||||
}
|
||||
|
||||
|
||||
bool operator <(const PIDate & t0, const PIDate & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
return t0.day < t1.day;
|
||||
} else return t0.month < t1.month;
|
||||
} else return t0.year < t1.year;
|
||||
}
|
||||
|
||||
|
||||
bool operator >(const PIDate & t0, const PIDate & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
return t0.day > t1.day;
|
||||
} else return t0.month > t1.month;
|
||||
} else return t0.year > t1.year;
|
||||
}
|
||||
|
||||
bool operator ==(const PIDateTime & t0, const PIDateTime & t1) {
|
||||
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day &&
|
||||
t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
|
||||
}
|
||||
|
||||
|
||||
bool operator <(const PIDateTime & t0, const PIDateTime & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
if (t0.day == t1.day) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds < t1.seconds;
|
||||
} else return t0.minutes < t1.minutes;
|
||||
} else return t0.hours < t1.hours;
|
||||
} else return t0.day < t1.day;
|
||||
} else return t0.month < t1.month;
|
||||
} else return t0.year < t1.year;
|
||||
}
|
||||
|
||||
|
||||
bool operator >(const PIDateTime & t0, const PIDateTime & t1) {
|
||||
if (t0.year == t1.year) {
|
||||
if (t0.month == t1.month) {
|
||||
if (t0.day == t1.day) {
|
||||
if (t0.hours == t1.hours) {
|
||||
if (t0.minutes == t1.minutes) {
|
||||
return t0.seconds > t1.seconds;
|
||||
} else return t0.minutes > t1.minutes;
|
||||
} else return t0.hours > t1.hours;
|
||||
} else return t0.day > t1.day;
|
||||
} else return t0.month > t1.month;
|
||||
} else return t0.year > t1.year;
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PITime::toSystemTime() const {
|
||||
return PISystemTime((hours * 60. + minutes) * 60. + seconds, milliseconds * 1000.);
|
||||
}
|
||||
|
||||
|
||||
PITime PITime::current() {
|
||||
time_t rt = ::time(0);
|
||||
tm * pt = localtime(&rt);
|
||||
PITime t;
|
||||
t.seconds = pt->tm_sec;
|
||||
t.minutes = pt->tm_min;
|
||||
t.hours = pt->tm_hour;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
PITime PITime::fromSystemTime(const PISystemTime & st) {
|
||||
double s = st.toSeconds();
|
||||
int v = s;
|
||||
PITime ret;
|
||||
ret.milliseconds = (s - v) * 1000;
|
||||
ret.seconds = v % 60; v = (v - ret.seconds) / 60;
|
||||
ret.minutes = v % 60; v = (v - ret.minutes) / 60;
|
||||
ret.hours = v;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIDate PIDate::current() {
|
||||
time_t rt = ::time(0);
|
||||
tm * pt = localtime(&rt);
|
||||
PIDate d;
|
||||
d.day = pt->tm_mday;
|
||||
d.month = pt->tm_mon + 1;
|
||||
d.year = pt->tm_year + 1900;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
PIDateTime PIDateTime::current() {
|
||||
time_t rt = ::time(0);
|
||||
tm * pt = localtime(&rt);
|
||||
PIDateTime dt;
|
||||
dt.milliseconds = 0;
|
||||
dt.seconds = pt->tm_sec;
|
||||
dt.minutes = pt->tm_min;
|
||||
dt.hours = pt->tm_hour;
|
||||
dt.day = pt->tm_mday;
|
||||
dt.month = pt->tm_mon + 1;
|
||||
dt.year = pt->tm_year + 1900;
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
void PISystemTime::toTimespec(void * ts) {
|
||||
#ifndef WINDOWS
|
||||
((timespec*)ts)->tv_sec = seconds;
|
||||
((timespec*)ts)->tv_nsec = nanoseconds;
|
||||
#endif
|
||||
}
|
||||
|
||||
PISystemTime PISystemTime::abs() const {
|
||||
if (seconds < 0)
|
||||
return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds));
|
||||
else
|
||||
return PISystemTime(piAbsl(seconds), piAbsl(nanoseconds));
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PISystemTime::current(bool precise_but_not_system) {
|
||||
#ifdef WINDOWS
|
||||
if (precise_but_not_system) {
|
||||
llong qpc(0);
|
||||
if (__pi_perf_freq > 0) {
|
||||
qpc = __PIQueryPerformanceCounter();
|
||||
return PISystemTime::fromSeconds(qpc / double(__pi_perf_freq));
|
||||
}
|
||||
return PISystemTime();
|
||||
} else {
|
||||
FILETIME ft, sft;
|
||||
# if (_WIN32_WINNT >= 0x0602)
|
||||
GetSystemTimePreciseAsFileTime(&ft);
|
||||
# else
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
# endif
|
||||
sft.dwHighDateTime = ft.dwHighDateTime - __pi_ftjan1970.dwHighDateTime;
|
||||
if (ft.dwLowDateTime < __pi_ftjan1970.dwLowDateTime) {
|
||||
sft.dwLowDateTime = ft.dwLowDateTime + (0xFFFFFFFF - __pi_ftjan1970.dwLowDateTime);
|
||||
sft.dwHighDateTime--;
|
||||
} else
|
||||
sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime;
|
||||
ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime);
|
||||
return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U);
|
||||
}
|
||||
#else
|
||||
# ifdef MAC_OS
|
||||
mach_timespec_t t_cur;
|
||||
clock_get_time(__pi_mac_clock, &t_cur);
|
||||
# else
|
||||
# ifdef FREERTOS
|
||||
timespec t_cur;
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
gettimeofday(&tv, NULL);
|
||||
t_cur.tv_sec = tv.tv_sec;
|
||||
t_cur.tv_nsec = tv.tv_usec * 1000;
|
||||
# else
|
||||
timespec t_cur;
|
||||
clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur);
|
||||
# endif
|
||||
# endif
|
||||
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PIString PITime::toString(const PIString & format) const {
|
||||
PIString ts = format;
|
||||
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(hours));
|
||||
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(minutes));
|
||||
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(seconds));
|
||||
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
|
||||
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
|
||||
ts.replace("z", PIString::fromNumber(milliseconds));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString PIDate::toString(const PIString & format) const {
|
||||
PIString ts = format;
|
||||
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(month));
|
||||
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(day));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString PIDateTime::toString(const PIString & format) const {
|
||||
PIString ts = format;
|
||||
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(month));
|
||||
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(day));
|
||||
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(hours));
|
||||
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(minutes));
|
||||
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(seconds));
|
||||
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
|
||||
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
|
||||
ts.replace("z", PIString::fromNumber(milliseconds));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
time_t PIDateTime::toSecondSinceEpoch() const {
|
||||
tm pt;
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
pt.tm_sec = seconds;
|
||||
pt.tm_min = minutes;
|
||||
pt.tm_hour = hours;
|
||||
pt.tm_mday = day;
|
||||
pt.tm_mon = month - 1;
|
||||
#ifdef WINDOWS
|
||||
pt.tm_year = piMaxi(year - 1900, 70);
|
||||
#else
|
||||
pt.tm_year = piMaxi(year - 1900, 0);
|
||||
#endif
|
||||
return mktime(&pt);
|
||||
}
|
||||
|
||||
|
||||
PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) {
|
||||
tm * pt = localtime(&sec);
|
||||
PIDateTime dt;
|
||||
dt.seconds = pt->tm_sec;
|
||||
dt.minutes = pt->tm_min;
|
||||
dt.hours = pt->tm_hour;
|
||||
dt.day = pt->tm_mday;
|
||||
dt.month = pt->tm_mon + 1;
|
||||
dt.year = pt->tm_year + 1900;
|
||||
return dt;
|
||||
|
||||
}
|
||||
|
||||
|
||||
PIString time2string(const PITime & time, const PIString & format) {
|
||||
PIString ts = format;
|
||||
ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(time.hours));
|
||||
ts.replace("mm", PIString::fromNumber(time.minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(time.minutes));
|
||||
ts.replace("ss", PIString::fromNumber(time.seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(time.seconds));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString date2string(const PIDate & date, const PIString & format) {
|
||||
PIString ts = format;
|
||||
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(date.year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(date.year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(date.month));
|
||||
ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(date.day));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
PIString datetime2string(const PIDateTime & date, const PIString & format) {
|
||||
PIString ts = format;
|
||||
ts.replace("hh", PIString::fromNumber(date.hours).expandLeftTo(2, '0'));
|
||||
ts.replace("h", PIString::fromNumber(date.hours));
|
||||
ts.replace("mm", PIString::fromNumber(date.minutes).expandLeftTo(2, '0'));
|
||||
ts.replace("m", PIString::fromNumber(date.minutes));
|
||||
ts.replace("ss", PIString::fromNumber(date.seconds).expandLeftTo(2, '0'));
|
||||
ts.replace("s", PIString::fromNumber(date.seconds));
|
||||
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
|
||||
ts.replace("yy", PIString::fromNumber(date.year).right(2));
|
||||
ts.replace("y", PIString::fromNumber(date.year).right(1));
|
||||
ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
|
||||
ts.replace("M", PIString::fromNumber(date.month));
|
||||
ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
|
||||
ts.replace("d", PIString::fromNumber(date.day));
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PITimeMeasurer::PITimeMeasurer() {
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_n() const {
|
||||
return (PISystemTime::current(true) - t_st).toNanoseconds() - PISystemTests::time_elapsed_ns;
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_u() const {
|
||||
return (PISystemTime::current(true) - t_st).toMicroseconds() - PISystemTests::time_elapsed_ns / 1.E+3;
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_m() const {
|
||||
return (PISystemTime::current(true) - t_st).toMilliseconds() - PISystemTests::time_elapsed_ns / 1.E+6;
|
||||
}
|
||||
|
||||
|
||||
double PITimeMeasurer::elapsed_s() const {
|
||||
return (PISystemTime::current(true) - t_st).toSeconds() - PISystemTests::time_elapsed_ns / 1.E+9;
|
||||
}
|
||||
|
||||
|
||||
PISystemTime PITimeMeasurer::elapsed() const {
|
||||
return (PISystemTime::current(true) - t_st);
|
||||
}
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PITime & v) {
|
||||
s.space();
|
||||
s.setControl(0, true);
|
||||
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();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PIDate & v) {
|
||||
s.space();
|
||||
s.setControl(0, true);
|
||||
s << "PIDate(" << v.day << "-";
|
||||
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
|
||||
s << v.year << ")";
|
||||
s.restoreControl();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PIDateTime & v) {
|
||||
s.space();
|
||||
s.setControl(0, true);
|
||||
s << "PIDateTime(";
|
||||
s << v.day << "-";
|
||||
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
|
||||
s << v.year << " ";
|
||||
s << 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();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WINDOWS
|
||||
void msleep(int msecs) {Sleep(msecs);}
|
||||
#else
|
||||
# ifdef FREERTOS
|
||||
void msleep(int msecs) {vTaskDelay(msecs / portTICK_PERIOD_MS);}
|
||||
# else
|
||||
void msleep(int msecs) {usleep(msecs * 1000);}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/*! @file pitime.h
|
||||
* @brief Time structs
|
||||
/*! \file pitime.h
|
||||
* \ingroup Core
|
||||
* \~\brief
|
||||
* \~english System time, time and date
|
||||
* \~russian Системное время, время и дата
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Time structs
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -23,300 +25,34 @@
|
||||
#ifndef PITIME_H
|
||||
#define PITIME_H
|
||||
|
||||
#include "pidatetime.h"
|
||||
|
||||
#include "pistring.h"
|
||||
#include <ctime>
|
||||
#ifdef QNX
|
||||
# include <time.h>
|
||||
#endif
|
||||
//! @brief Sleep for "msecs" milliseconds
|
||||
PIP_EXPORT void msleep(int msecs);
|
||||
|
||||
/*! @brief Precise sleep for "usecs" microseconds
|
||||
* \details This function consider \c "usleep" offset
|
||||
* on QNX/Linux/Mac, which is calculated with
|
||||
* \a pip_sys_test program. If there is correct
|
||||
* offset value in system config, this function
|
||||
* wait \b exactly "usecs" microseconds. */
|
||||
//! \ingroup Core
|
||||
//! \~english Precise sleep for "usecs" microseconds
|
||||
//! \~russian Точно ожидает "usecs" микросекунд
|
||||
PIP_EXPORT void piUSleep(int usecs); // on !Windows consider constant "usleep" offset
|
||||
|
||||
/*! @brief Precise sleep for "msecs" milliseconds
|
||||
* \details This function exec \a piUSleep (msecs * 1000). */
|
||||
//! \ingroup Core
|
||||
//! \brief
|
||||
//! \~english Precise sleep for "msecs" milliseconds
|
||||
//! \~russian Точно ожидает "msecs" миллисекунд
|
||||
//! \~\details
|
||||
//! \~english This function exec \a piUSleep (msecs * 1000)
|
||||
//! \~russian Этот метод вызывает \a piUSleep (msecs * 1000)
|
||||
inline void piMSleep(double msecs) {piUSleep(int(msecs * 1000.));} // on !Windows consider constant "usleep" offset
|
||||
|
||||
/*! @brief Precise sleep for "secs" seconds
|
||||
* \details This function exec \a piUSleep (msecs * 1000000). */
|
||||
//! \ingroup Core
|
||||
//! \brief
|
||||
//! \~english Precise sleep for "secs" seconds
|
||||
//! \~russian Точно ожидает "secs" секунд
|
||||
//! \~\details
|
||||
//! \~english This function exec \a piUSleep (msecs * 1000000)
|
||||
//! \~russian Этот метод вызывает \a piUSleep (msecs * 1000000)
|
||||
inline void piSleep(double secs) {piUSleep(int(secs * 1000000.));} // on !Windows consider constant "usleep" offset
|
||||
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT PISystemTime {
|
||||
public:
|
||||
|
||||
//! Contructs system time with s = ns = 0
|
||||
PISystemTime() {seconds = nanoseconds = 0;}
|
||||
|
||||
//! Contructs system time with s = "s" and ns = "ns"
|
||||
PISystemTime(int s, int ns) {seconds = s; nanoseconds = ns; checkOverflows();}
|
||||
|
||||
|
||||
//! Returns stored system time value in seconds
|
||||
double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;}
|
||||
|
||||
//! Returns stored system time value in milliseconds
|
||||
double toMilliseconds() const {return seconds * 1.e+3 + nanoseconds / 1.e+6;}
|
||||
|
||||
//! Returns stored system time value in microseconds
|
||||
double toMicroseconds() const {return seconds * 1.e+6 + nanoseconds / 1.e+3;}
|
||||
|
||||
//! Returns stored system time value in nanoseconds
|
||||
double toNanoseconds() const {return seconds * 1.e+9 + double(nanoseconds);}
|
||||
|
||||
|
||||
//! Add to stored system time "v" seconds
|
||||
PISystemTime & addSeconds(double v) {*this += fromSeconds(v); return *this;}
|
||||
|
||||
//! Add to stored system time "v" milliseconds
|
||||
PISystemTime & addMilliseconds(double v) {*this += fromMilliseconds(v); return *this;}
|
||||
|
||||
//! Add to stored system time "v" microseconds
|
||||
PISystemTime & addMicroseconds(double v) {*this += fromMicroseconds(v); return *this;}
|
||||
|
||||
//! Add to stored system time "v" nanoseconds
|
||||
PISystemTime & addNanoseconds(double v) {*this += fromNanoseconds(v); return *this;}
|
||||
|
||||
|
||||
//! Sleep for stored value. \warning Use this function to sleep for difference of system times or constructs system time.
|
||||
//! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever.
|
||||
void sleep() {piUSleep(piFloord(toMicroseconds()));} // wait self value, useful to wait some dT = (t1 - t0)
|
||||
|
||||
//! On Unix system assign current value to timespec struct
|
||||
void toTimespec(void *ts);
|
||||
|
||||
//! Returns copy of this system time with absolutely values of s and ns
|
||||
PISystemTime abs() const;
|
||||
|
||||
//! Returns sum of this system time with "t"
|
||||
PISystemTime operator +(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds += t.seconds; tt.nanoseconds += t.nanoseconds; tt.checkOverflows(); return tt;}
|
||||
|
||||
//! Returns difference between this system time and "t"
|
||||
PISystemTime operator -(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds -= t.seconds; tt.nanoseconds -= t.nanoseconds; tt.checkOverflows(); return tt;}
|
||||
|
||||
//! Returns multiplication between this system time and "t"
|
||||
PISystemTime operator *(const double & v) const {return fromMilliseconds(toMilliseconds() * v);}
|
||||
|
||||
//! Returns division between this system time and "t"
|
||||
PISystemTime operator /(const double & v) const {return fromMilliseconds(toMilliseconds() / v);}
|
||||
|
||||
//! Add to stored value system time "t"
|
||||
PISystemTime & operator +=(const PISystemTime & t) {seconds += t.seconds; nanoseconds += t.nanoseconds; checkOverflows(); return *this;}
|
||||
|
||||
//! Subtract from stored value system time "t"
|
||||
PISystemTime & operator -=(const PISystemTime & t) {seconds -= t.seconds; nanoseconds -= t.nanoseconds; checkOverflows(); return *this;}
|
||||
|
||||
//! Multiply stored value system time by "v"
|
||||
PISystemTime & operator *=(const double & v) {*this = fromMilliseconds(toMilliseconds() * v); return *this;}
|
||||
|
||||
//! Divide stored value system time by "v"
|
||||
PISystemTime & operator /=(const double & v) {*this = fromMilliseconds(toMilliseconds() / v); return *this;}
|
||||
|
||||
|
||||
//! Compare system times
|
||||
bool operator ==(const PISystemTime & t) const {return ((seconds == t.seconds) && (nanoseconds == t.nanoseconds));}
|
||||
|
||||
//! Compare system times
|
||||
bool operator !=(const PISystemTime & t) const {return ((seconds != t.seconds) || (nanoseconds != t.nanoseconds));}
|
||||
|
||||
//! Compare system times
|
||||
bool operator >(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds > t.nanoseconds; return seconds > t.seconds;}
|
||||
|
||||
//! Compare system times
|
||||
bool operator <(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds < t.nanoseconds; return seconds < t.seconds;}
|
||||
|
||||
//! Compare system times
|
||||
bool operator >=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds >= t.nanoseconds; return seconds >= t.seconds;}
|
||||
|
||||
//! Compare system times
|
||||
bool operator <=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds <= t.nanoseconds; return seconds <= t.seconds;}
|
||||
|
||||
|
||||
//! Contructs system time from seconds "v"
|
||||
static PISystemTime fromSeconds(double v) {int s = piFloord(v); return PISystemTime(s, int((v - s) * 1000000000.));}
|
||||
|
||||
//! Contructs system time from milliseconds "v"
|
||||
static PISystemTime fromMilliseconds(double v) {int s = piFloord(v / 1000.); return PISystemTime(s, int((v / 1000. - s) * 1000000000.));}
|
||||
|
||||
//! Contructs system time from microseconds "v"
|
||||
static PISystemTime fromMicroseconds(double v) {int s = piFloord(v / 1000000.); return PISystemTime(s, int((v / 1000000. - s) * 1000000000.));}
|
||||
|
||||
//! Contructs system time from nanoseconds "v"
|
||||
static PISystemTime fromNanoseconds(double v) {int s = piFloord(v / 1000000000.); return PISystemTime(s, int((v / 1000000000. - s) * 1000000000.));}
|
||||
|
||||
//! Returns current system time
|
||||
static PISystemTime current(bool precise_but_not_system = false);
|
||||
|
||||
//! Seconds of stored system time
|
||||
int seconds;
|
||||
|
||||
//! Nanoseconds of stored system time
|
||||
int nanoseconds;
|
||||
|
||||
private:
|
||||
void checkOverflows() {while (nanoseconds >= 1000000000) {nanoseconds -= 1000000000; seconds++;} while (nanoseconds < 0) {nanoseconds += 1000000000; seconds--;}}
|
||||
|
||||
};
|
||||
|
||||
//! \relatesalso PICout @brief Output operator to 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;}
|
||||
|
||||
|
||||
|
||||
struct PIP_EXPORT PITime {
|
||||
PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;}
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
int milliseconds;
|
||||
PIString toString(const PIString & format = "h:mm:ss") const;
|
||||
PISystemTime toSystemTime() const;
|
||||
static PITime current();
|
||||
static PITime fromSystemTime(const PISystemTime & st);
|
||||
};
|
||||
|
||||
PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1);
|
||||
PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1);
|
||||
PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1);
|
||||
inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);}
|
||||
|
||||
//! \relatesalso PICout @brief Output operator to PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PITime & v);
|
||||
|
||||
|
||||
|
||||
|
||||
struct PIP_EXPORT PIDate {
|
||||
PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;}
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
PIString toString(const PIString & format = "d.MM.yyyy") const;
|
||||
static PIDate current();
|
||||
};
|
||||
|
||||
PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1);
|
||||
PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1);
|
||||
PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1);
|
||||
inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);}
|
||||
|
||||
//! \relatesalso PICout @brief Output operator to PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIDate & v);
|
||||
|
||||
|
||||
|
||||
|
||||
struct PIP_EXPORT PIDateTime {
|
||||
PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;}
|
||||
PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
|
||||
PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;}
|
||||
PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
int milliseconds;
|
||||
PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());}
|
||||
void normalize() {*this = normalized();}
|
||||
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const;
|
||||
time_t toSecondSinceEpoch() const;
|
||||
PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);}
|
||||
PIDate date() const {return PIDate(year, month, day);}
|
||||
PITime time() const {return PITime(hours, minutes, seconds, milliseconds);}
|
||||
void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;}
|
||||
void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;}
|
||||
void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();}
|
||||
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
|
||||
static PIDateTime fromSecondSinceEpoch(const time_t sec);
|
||||
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
|
||||
static PIDateTime current();
|
||||
};
|
||||
|
||||
inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();}
|
||||
inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();}
|
||||
PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1);
|
||||
PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1);
|
||||
PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1);
|
||||
inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);}
|
||||
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
|
||||
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDateTime & v) {s << v.year << v.month << v.day << v.hours << v.minutes << v.seconds << v.milliseconds; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDateTime & v) {s >> v.year >> v.month >> v.day >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;}
|
||||
|
||||
//! \relatesalso PICout @brief Output operator to PICout
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIDateTime & v);
|
||||
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT PITimeMeasurer {
|
||||
public:
|
||||
PITimeMeasurer();
|
||||
|
||||
/** @brief Set internal time mark to current system time
|
||||
* \details This function used for set start time mark. Later
|
||||
* you can find out elapsed time from this time mark to any
|
||||
* moment of time with \a elapsed_s(), \a elapsed_m(),
|
||||
* \a elapsed_u() or \a elapsed_n() functions.
|
||||
* \sa \a elapsed_s(), \a elapsed_m(), \a elapsed_u(), \a elapsed_n() */
|
||||
void reset() {t_st = PISystemTime::current(true);}
|
||||
|
||||
//! @brief Returns nanoseconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_n() const;
|
||||
|
||||
//! @brief Returns microseconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_u() const;
|
||||
|
||||
//! @brief Returns milliseconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_m() const;
|
||||
|
||||
//! @brief Returns seconds elapsed from last \a reset() execution or from timer measurer creation.
|
||||
double elapsed_s() const;
|
||||
|
||||
//! @brief Returns PISystemTime elapsed from last \a reset() execution or from timer measurer creation.
|
||||
PISystemTime elapsed() const;
|
||||
|
||||
double reset_time_n() const {return t_st.toNanoseconds();}
|
||||
double reset_time_u() const {return t_st.toMicroseconds();}
|
||||
double reset_time_m() const {return t_st.toMilliseconds();}
|
||||
double reset_time_s() const {return t_st.toSeconds();}
|
||||
|
||||
//! @brief Returns time mark of last \a reset() execution or timer measurer creation.
|
||||
PISystemTime reset_time() {return t_st;}
|
||||
|
||||
//! @brief Returns nanoseconds representation of current system time.
|
||||
static double elapsed_system_n() {return PISystemTime::current(true).toNanoseconds();}
|
||||
|
||||
//! @brief Returns microseconds representation of current system time.
|
||||
static double elapsed_system_u() {return PISystemTime::current(true).toMicroseconds();}
|
||||
|
||||
//! @brief Returns milliseconds representation of current system time.
|
||||
static double elapsed_system_m() {return PISystemTime::current(true).toMilliseconds();}
|
||||
|
||||
//! @brief Returns seconds representation of current system time.
|
||||
static double elapsed_system_s() {return PISystemTime::current(true).toSeconds();}
|
||||
|
||||
//! @brief Returns time mark of current system time.
|
||||
static PISystemTime elapsed_system() {return PISystemTime::current(true);}
|
||||
|
||||
private:
|
||||
PISystemTime t_st, t_cur;
|
||||
|
||||
};
|
||||
//! \ingroup Core
|
||||
//! \~english Shortest available on current system sleep
|
||||
//! \~russian Наименее возможное для данной системы по длительности ожидание
|
||||
inline void piMinSleep() {piMSleep(PIP_MIN_MSLEEP);}
|
||||
|
||||
#endif // PITIME_H
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file pitime_win.h
|
||||
* @brief PITime conversions for Windows
|
||||
*
|
||||
* This file declare time conversions for Windows
|
||||
/*! \file pitime_win.h
|
||||
* \ingroup Core
|
||||
* \brief
|
||||
* \~english PITime conversions for Windows
|
||||
* \~russian Преобразования PITime для Windows
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
/** \class PIVariant
|
||||
* @brief Variant type
|
||||
* \brief Variant type
|
||||
* \details
|
||||
* \section PIVariant_sec0 Synopsis
|
||||
* This class provides general type that can contains all standard types, some
|
||||
@@ -220,7 +220,7 @@ PIString PIVariant::typeName(PIVariant::Type type) {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as boolean
|
||||
/** \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,
|
||||
@@ -251,7 +251,7 @@ bool PIVariant::toBool() const {
|
||||
|
||||
|
||||
|
||||
/** @brief Returns variant content as int
|
||||
/** \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,
|
||||
@@ -283,7 +283,7 @@ int PIVariant::toInt() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as long long
|
||||
/** \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,
|
||||
@@ -314,7 +314,7 @@ llong PIVariant::toLLong() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as float
|
||||
/** \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,
|
||||
@@ -345,7 +345,7 @@ float PIVariant::toFloat() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as double
|
||||
/** \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,
|
||||
@@ -376,7 +376,7 @@ double PIVariant::toDouble() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as long double
|
||||
/** \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,
|
||||
@@ -407,7 +407,7 @@ ldouble PIVariant::toLDouble() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as time
|
||||
/** \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(). */
|
||||
@@ -420,7 +420,7 @@ PITime PIVariant::toTime() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as date
|
||||
/** \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(). */
|
||||
@@ -433,7 +433,7 @@ PIDate PIVariant::toDate() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as date and time
|
||||
/** \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
|
||||
@@ -448,7 +448,7 @@ PIDateTime PIVariant::toDateTime() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as system time
|
||||
/** \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. */
|
||||
@@ -460,7 +460,7 @@ PISystemTime PIVariant::toSystemTime() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as string
|
||||
/** \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
|
||||
@@ -501,7 +501,7 @@ PIString PIVariant::toString() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as strings list
|
||||
/** \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. */
|
||||
PIStringList PIVariant::toStringList() const {
|
||||
@@ -513,7 +513,7 @@ PIStringList PIVariant::toStringList() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as bit array
|
||||
/** \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. */
|
||||
PIBitArray PIVariant::toBitArray() const {
|
||||
@@ -524,7 +524,7 @@ PIBitArray PIVariant::toBitArray() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as byte array
|
||||
/** \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. */
|
||||
PIByteArray PIVariant::toByteArray() const {
|
||||
@@ -535,7 +535,7 @@ PIByteArray PIVariant::toByteArray() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as enum
|
||||
/** \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
|
||||
@@ -550,7 +550,7 @@ PIVariantTypes::Enum PIVariant::toEnum() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as file
|
||||
/** \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. */
|
||||
@@ -563,7 +563,7 @@ PIVariantTypes::File PIVariant::toFile() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as dir
|
||||
/** \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. */
|
||||
@@ -576,7 +576,7 @@ PIVariantTypes::Dir PIVariant::toDir() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as color
|
||||
/** \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. */
|
||||
@@ -589,7 +589,7 @@ PIVariantTypes::Color PIVariant::toColor() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as IODevice
|
||||
/** \brief Returns variant content as IODevice
|
||||
* \details In case of IODevice type returns IODevice value. \n
|
||||
* In case of other types returns empty IODevice. */
|
||||
PIVariantTypes::IODevice PIVariant::toIODevice() const {
|
||||
@@ -599,7 +599,7 @@ PIVariantTypes::IODevice PIVariant::toIODevice() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as point
|
||||
/** \brief Returns variant content as point
|
||||
* \details In case of PIPointd type returns point value. \n
|
||||
* In case of other types returns empty PIPointd. */
|
||||
PIPointd PIVariant::toPoint() const {
|
||||
@@ -609,7 +609,7 @@ PIPointd PIVariant::toPoint() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as rect
|
||||
/** \brief Returns variant content as rect
|
||||
* \details In case of PIRectd type returns rect value. \n
|
||||
* In case of other types returns empty PIRectd. */
|
||||
PIRectd PIVariant::toRect() const {
|
||||
@@ -619,7 +619,17 @@ PIRectd PIVariant::toRect() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as math vector
|
||||
/** \brief Returns variant content as line
|
||||
* \details In case of PILined type returns line value. \n
|
||||
* In case of other types returns empty PILined. */
|
||||
PILined PIVariant::toLine() const {
|
||||
PIByteArray ba(_content);
|
||||
if (_type == PIVariant::pivLine) {PILined r; ba >> r; return r;}
|
||||
return PILined();
|
||||
}
|
||||
|
||||
|
||||
/** \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. */
|
||||
PIMathVectord PIVariant::toMathVector() const {
|
||||
@@ -629,7 +639,7 @@ PIMathVectord PIVariant::toMathVector() const {
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns variant content as math matrix
|
||||
/** \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. */
|
||||
PIMathMatrixd PIVariant::toMathMatrix() const {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file pivariant.h
|
||||
* @brief Variant type
|
||||
*
|
||||
* This file declares PIVariant
|
||||
/*! \file pivariant.h
|
||||
* \ingroup Core
|
||||
* \brief
|
||||
* \~english Variant type
|
||||
* \~russian Вариативный тип
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -234,11 +235,12 @@ public:
|
||||
pivFile /** PIVariantTypes::File */ ,
|
||||
pivDir /** PIVariantTypes::Dir */ ,
|
||||
pivColor /** PIVariantTypes::Color */ ,
|
||||
pivPoint /** PIPoint */ ,
|
||||
pivRect /** PIRect */ ,
|
||||
pivPoint /** PIPoint<double> */ ,
|
||||
pivRect /** PIRect<double> */ ,
|
||||
pivIODevice /** PIVariantTypes::IODevice */ ,
|
||||
pivMathVector /** PIMathVectord */ ,
|
||||
pivMathMatrix /** PIMathMatrixd */ ,
|
||||
pivMathVector /** PIMathVector<double> */ ,
|
||||
pivMathMatrix /** PIMathMatrix<double> */ ,
|
||||
pivLine /** PILine<double> */ ,
|
||||
pivCustom /** Custom */ = 0xFF
|
||||
};
|
||||
|
||||
@@ -333,6 +335,9 @@ public:
|
||||
//! Constructs variant from rect
|
||||
PIVariant(const PIRectd & v) {initType(v);}
|
||||
|
||||
//! Constructs variant from line
|
||||
PIVariant(const PILined & v) {initType(v);}
|
||||
|
||||
//! Constructs variant from MathVector
|
||||
PIVariant(const PIMathVectord & v) {initType(v);}
|
||||
|
||||
@@ -424,6 +429,9 @@ public:
|
||||
//! Set variant content and type to rect
|
||||
void setValue(const PIRectd & v) {initType(v);}
|
||||
|
||||
//! Set variant content and type to line
|
||||
void setValue(const PILined & v) {initType(v);}
|
||||
|
||||
//! Set variant content and type to math vector
|
||||
void setValue(const PIMathVectord & v) {initType(v);}
|
||||
|
||||
@@ -456,11 +464,12 @@ public:
|
||||
PIVariantTypes::IODevice toIODevice() const;
|
||||
PIPointd toPoint() const;
|
||||
PIRectd toRect() const;
|
||||
PILined toLine() const;
|
||||
PIMathVectord toMathVector() const;
|
||||
PIMathMatrixd toMathMatrix() const;
|
||||
|
||||
|
||||
/** @brief Returns variant content as custom type
|
||||
/** \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. */
|
||||
template<typename T>
|
||||
@@ -527,6 +536,8 @@ public:
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIRectd & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PILined & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIMathVectord & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIMathMatrixd & v) {setValue(v); return *this;}
|
||||
@@ -551,7 +562,7 @@ public:
|
||||
void swap(PIVariant & v);
|
||||
|
||||
|
||||
/** @brief Returns new variant from custom type
|
||||
/** \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. */
|
||||
template <typename T>
|
||||
@@ -661,6 +672,7 @@ template<> inline PIVariantTypes::Color PIVariant::value() const {return toColor
|
||||
template<> inline PIVariantTypes::IODevice PIVariant::value() const {return toIODevice();}
|
||||
template<> inline PIPointd PIVariant::value() const {return toPoint();}
|
||||
template<> inline PIRectd PIVariant::value() const {return toRect();}
|
||||
template<> inline PILined PIVariant::value() const {return toLine();}
|
||||
template<> inline PIVariant PIVariant::value() const {return *this;}
|
||||
|
||||
template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);}
|
||||
@@ -690,6 +702,7 @@ template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::Color & v
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::IODevice & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIPointd & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIRectd & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PILined & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIMathVectord & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIMathMatrixd & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIVariant & v) {return PIVariant(v);}
|
||||
@@ -721,6 +734,7 @@ template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::Color>() {r
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::IODevice>() {return PIVariant::pivIODevice;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIPointd>() {return PIVariant::pivPoint;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIRectd>() {return PIVariant::pivRect;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PILined>() {return PIVariant::pivLine;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIMathVectord>() {return PIVariant::pivMathVector;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIMathMatrixd>() {return PIVariant::pivMathMatrix;}
|
||||
|
||||
@@ -751,6 +765,7 @@ REGISTER_NS_VARIANT(PIVariantTypes, Color)
|
||||
REGISTER_NS_VARIANT(PIVariantTypes, IODevice)
|
||||
REGISTER_VARIANT(PIPointd)
|
||||
REGISTER_VARIANT(PIRectd)
|
||||
REGISTER_VARIANT(PILined)
|
||||
REGISTER_VARIANT(PIMathVectord)
|
||||
REGISTER_VARIANT(PIMathMatrixd)
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file pivariantsimple.h
|
||||
* @brief Variant simple type
|
||||
*
|
||||
* This file declares PIVariantSimple
|
||||
/*! \file pivariantsimple.h
|
||||
* \ingroup Core
|
||||
* \brief
|
||||
* \~english Variant simple type
|
||||
* \~russian Простой вариативный тип
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -27,7 +28,7 @@
|
||||
|
||||
#include "pistring.h"
|
||||
#include <typeinfo>
|
||||
#ifdef PIP_FREERTOS
|
||||
#ifdef MICRO_PIP
|
||||
#include "pivariant.h"
|
||||
#endif
|
||||
|
||||
@@ -48,7 +49,7 @@ template<typename T>
|
||||
class __VariantFunctions__: public __VariantFunctionsBase__ {
|
||||
public:
|
||||
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<T> ret; return &ret;}
|
||||
#ifdef PIP_FREERTOS
|
||||
#ifdef MICRO_PIP
|
||||
PIString typeName() const final {static PIString ret(PIVariant(T()).typeName()); return ret;}
|
||||
#else
|
||||
PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;}
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
|
||||
#include "pivarianttypes.h"
|
||||
#include "pipropertystorage.h"
|
||||
#include "piiodevice.h"
|
||||
|
||||
#ifndef MICRO_PIP
|
||||
# include "piiodevice.h"
|
||||
#endif
|
||||
|
||||
int PIVariantTypes::Enum::selectedValue() const {
|
||||
piForeachC (Enumerator & e, enum_list)
|
||||
@@ -83,9 +84,12 @@ PIStringList PIVariantTypes::Enum::names() const {
|
||||
|
||||
|
||||
|
||||
|
||||
PIVariantTypes::IODevice::IODevice() {
|
||||
#ifndef MICRO_PIP
|
||||
mode = PIIODevice::ReadWrite;
|
||||
#else
|
||||
mode = 0; // TODO: PIIODevice for MICRO PIP
|
||||
#endif // MICRO_PIP
|
||||
options = 0;
|
||||
}
|
||||
|
||||
@@ -112,12 +116,14 @@ PIString PIVariantTypes::IODevice::toPICout() const {
|
||||
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";
|
||||
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite])
|
||||
s << " bw";
|
||||
}
|
||||
#endif // MICRO_PIP
|
||||
PIPropertyStorage ps = get();
|
||||
piForeachC (PIPropertyStorage::Property & p, ps) {
|
||||
s << ", " << p.name << "=\"" << p.value.toString() << "\"";
|
||||
@@ -128,7 +134,6 @@ PIString PIVariantTypes::IODevice::toPICout() const {
|
||||
|
||||
|
||||
|
||||
|
||||
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIVariantTypes::Enumerator & v) {
|
||||
enum_list << v;
|
||||
return *this;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*! @file pivarianttypes.h
|
||||
* @brief Variant type
|
||||
*
|
||||
* This file declares PIVariant
|
||||
/*! \file pivarianttypes.h
|
||||
* \ingroup Core
|
||||
* \brief
|
||||
* \~english Types for PIVariant
|
||||
* \~russian Типы для PIVariant
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -34,7 +35,7 @@ class PIPropertyStorage;
|
||||
namespace PIVariantTypes {
|
||||
|
||||
/**
|
||||
* @brief name-value pair
|
||||
* \brief name-value pair
|
||||
*/
|
||||
struct PIP_EXPORT Enumerator {
|
||||
Enumerator(int v = 0, const PIString & n = PIString()): value(v), name(n) {}
|
||||
@@ -43,26 +44,26 @@ struct PIP_EXPORT Enumerator {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Collection of PIVariantTypes::Enumerator. It's replace classic c-style enum.
|
||||
* \brief Collection of PIVariantTypes::Enumerator. It's replace classic c-style enum.
|
||||
* Contains elements with unique name and not uniqueue values.
|
||||
*/
|
||||
struct PIP_EXPORT Enum {
|
||||
Enum(const PIString & n = PIString()): enum_name(n) {}
|
||||
|
||||
/**
|
||||
* @brief Find selected value.
|
||||
* \brief Find selected value.
|
||||
* @return selected value, otherwrise 0
|
||||
*/
|
||||
int selectedValue() const;
|
||||
|
||||
/**
|
||||
* @brief Get selected name
|
||||
* \brief Get selected name
|
||||
* @return selected name, otherwrise empty PIString
|
||||
*/
|
||||
PIString selectedName() const {return selected;}
|
||||
|
||||
/**
|
||||
* @brief Select value if exists in Enum. If Enum contains several PIVariantTypes::Enumerator with same values,
|
||||
* \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
|
||||
@@ -70,55 +71,61 @@ struct PIP_EXPORT Enum {
|
||||
bool selectValue(int v);
|
||||
|
||||
/**
|
||||
* @brief Select name if exists in enum
|
||||
* \brief Select name if exists in enum
|
||||
* @param n name for selection
|
||||
* @return true if name exists in Enum, false otherwrise
|
||||
*/
|
||||
bool selectName(const PIString & n);
|
||||
|
||||
/**
|
||||
* @brief Find PIVariantTypes::Enumerator with specific name and return it value
|
||||
* \brief Find PIVariantTypes::Enumerator with specific name and return it value
|
||||
* @param n name for search
|
||||
* @return value of founded PIVariantTypes::Enumerator, 0 otherwrise
|
||||
*/
|
||||
int value(const PIString & n) const;
|
||||
|
||||
/**
|
||||
* @brief Find first PIVariantTypes::Enumerator with specific value and return it name
|
||||
* \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
|
||||
*/
|
||||
PIString name(int v) const;
|
||||
|
||||
/**
|
||||
* @brief Make vector of Enum values
|
||||
* \brief Make vector of Enum values
|
||||
*/
|
||||
PIVector<int> values() const;
|
||||
|
||||
/**
|
||||
* @brief Make vector of Enum names
|
||||
* \brief Make vector of Enum names
|
||||
*/
|
||||
PIStringList names() const;
|
||||
PIString enum_name;
|
||||
PIString selected;
|
||||
PIVector<Enumerator> enum_list;
|
||||
|
||||
/**
|
||||
* @brief Add PIVariantTypes::Enumerator to Enum
|
||||
* \brief Add PIVariantTypes::Enumerator to Enum
|
||||
*/
|
||||
Enum & operator <<(const Enumerator & v);
|
||||
|
||||
/**
|
||||
* @brief Add PIVariantTypes::Enumerator element to Enum. Element contains specific name and value more per
|
||||
* \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
|
||||
*/
|
||||
Enum & operator <<(const PIString & v);
|
||||
|
||||
/**
|
||||
* @brief Add PIVariantTypes::Enumerator element for each name in vector
|
||||
* \brief Add PIVariantTypes::Enumerator element for each name in vector
|
||||
*/
|
||||
Enum & operator <<(const PIStringList & v);
|
||||
|
||||
/**
|
||||
* \brief Return true if Enum is empty
|
||||
*/
|
||||
bool isEmpty() const {return enum_list.isEmpty();}
|
||||
|
||||
PIString enum_name;
|
||||
PIString selected;
|
||||
PIVector<Enumerator> enum_list;
|
||||
};
|
||||
|
||||
struct PIP_EXPORT File {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file piauth.h
|
||||
* @brief PIP Authentication API
|
||||
/*! \file piauth.h
|
||||
* \brief PIP Authentication API
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*! @file picrypt.h
|
||||
* @brief Cryptographic class using lib Sodium
|
||||
/*! \file picrypt.h
|
||||
* \brief Cryptographic class using lib Sodium
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
@@ -58,6 +58,9 @@ public:
|
||||
//! Generate hash from bytearray
|
||||
static PIByteArray hash(const PIByteArray & data);
|
||||
|
||||
//! Generate hash from bytearray
|
||||
static PIByteArray hash(const PIByteArray & data, const unsigned char * key, size_t keylen);
|
||||
|
||||
//! Returns hash size
|
||||
static size_t sizeHash();
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user