Compare commits
3 Commits
960e4a7cce
...
pimap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e85b11a233 | ||
|
|
831adf3fc9 | ||
|
|
a18f461ce3 |
224
.clang-format
224
.clang-format
@@ -1,224 +0,0 @@
|
|||||||
---
|
|
||||||
Language: Cpp
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
AlignAfterOpenBracket: Align
|
|
||||||
AlignArrayOfStructures: Left
|
|
||||||
AlignConsecutiveAssignments:
|
|
||||||
Enabled: true
|
|
||||||
AcrossEmptyLines: true
|
|
||||||
AcrossComments: true
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: true
|
|
||||||
AlignConsecutiveBitFields:
|
|
||||||
Enabled: true
|
|
||||||
AcrossEmptyLines: false
|
|
||||||
AcrossComments: true
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: true
|
|
||||||
AlignConsecutiveDeclarations:
|
|
||||||
Enabled: false
|
|
||||||
AcrossEmptyLines: false
|
|
||||||
AcrossComments: false
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: false
|
|
||||||
AlignConsecutiveMacros:
|
|
||||||
Enabled: true
|
|
||||||
AcrossEmptyLines: true
|
|
||||||
AcrossComments: true
|
|
||||||
AlignCompound: false
|
|
||||||
PadOperators: true
|
|
||||||
AlignEscapedNewlines: Left
|
|
||||||
AlignOperands: Align
|
|
||||||
AlignTrailingComments: true
|
|
||||||
AllowAllArgumentsOnNextLine: false
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
|
||||||
AllowShortEnumsOnASingleLine: false
|
|
||||||
AllowShortBlocksOnASingleLine: Empty
|
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
|
||||||
AllowShortFunctionsOnASingleLine: Inline
|
|
||||||
AllowShortLambdasOnASingleLine: All
|
|
||||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
AlwaysBreakAfterReturnType: None
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
|
||||||
AttributeMacros:
|
|
||||||
- __capability
|
|
||||||
BinPackArguments: false
|
|
||||||
BinPackParameters: false
|
|
||||||
BraceWrapping:
|
|
||||||
AfterCaseLabel: false
|
|
||||||
AfterClass: false
|
|
||||||
AfterControlStatement: Never
|
|
||||||
AfterEnum: false
|
|
||||||
AfterFunction: false
|
|
||||||
AfterNamespace: false
|
|
||||||
AfterObjCDeclaration: false
|
|
||||||
AfterStruct: false
|
|
||||||
AfterUnion: false
|
|
||||||
AfterExternBlock: false
|
|
||||||
BeforeCatch: false
|
|
||||||
BeforeElse: false
|
|
||||||
BeforeLambdaBody: false
|
|
||||||
BeforeWhile: false
|
|
||||||
IndentBraces: false
|
|
||||||
SplitEmptyFunction: false
|
|
||||||
SplitEmptyRecord: false
|
|
||||||
SplitEmptyNamespace: true
|
|
||||||
BreakBeforeBinaryOperators: None
|
|
||||||
BreakBeforeConceptDeclarations: Always
|
|
||||||
BreakBeforeBraces: Attach
|
|
||||||
BreakInheritanceList: BeforeComma
|
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializers: BeforeComma
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
|
||||||
BreakStringLiterals: true
|
|
||||||
ColumnLimit: 140
|
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
|
||||||
QualifierAlignment: Leave
|
|
||||||
CompactNamespaces: false
|
|
||||||
ConstructorInitializerIndentWidth: 4
|
|
||||||
ContinuationIndentWidth: 4
|
|
||||||
Cpp11BracedListStyle: true
|
|
||||||
DeriveLineEnding: false
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
DisableFormat: false
|
|
||||||
EmptyLineAfterAccessModifier: Never
|
|
||||||
EmptyLineBeforeAccessModifier: Always
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
PackConstructorInitializers: CurrentLine
|
|
||||||
BasedOnStyle: ''
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
||||||
AllowAllConstructorInitializersOnNextLine: true
|
|
||||||
FixNamespaceComments: true
|
|
||||||
ForEachMacros:
|
|
||||||
- foreach
|
|
||||||
- Q_FOREACH
|
|
||||||
- BOOST_FOREACH
|
|
||||||
- piForeach
|
|
||||||
- piForeachC
|
|
||||||
- piForeachR
|
|
||||||
- piForeachRC
|
|
||||||
- piForeachCR
|
|
||||||
IfMacros:
|
|
||||||
- KJ_IF_MAYBE
|
|
||||||
IncludeBlocks: Regroup
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
|
||||||
Priority: 2
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
|
||||||
Priority: 3
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
- Regex: '.*'
|
|
||||||
Priority: 1
|
|
||||||
SortPriority: 0
|
|
||||||
CaseSensitive: false
|
|
||||||
IncludeIsMainRegex: '(Test)?$'
|
|
||||||
IncludeIsMainSourceRegex: ''
|
|
||||||
IndentAccessModifiers: false
|
|
||||||
IndentCaseLabels: false
|
|
||||||
IndentCaseBlocks: false
|
|
||||||
IndentGotoLabels: false
|
|
||||||
IndentPPDirectives: AfterHash
|
|
||||||
IndentExternBlock: NoIndent
|
|
||||||
IndentRequiresClause: true
|
|
||||||
IndentWidth: 4
|
|
||||||
IndentWrappedFunctionNames: false
|
|
||||||
InsertBraces: false
|
|
||||||
InsertTrailingCommas: Wrapped
|
|
||||||
JavaScriptQuotes: Leave
|
|
||||||
JavaScriptWrapImports: true
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
||||||
LambdaBodyIndentation: Signature
|
|
||||||
MacroBlockBegin: "PRIVATE_DEFINITION_START|STATIC_INITIALIZER_BEGIN"
|
|
||||||
MacroBlockEnd: "PRIVATE_DEFINITION_END|STATIC_INITIALIZER_END"
|
|
||||||
MaxEmptyLinesToKeep: 2
|
|
||||||
NamespaceIndentation: None
|
|
||||||
ObjCBinPackProtocolList: Auto
|
|
||||||
ObjCBlockIndentWidth: 2
|
|
||||||
ObjCBreakBeforeNestedBlockParam: true
|
|
||||||
ObjCSpaceAfterProperty: false
|
|
||||||
ObjCSpaceBeforeProtocolList: true
|
|
||||||
PenaltyBreakAssignment: 2
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 19
|
|
||||||
PenaltyBreakComment: 300
|
|
||||||
PenaltyBreakFirstLessLess: 120
|
|
||||||
PenaltyBreakOpenParenthesis: 0
|
|
||||||
PenaltyBreakString: 1000
|
|
||||||
PenaltyBreakTemplateDeclaration: 10
|
|
||||||
PenaltyExcessCharacter: 1000000
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
|
||||||
PenaltyIndentedWhitespace: 0
|
|
||||||
PointerAlignment: Middle
|
|
||||||
PPIndentWidth: 2
|
|
||||||
ReferenceAlignment: Middle
|
|
||||||
ReflowComments: true
|
|
||||||
RemoveBracesLLVM: false
|
|
||||||
RequiresClausePosition: OwnLine
|
|
||||||
SeparateDefinitionBlocks: Leave
|
|
||||||
ShortNamespaceLines: 1
|
|
||||||
SortIncludes: CaseSensitive
|
|
||||||
SortJavaStaticImport: Before
|
|
||||||
SortUsingDeclarations: true
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceAfterLogicalNot: false
|
|
||||||
SpaceAfterTemplateKeyword: false
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
SpaceBeforeCaseColon: false
|
|
||||||
SpaceBeforeCpp11BracedList: false
|
|
||||||
SpaceBeforeCtorInitializerColon: false
|
|
||||||
SpaceBeforeInheritanceColon: false
|
|
||||||
SpaceBeforeParens: ControlStatementsExceptControlMacros
|
|
||||||
SpaceBeforeParensOptions:
|
|
||||||
AfterControlStatements: true
|
|
||||||
AfterForeachMacros: false
|
|
||||||
AfterFunctionDefinitionName: false
|
|
||||||
AfterFunctionDeclarationName: false
|
|
||||||
AfterIfMacros: false
|
|
||||||
AfterOverloadedOperator: false
|
|
||||||
AfterRequiresInClause: false
|
|
||||||
AfterRequiresInExpression: false
|
|
||||||
BeforeNonEmptyParentheses: false
|
|
||||||
SpaceAroundPointerQualifiers: Both
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: false
|
|
||||||
SpaceInEmptyBlock: false
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
||||||
SpacesInAngles: Never
|
|
||||||
SpacesInConditionalStatement: false
|
|
||||||
SpacesInContainerLiterals: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInLineCommentPrefix:
|
|
||||||
Minimum: 1
|
|
||||||
Maximum: -1
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
SpaceBeforeSquareBrackets: false
|
|
||||||
BitFieldColonSpacing: After
|
|
||||||
Standard: c++11
|
|
||||||
StatementAttributeLikeMacros:
|
|
||||||
- Q_EMIT
|
|
||||||
- PIMETA
|
|
||||||
StatementMacros:
|
|
||||||
- Q_UNUSED
|
|
||||||
- QT_REQUIRE_VERSION
|
|
||||||
- PRIVATE_DECLARATION
|
|
||||||
- NO_COPY_CLASS
|
|
||||||
- FOREVER_WAIT
|
|
||||||
- WAIT_FOREVER
|
|
||||||
TabWidth: 4
|
|
||||||
UseCRLF: false
|
|
||||||
UseTab: AlignWithSpaces
|
|
||||||
WhitespaceSensitiveMacros:
|
|
||||||
- STRINGIZE
|
|
||||||
- PP_STRINGIZE
|
|
||||||
- BOOST_PP_STRINGIZE
|
|
||||||
- NS_SWIFT_NAME
|
|
||||||
- CF_SWIFT_NAME
|
|
||||||
- PIMETA
|
|
||||||
...
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*.{h,c,cpp}]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = tab
|
|
||||||
tab_width = 4
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lapi_c
|
#define lapi_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lcode_c
|
#define lcode_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lctype_c
|
#define lctype_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ldebug_c
|
#define ldebug_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ldo_c
|
#define ldo_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ldump_c
|
#define ldump_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lfunc_c
|
#define lfunc_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lgc_c
|
#define lgc_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define llex_c
|
#define llex_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lmem_c
|
#define lmem_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lobject_c
|
#define lobject_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lopcodes_c
|
#define lopcodes_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lparser_c
|
#define lparser_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lstate_c
|
#define lstate_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lstring_c
|
#define lstring_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ltable_c
|
#define ltable_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ltm_c
|
#define ltm_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lundump_c
|
#define lundump_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lvm_c
|
#define lvm_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define lzio_c
|
#define lzio_c
|
||||||
|
#define LUA_CORE
|
||||||
|
|
||||||
#include "lprefix.h"
|
#include "lprefix.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||||
project(PIP)
|
project(pip)
|
||||||
set(PIP_MAJOR 3)
|
set(pip_MAJOR 2)
|
||||||
set(PIP_MINOR 15)
|
set(pip_MINOR 39)
|
||||||
set(PIP_REVISION 2)
|
set(pip_REVISION 0)
|
||||||
set(PIP_SUFFIX )
|
set(pip_SUFFIX )
|
||||||
set(PIP_COMPANY SHS)
|
set(pip_COMPANY SHS)
|
||||||
set(PIP_DOMAIN org.SHS)
|
set(pip_DOMAIN org.SHS)
|
||||||
|
|
||||||
set(GIT_CMAKE_DIR)
|
set(GIT_CMAKE_DIR)
|
||||||
if (NOT DEFINED SHSTKPROJECT)
|
if (NOT DEFINED SHSTKPROJECT)
|
||||||
@@ -17,7 +17,7 @@ cmake_minimum_required(VERSION 2.8.2)
|
|||||||
project(cmake-download NONE)
|
project(cmake-download NONE)
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(cmake
|
ExternalProject_Add(cmake
|
||||||
GIT_REPOSITORY https://git.shstk.ru/SHS/cmake.git
|
GIT_REPOSITORY https://git.shs.tools/SHS/cmake.git
|
||||||
GIT_TAG \"origin/master\"
|
GIT_TAG \"origin/master\"
|
||||||
GIT_CONFIG \"advice.detachedHead=false\"
|
GIT_CONFIG \"advice.detachedHead=false\"
|
||||||
SOURCE_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cmake-src\"
|
SOURCE_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cmake-src\"
|
||||||
@@ -53,7 +53,7 @@ include(CheckFunctionExists)
|
|||||||
include(PIPMacros)
|
include(PIPMacros)
|
||||||
include(SHSTKMacros)
|
include(SHSTKMacros)
|
||||||
|
|
||||||
shstk_begin_project(PIP)
|
shstk_begin_project(pip PIP)
|
||||||
|
|
||||||
set(_ICU_DEFAULT OFF)
|
set(_ICU_DEFAULT OFF)
|
||||||
if((NOT DEFINED WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT DEFINED APPLE))
|
if((NOT DEFINED WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT DEFINED APPLE))
|
||||||
@@ -61,21 +61,14 @@ if((NOT DEFINED WIN32) AND (NOT DEFINED ANDROID_PLATFORM) AND (NOT DEFINED APPLE
|
|||||||
endif()
|
endif()
|
||||||
set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE STRING "")
|
set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE STRING "")
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
|
||||||
set(PIP_BUILD_DEBUG ON)
|
|
||||||
else()
|
|
||||||
set(PIP_BUILD_DEBUG OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT})
|
option(ICU "ICU support for convert codepages" ${_ICU_DEFAULT})
|
||||||
option(STD_IOSTREAM "Building with std iostream operators support" OFF)
|
option(STD_IOSTREAM "Building with std iostream operators support" OFF)
|
||||||
option(INTROSPECTION "Build with introspection" OFF)
|
option(INTROSPECTION "Build with introspection" OFF)
|
||||||
option(TESTS "Build tests and perform their before install step" ${PIP_BUILD_DEBUG})
|
option(TESTS "Build tests and perform their before install step" OFF)
|
||||||
option(COVERAGE "Build project with coverage info" OFF)
|
option(COVERAGE "Build project with coverage info" OFF)
|
||||||
set(PIP_UTILS 1)
|
set(PIP_UTILS 1)
|
||||||
set(BUILDING_pip 1 PARENT_SCOPE)
|
|
||||||
set(pip_ROOT_SRC "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
@@ -103,7 +96,7 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
|
|||||||
set(CRES)
|
set(CRES)
|
||||||
file(GLOB_RECURSE CPPS "libs/${NAME}/*.cpp" "libs/${NAME}/*.c")
|
file(GLOB_RECURSE CPPS "libs/${NAME}/*.cpp" "libs/${NAME}/*.c")
|
||||||
file(GLOB_RECURSE HS "libs/${NAME}/*.h")
|
file(GLOB_RECURSE HS "libs/${NAME}/*.h")
|
||||||
file(GLOB_RECURSE PHS "libs/${NAME}/*_p.h" "libs/${NAME}/3rd/*.h")
|
file(GLOB_RECURSE PHS "libs/${NAME}/*_p.h")
|
||||||
file(GLOB_RECURSE RES "libs/${NAME}/*.conf")
|
file(GLOB_RECURSE RES "libs/${NAME}/*.conf")
|
||||||
if (NOT "x${PHS}" STREQUAL "x")
|
if (NOT "x${PHS}" STREQUAL "x")
|
||||||
list(REMOVE_ITEM HS ${PHS})
|
list(REMOVE_ITEM HS ${PHS})
|
||||||
@@ -112,14 +105,9 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
|
|||||||
file(GLOB_RECURSE ASRC "${SOURCES}/*.cpp" "${SOURCES}/*.c")
|
file(GLOB_RECURSE ASRC "${SOURCES}/*.cpp" "${SOURCES}/*.c")
|
||||||
list(APPEND CPPS ${ASRC})
|
list(APPEND CPPS ${ASRC})
|
||||||
endif()
|
endif()
|
||||||
#message("${NAME} HS = ${HS}")
|
|
||||||
list(APPEND HDRS ${HS})
|
list(APPEND HDRS ${HS})
|
||||||
list(APPEND PHDRS ${PHS})
|
list(APPEND PHDRS ${PHS})
|
||||||
|
|
||||||
if(${CMAKE_VERSION} VERSION_LESS "3.8.0")
|
|
||||||
else()
|
|
||||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${CPPS} ${HS} ${PHS})
|
|
||||||
endif()
|
|
||||||
set(_target "pip_${NAME}")
|
set(_target "pip_${NAME}")
|
||||||
set(_libs "${LIBS}")
|
set(_libs "${LIBS}")
|
||||||
if ("${NAME}" STREQUAL "main")
|
if ("${NAME}" STREQUAL "main")
|
||||||
@@ -130,11 +118,11 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
|
|||||||
string(TOUPPER "${_target}" DEF_NAME)
|
string(TOUPPER "${_target}" DEF_NAME)
|
||||||
|
|
||||||
set(PIP_MSG_${NAME} "yes${MSG}")
|
set(PIP_MSG_${NAME} "yes${MSG}")
|
||||||
import_version(${_target} PIP)
|
import_version(${_target} pip)
|
||||||
set_deploy_property(${_target} ${PIP_LIB_TYPE}
|
set_deploy_property(${_target} ${pip_LIB_TYPE}
|
||||||
LABEL "${LABEL}"
|
LABEL "${LABEL}"
|
||||||
FULLNAME "${PIP_DOMAIN}.${_target}"
|
FULLNAME "${pip_DOMAIN}.${_target}"
|
||||||
COMPANY "${PIP_COMPANY}"
|
COMPANY "${pip_COMPANY}"
|
||||||
INFO "Platform-Independent Primitives")
|
INFO "Platform-Independent Primitives")
|
||||||
make_rc(${_target} _RC)
|
make_rc(${_target} _RC)
|
||||||
|
|
||||||
@@ -151,7 +139,7 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
|
|||||||
pip_resources(CRES "${RES}")
|
pip_resources(CRES "${RES}")
|
||||||
endif()
|
endif()
|
||||||
add_definitions(-D${DEF_NAME})
|
add_definitions(-D${DEF_NAME})
|
||||||
add_library(${_target} ${PIP_LIB_TYPE} ${CPPS} ${CRES} ${_RC} ${HS} ${PHS})
|
add_library(${_target} ${pip_LIB_TYPE} ${CPPS} ${CRES} ${_RC})
|
||||||
target_include_directories(${_target} PUBLIC ${PIP_INCLUDES})
|
target_include_directories(${_target} PUBLIC ${PIP_INCLUDES})
|
||||||
if (NOT "x${RES}" STREQUAL "x")
|
if (NOT "x${RES}" STREQUAL "x")
|
||||||
add_dependencies(${_target} pip_rc)
|
add_dependencies(${_target} pip_rc)
|
||||||
@@ -260,10 +248,12 @@ CHECK_FUNCTION_EXISTS(timer_delete PIP_TIMER_RT_2)
|
|||||||
|
|
||||||
|
|
||||||
# Check if build debug version
|
# Check if build debug version
|
||||||
if (PIP_BUILD_DEBUG)
|
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
set(PIP_BUILD_TYPE "Debug")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall")
|
||||||
add_definitions(-DPIP_DEBUG)
|
add_definitions(-DPIP_DEBUG)
|
||||||
else()
|
else()
|
||||||
|
set(PIP_BUILD_TYPE "Release")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -458,16 +448,17 @@ if (NOT CROSSTOOLS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if (NOT "x${MINGW_INCLUDE}" STREQUAL "x")
|
|
||||||
list(APPEND CMAKE_INCLUDE_PATH "${MINGW_INCLUDE}")
|
|
||||||
endif()
|
|
||||||
find_package(OpenCL QUIET) #OpenCL_VERSION_STRING
|
find_package(OpenCL QUIET) #OpenCL_VERSION_STRING
|
||||||
if(OpenCL_FOUND)
|
if(OpenCL_FOUND)
|
||||||
|
set(_opencl_lib OpenCL::OpenCL)
|
||||||
|
if(${CMAKE_VERSION} VERSION_LESS "3.7.0")
|
||||||
|
target_link_libraries(_opencl_lib OpenCL)
|
||||||
|
endif()
|
||||||
set(_opencl_inc "${OpenCL_INCLUDE_DIRS}")
|
set(_opencl_inc "${OpenCL_INCLUDE_DIRS}")
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(_opencl_inc "${OpenCL_INCLUDE_DIRS}/Headers")
|
set(_opencl_inc "${OpenCL_INCLUDE_DIRS}/Headers")
|
||||||
endif()
|
endif()
|
||||||
pip_module(opencl "OpenCL" "PIP OpenCL support" "${_opencl_inc}" "" " (${OpenCL_VERSION_STRING})")
|
pip_module(opencl "${_opencl_lib}" "PIP OpenCL support" "${_opencl_inc}" "" " (${OpenCL_VERSION_STRING})")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
@@ -490,18 +481,14 @@ if (NOT CROSSTOOLS)
|
|||||||
list(APPEND HDR_DIRS "${_lua_bri_dir}/LuaBridge")
|
list(APPEND HDR_DIRS "${_lua_bri_dir}/LuaBridge")
|
||||||
list(APPEND HDRS ${_lua_src_hdr})
|
list(APPEND HDRS ${_lua_src_hdr})
|
||||||
|
|
||||||
|
|
||||||
# Test program
|
# Test program
|
||||||
if(PIP_UTILS)
|
if(PIP_UTILS)
|
||||||
|
#add_library(pip_plugin SHARED "test_plugin.h" "test_plugin.cpp")
|
||||||
#add_library(pip_plugin SHARED "test_plugin.h" "test_plugin.cpp" "ccm.h" "ccm.cpp")
|
|
||||||
#target_link_libraries(pip_plugin pip)
|
#target_link_libraries(pip_plugin pip)
|
||||||
|
|
||||||
add_executable(pip_test "main.cpp")
|
add_executable(pip_test "main.cpp")
|
||||||
target_link_libraries(pip_test pip)
|
target_link_libraries(pip_test pip)
|
||||||
if(sodium_FOUND)
|
|
||||||
add_executable(pip_cloud_test "main_picloud_test.cpp")
|
|
||||||
target_link_libraries(pip_cloud_test pip_cloud)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
else()
|
else()
|
||||||
@@ -575,7 +562,6 @@ if(NOT PIP_FREERTOS)
|
|||||||
add_subdirectory("utils/code_model_generator")
|
add_subdirectory("utils/code_model_generator")
|
||||||
add_subdirectory("utils/resources_compiler")
|
add_subdirectory("utils/resources_compiler")
|
||||||
add_subdirectory("utils/deploy_tool")
|
add_subdirectory("utils/deploy_tool")
|
||||||
add_subdirectory("utils/value_tree_translator")
|
|
||||||
if(PIP_UTILS AND (NOT CROSSTOOLS))
|
if(PIP_UTILS AND (NOT CROSSTOOLS))
|
||||||
add_subdirectory("utils/system_test")
|
add_subdirectory("utils/system_test")
|
||||||
add_subdirectory("utils/udp_file_transfer")
|
add_subdirectory("utils/udp_file_transfer")
|
||||||
@@ -606,14 +592,14 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
|
|||||||
string(TOUPPER "${_m}" _mdef)
|
string(TOUPPER "${_m}" _mdef)
|
||||||
list(APPEND DOXY_DEFINES "PIP_${_mdef}_EXPORT")
|
list(APPEND DOXY_DEFINES "PIP_${_mdef}_EXPORT")
|
||||||
endforeach()
|
endforeach()
|
||||||
set(DOXY_PROJECT_NUMBER "${PIP_VERSION}")
|
set(DOXY_PROJECT_NUMBER "${pip_VERSION}")
|
||||||
set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
|
set(DOXY_QHP_CUST_FILTER_ATTRS "\"PIP ${pip_VERSION}\"")
|
||||||
set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${PIP_VERSION}\"")
|
set(DOXY_QHP_SECT_FILTER_ATTRS "\"PIP ${pip_VERSION}\"")
|
||||||
set(DOXY_EXAMPLE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/examples\"")
|
set(DOXY_EXAMPLE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/examples\"")
|
||||||
set(DOXY_IMAGE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/images\"")
|
set(DOXY_IMAGE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/images\"")
|
||||||
set(DOXY_LOGO_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/pip.png\"")
|
set(DOXY_LOGO_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/doc/pip.png\"")
|
||||||
set(DOXY_EXCLUDE "\"${CMAKE_CURRENT_SOURCE_DIR}/libs/lua/3rd\"")
|
set(DOXY_EXCLUDE "\"${CMAKE_CURRENT_SOURCE_DIR}/libs/lua/3rd\"")
|
||||||
set(DOXY_DOMAIN "${PIP_DOMAIN}.${PROJECT_NAME}.doc")
|
set(DOXY_DOMAIN "${pip_DOMAIN}.${PROJECT_NAME}.doc")
|
||||||
if ("x${DOC_LANG}" STREQUAL "x")
|
if ("x${DOC_LANG}" STREQUAL "x")
|
||||||
set(DOXY_OUTPUT_LANGUAGE English)
|
set(DOXY_OUTPUT_LANGUAGE English)
|
||||||
set(DOXY_OUTPUT_DIR en)
|
set(DOXY_OUTPUT_DIR en)
|
||||||
@@ -659,9 +645,9 @@ endmacro()
|
|||||||
|
|
||||||
list(REMOVE_ITEM LIBS_STATUS ${PIP_MODULES})
|
list(REMOVE_ITEM LIBS_STATUS ${PIP_MODULES})
|
||||||
message("----------PIP----------")
|
message("----------PIP----------")
|
||||||
message(" Version: ${PIP_VERSION} ")
|
message(" Version: ${pip_VERSION} ")
|
||||||
message(" Linkage: ${PIP_LIB_TYPE_MSG}")
|
message(" Linkage: ${pip_LIB_TYPE_MSG}")
|
||||||
message(" Type : ${CMAKE_BUILD_TYPE}")
|
message(" Type : ${pip_BUILD_TYPE}")
|
||||||
if (NOT LOCAL)
|
if (NOT LOCAL)
|
||||||
message(" Install: \"${CMAKE_INSTALL_PREFIX}\"")
|
message(" Install: \"${CMAKE_INSTALL_PREFIX}\"")
|
||||||
else()
|
else()
|
||||||
|
|||||||
@@ -20,11 +20,16 @@ main library
|
|||||||
cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
|
cmake_policy(SET CMP0011 NEW) # don`t affect includer policies
|
||||||
include(SHSTKMacros)
|
include(SHSTKMacros)
|
||||||
|
|
||||||
shstk_set_find_dirs(PIP)
|
shstk_set_find_dirs(pip)
|
||||||
|
if(PIP_DIR)
|
||||||
|
list(APPEND pip_LIBDIR "${PIP_DIR}/lib")
|
||||||
|
list(APPEND pip_INCDIR "${PIP_DIR}/include/pip")
|
||||||
|
list(APPEND pip_BINDIR "${PIP_DIR}/bin")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(__libs "usb;crypt;console;fftw;compress;io_utils;opencl;cloud;lua")
|
set(__libs "usb;crypt;console;fftw;compress;io_utils;opencl;cloud;lua")
|
||||||
|
|
||||||
if (BUILDING_PIP)
|
if (BUILDING_pip)
|
||||||
#set(_libs "pip;pip_usb;pip_console;pip_crypt;pip_fftw;pip_compress;pip_opencl;pip_io_utils;pip_cloud;pip_lua")
|
#set(_libs "pip;pip_usb;pip_console;pip_crypt;pip_fftw;pip_compress;pip_opencl;pip_io_utils;pip_cloud;pip_lua")
|
||||||
#set(_bins "pip_cmg;pip_rc;deploy_tool")
|
#set(_bins "pip_cmg;pip_rc;deploy_tool")
|
||||||
#get_target_property(_path pip BINARY_DIR)
|
#get_target_property(_path pip BINARY_DIR)
|
||||||
@@ -35,20 +40,20 @@ if (BUILDING_PIP)
|
|||||||
|
|
||||||
set(PIP_FOUND ON CACHE BOOL "")
|
set(PIP_FOUND ON CACHE BOOL "")
|
||||||
else()
|
else()
|
||||||
find_library(PIP_LIBRARY pip HINTS ${PIP_LIBDIR})
|
find_library(PIP_LIBRARY pip HINTS ${pip_LIBDIR})
|
||||||
foreach (_l ${__libs})
|
foreach (_l ${__libs})
|
||||||
find_library(PIP_LIBRARY_${_l} pip_${_l} HINTS ${PIP_LIBDIR})
|
find_library(PIP_LIBRARY_${_l} pip_${_l} HINTS ${pip_LIBDIR})
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILDING_PIP AND (NOT CMAKE_CROSSCOMPILING))
|
if (BUILDING_pip AND (NOT CMAKE_CROSSCOMPILING))
|
||||||
set(PIP_CMG "$<TARGET_FILE_DIR:pip_cmg>/$<TARGET_FILE_NAME:pip_cmg>" CACHE STRING "")
|
set(PIP_CMG "$<TARGET_FILE_DIR:pip_cmg>/$<TARGET_FILE_NAME:pip_cmg>" CACHE STRING "")
|
||||||
set(PIP_RC "$<TARGET_FILE_DIR:pip_rc>/$<TARGET_FILE_NAME:pip_rc>" CACHE STRING "")
|
set(PIP_RC "$<TARGET_FILE_DIR:pip_rc>/$<TARGET_FILE_NAME:pip_rc>" CACHE STRING "")
|
||||||
set(PIP_DEPLOY_TOOL "$<TARGET_FILE_DIR:deploy_tool>/$<TARGET_FILE_NAME:deploy_tool>" CACHE STRING "")
|
set(PIP_DEPLOY_TOOL "$<TARGET_FILE_DIR:deploy_tool>/$<TARGET_FILE_NAME:deploy_tool>" CACHE STRING "")
|
||||||
else()
|
else()
|
||||||
find_program(PIP_CMG pip_cmg${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
|
find_program(PIP_CMG pip_cmg${pip_BINEXT} HINTS ${pip_BINDIR} ${pip_FIND_PROGRAM_ARG})
|
||||||
find_program(PIP_RC pip_rc${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
|
find_program(PIP_RC pip_rc${pip_BINEXT} HINTS ${pip_BINDIR} ${pip_FIND_PROGRAM_ARG})
|
||||||
find_program(PIP_DEPLOY_TOOL deploy_tool${PIP_BINEXT} HINTS ${PIP_BINDIR} ${PIP_FIND_PROGRAM_ARG})
|
find_program(PIP_DEPLOY_TOOL deploy_tool${pip_BINEXT} HINTS ${pip_BINDIR} ${pip_FIND_PROGRAM_ARG})
|
||||||
endif()
|
endif()
|
||||||
if (NOT PIP_LIBRARY)
|
if (NOT PIP_LIBRARY)
|
||||||
if(PIP_FIND_REQUIRED)
|
if(PIP_FIND_REQUIRED)
|
||||||
@@ -58,7 +63,7 @@ if (NOT PIP_LIBRARY)
|
|||||||
endif()
|
endif()
|
||||||
set(_PIP_LIBRARY_PATH_ "${PIP_LIBRARY}")
|
set(_PIP_LIBRARY_PATH_ "${PIP_LIBRARY}")
|
||||||
set(_PIP_ADD_LIBS_ "")
|
set(_PIP_ADD_LIBS_ "")
|
||||||
if (NOT BUILDING_PIP)
|
if (NOT BUILDING_pip)
|
||||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||||
find_library(DL_LIBRARY dl)
|
find_library(DL_LIBRARY dl)
|
||||||
list(APPEND PIP_LIBRARY ${DL_LIBRARY})
|
list(APPEND PIP_LIBRARY ${DL_LIBRARY})
|
||||||
@@ -75,9 +80,9 @@ if (NOT BUILDING_PIP)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT BUILDING_PIP)
|
if (NOT BUILDING_pip)
|
||||||
shstk_find_header(PIP "pip_version.h" "${_PIP_LIBRARY_PATH_}")
|
shstk_find_header(pip PIP "pip_version.h" "${_PIP_LIBRARY_PATH_}")
|
||||||
set(PIP_INCLUDES "${PIP_INCLUDES}" CACHE STRING "")
|
set(PIP_INCLUDES "${pip_INCLUDES}" CACHE STRING "")
|
||||||
endif()
|
endif()
|
||||||
if(PIP_FIND_VERSION VERSION_GREATER PIP_VERSION)
|
if(PIP_FIND_VERSION VERSION_GREATER PIP_VERSION)
|
||||||
message(FATAL_ERROR "PIP version ${PIP_VERSION} is available, but ${PIP_FIND_VERSION} requested!")
|
message(FATAL_ERROR "PIP version ${PIP_VERSION} is available, but ${PIP_FIND_VERSION} requested!")
|
||||||
@@ -103,10 +108,10 @@ set(__deps_io_utils "PIP::Crypt")
|
|||||||
set(__deps_cloud "PIP::IOUtils")
|
set(__deps_cloud "PIP::IOUtils")
|
||||||
|
|
||||||
|
|
||||||
if (BUILDING_PIP)
|
if (BUILDING_pip)
|
||||||
|
|
||||||
if (NOT SET_TARGETS_PIP)
|
if (NOT SET_TARGETS_pip)
|
||||||
set(SET_TARGETS_PIP ON CACHE BOOL "")
|
set(SET_TARGETS_pip ON CACHE BOOL "")
|
||||||
#message("create aliases")
|
#message("create aliases")
|
||||||
if((NOT TARGET PIP) AND PIP_LIBRARY)
|
if((NOT TARGET PIP) AND PIP_LIBRARY)
|
||||||
#message("alias PIP = pip")
|
#message("alias PIP = pip")
|
||||||
@@ -128,7 +133,7 @@ else()
|
|||||||
add_library(PIP UNKNOWN IMPORTED)
|
add_library(PIP UNKNOWN IMPORTED)
|
||||||
set_target_properties(PIP PROPERTIES
|
set_target_properties(PIP PROPERTIES
|
||||||
IMPORTED_LOCATION "${_PIP_LIBRARY_PATH_}"
|
IMPORTED_LOCATION "${_PIP_LIBRARY_PATH_}"
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${PIP_INCLUDES}"
|
INTERFACE_INCLUDE_DIRECTORIES "${pip_INCLUDES}"
|
||||||
INTERFACE_LINK_LIBRARIES "${_PIP_ADD_LIBS_}")
|
INTERFACE_LINK_LIBRARIES "${_PIP_ADD_LIBS_}")
|
||||||
#message("imported PIP = ${PIP_LIBRARY}")
|
#message("imported PIP = ${PIP_LIBRARY}")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -2282,7 +2282,7 @@ EXTERNAL_GROUPS = YES
|
|||||||
# be listed.
|
# be listed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
EXTERNAL_PAGES = NO
|
EXTERNAL_PAGES = YES
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the dot tool
|
# Configuration options related to the dot tool
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
inline PICout operator <<(PICout s, const PIByteArray & ba) {
|
inline PICout operator <<(PICout s, const PIByteArray & ba) {
|
||||||
s.space(); // insert space after previous output
|
s.space(); // insert space after previous output
|
||||||
s.quote(); // ONLY if you want to quoted your type
|
s.quote(); // ONLY if you want to quoted your type
|
||||||
s.saveAndSetControls(0); // clear all features and
|
s.setControl(0, true); // clear all features and
|
||||||
// save them to stack,
|
// save them to stack,
|
||||||
// now it`s behavior similar to std::cout
|
// now it`s behavior similar to std::cout
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ inline PICout operator <<(PICout s, const PIByteArray & ba) {
|
|||||||
for (uint i = 0; i < ba.size(); ++i)
|
for (uint i = 0; i < ba.size(); ++i)
|
||||||
s << ba[i];
|
s << ba[i];
|
||||||
|
|
||||||
s.restoreControls(); // restore features from stack
|
s.restoreControl(); // restore features from stack
|
||||||
s.quote(); // ONLY if you want to quoted your type
|
s.quote(); // ONLY if you want to quoted your type
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,19 @@ class SomeIO: public PIIODevice {
|
|||||||
public:
|
public:
|
||||||
SomeIO(): PIIODevice() {}
|
SomeIO(): PIIODevice() {}
|
||||||
protected:
|
protected:
|
||||||
bool openDevice() override {
|
bool openDevice() {
|
||||||
// open your device here
|
// open your device here
|
||||||
return if_success;
|
return if_success;
|
||||||
}
|
}
|
||||||
ssize_t readDevice(void * read_to, ssize_t max_size) override {
|
int read(void * read_to, int max_size) {
|
||||||
// read from your device here
|
// read from your device here
|
||||||
return readed_bytes;
|
return readed_bytes;
|
||||||
}
|
}
|
||||||
ssize_t writeDevice(const void * data, ssize_t max_size) override {
|
int write(const void * data, int max_size) {
|
||||||
// write to your device here
|
// write to your device here
|
||||||
return written_bytes;
|
return written_bytes;
|
||||||
}
|
}
|
||||||
void configureFromFullPathDevice(const PIString & full_path) override {
|
void configureFromFullPath(const PIString & full_path) {
|
||||||
// parse full_path and configure device here
|
// parse full_path and configure device here
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -38,7 +38,7 @@ ser.configure("example.conf", "dev");
|
|||||||
//! [configureDevice]
|
//! [configureDevice]
|
||||||
class SomeIO: public PIIODevice {
|
class SomeIO: public PIIODevice {
|
||||||
...
|
...
|
||||||
bool configureDevice(const void * e_main, const void * e_parent) override {
|
bool configureDevice(const void * e_main, const void * e_parent) {
|
||||||
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
|
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
|
||||||
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
|
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
|
||||||
setStringParam(readDeviceSetting<PIString>("stringParam", stringParam(), em, ep));
|
setStringParam(readDeviceSetting<PIString>("stringParam", stringParam(), em, ep));
|
||||||
|
|||||||
@@ -1,297 +0,0 @@
|
|||||||
\~english \page code_model Code generation
|
|
||||||
\~russian \page code_model Генерация кода
|
|
||||||
|
|
||||||
\~english
|
|
||||||
|
|
||||||
\~russian
|
|
||||||
|
|
||||||
# Введение
|
|
||||||
|
|
||||||
Кодогенерация помогает в случаях, когда нужен доступ к строковому представлению
|
|
||||||
сущностей (классов, перечислений, ...), либо автоматизированная де/сериализация
|
|
||||||
структур и классов.
|
|
||||||
|
|
||||||
Например, необходимо для создания интерфейса получить в готовом виде список
|
|
||||||
пар "имя" = "значение" от какого-либо перечисления, либо обойти список
|
|
||||||
вложенных в класс структур с дополнительными метками. Или просто описать
|
|
||||||
структуру любой сложности, пометить поля номерами и получить готовые операторы
|
|
||||||
де/сериализации для PIBinaryStream с возможностью будущих изменений и сохранением
|
|
||||||
обратной совместимости.
|
|
||||||
|
|
||||||
# pip_cmg
|
|
||||||
|
|
||||||
PIP предоставляет утилиту, которая берет на вход файлы исходного кода, пути
|
|
||||||
включения, параметры и макросы, и на выходе создает h/cpp пару файлов с
|
|
||||||
необходимым функционалом. В зависимости от параметров, в этих файлах будут
|
|
||||||
присутствовать секции:
|
|
||||||
* метаинформации о сущностях;
|
|
||||||
* операторы де/сериализации;
|
|
||||||
* возможность получить PIVariant любого члена структуры по имени.
|
|
||||||
|
|
||||||
Параметры обработки:
|
|
||||||
* -s - не следовать "#include" внутри файлов;
|
|
||||||
* -I<include_dir> - добавить папку включения (например, -I.. -I../some_dir -I/usr/include);
|
|
||||||
* -D<define> - добавить макрос, PICODE всегда объявлен (например, -DMY_DEFINE добавит макрос MY_DEFINE).
|
|
||||||
|
|
||||||
Параметры создания:
|
|
||||||
* -A - создать всё;
|
|
||||||
* -M - создать метаинформацию (имена и типы всех членов, иерархия включения);
|
|
||||||
* -E - создать перечисления (списки перечислений);
|
|
||||||
* -S - создать операторы де/сериализации;
|
|
||||||
* -G - создать методы получения значений переменных по именам;
|
|
||||||
* -o <output_file> - имя файлов модели без расширения (например, "ccm" - создадутся файлы "ccm.h" и "ccm.cpp")
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
|
|
||||||
Для автоматизации кодогенерации существует CMake макрос pip_code_model, который сам вызывает pip_cmg и
|
|
||||||
следит за актуальностью модели.
|
|
||||||
|
|
||||||
Формат вызова макроса:
|
|
||||||
\code{.cmake}
|
|
||||||
pip_code_model(<out_var> file0 [file1 ...] [OPTIONS opt0 [opt1 ...] ] [NAME name])
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
Параметры:
|
|
||||||
* out_var - имя переменной, куда будут записаны абсолютные пути сгенерённых файлов;
|
|
||||||
* file... - файлы для генерации, допускаются относительные или абсолютные пути;
|
|
||||||
* OPTIONS - передаваемые в pip_cmg параметры, например, "-Es";
|
|
||||||
* NAME - базовое имя файлов модели, если не указано, то используется "ccm_${PROJECT_NAME}".
|
|
||||||
|
|
||||||
Этот макрос сам включает все пути для PIP.
|
|
||||||
|
|
||||||
Для получения актуальных параметров pip_cmg можно вызывать "pip_cmg -v".
|
|
||||||
|
|
||||||
# Подробности
|
|
||||||
|
|
||||||
## Метаинформация
|
|
||||||
|
|
||||||
Метаинформация - это текстовое представление всех членов и методов структуры или класса C++.
|
|
||||||
Для доступа к ним используется PICODEINFO::classes().value("name"), который возвращает
|
|
||||||
указатель на структуру PICodeInfo::ClassInfo, содержащую всю информацию о сущности.
|
|
||||||
|
|
||||||
В любой структуре PICodeInfo есть поле "MetaMap meta", содержащее произвольные
|
|
||||||
данные, видимые для кодогенератора, но невидимые для компилятора.
|
|
||||||
Для этого используется макрос PIMETA(), который необходимо вписать после объявления
|
|
||||||
переменной, метода либо сущности, например:
|
|
||||||
\code{.cpp}
|
|
||||||
struct MyStruct: Header PIMETA(type=in,port=5005) {
|
|
||||||
ushort calcChecksum() const PIMETA(show=true);
|
|
||||||
bool checkChecksum() const;
|
|
||||||
void setChecksum();
|
|
||||||
uchar block_id PIMETA(type=int) = 0;
|
|
||||||
};
|
|
||||||
enum FOV { // Поле зрения
|
|
||||||
fovWide PIMETA(label="Широкое",angle=90),
|
|
||||||
fovNormal PIMETA(label="Нормальное",angle=60),
|
|
||||||
fovNarrow PIMETA(label="Узкое",angle=30)
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
В этом примере в каждом месте, где указана PIMETA, её можно будет получить через "MetaMap meta".
|
|
||||||
|
|
||||||
## Перечисления
|
|
||||||
|
|
||||||
Перечисления записываются отдельно, для доступа к ним используется PICODEINFO::enums().value("name"),
|
|
||||||
который возвращает указатель на структуру PICodeInfo::EnumInfo, содержащую всю информацию о перечеслении.
|
|
||||||
|
|
||||||
## Операторы де/сериализации
|
|
||||||
|
|
||||||
Эти операторы создаются в h файле для всех сутрктур и классов, в которых есть хотя бы один член,
|
|
||||||
доступный для работы. Операторы работают с PIBinaryStream в двух вариантах - простом или через PIChunkStream.
|
|
||||||
|
|
||||||
Для каждой структуры можно указать режим де/сериализации с помощью фиксированного поля в PIMETA:
|
|
||||||
* нет указаний - работа через PIChunkStream;
|
|
||||||
* simple-stream - работа просто через PIBinaryStream;
|
|
||||||
* no-stream - не создавать операторы.
|
|
||||||
|
|
||||||
Например, для структуры
|
|
||||||
\code{.cpp}
|
|
||||||
struct DateTime {
|
|
||||||
uchar seconds;
|
|
||||||
uchar minutes;
|
|
||||||
uchar hours;
|
|
||||||
uchar days;
|
|
||||||
uchar months;
|
|
||||||
uchar years;
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
создадутся операторы
|
|
||||||
\code{.cpp}
|
|
||||||
BINARY_STREAM_WRITE(DateTime) {
|
|
||||||
PIChunkStream cs;
|
|
||||||
cs << cs.chunk(1, v.seconds);
|
|
||||||
cs << cs.chunk(2, v.minutes);
|
|
||||||
cs << cs.chunk(3, v.hours);
|
|
||||||
cs << cs.chunk(4, v.days);
|
|
||||||
cs << cs.chunk(5, v.months);
|
|
||||||
cs << cs.chunk(6, v.years);
|
|
||||||
s << cs.data();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
BINARY_STREAM_READ (DateTime) {
|
|
||||||
PIByteArray csba; s >> csba;
|
|
||||||
PIChunkStream cs(csba);
|
|
||||||
while (!cs.atEnd()) {
|
|
||||||
switch (cs.read()) {
|
|
||||||
case 1: cs.get(v.seconds); break;
|
|
||||||
case 2: cs.get(v.minutes); break;
|
|
||||||
case 3: cs.get(v.hours); break;
|
|
||||||
case 4: cs.get(v.days); break;
|
|
||||||
case 5: cs.get(v.months); break;
|
|
||||||
case 6: cs.get(v.years); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
, где порядок id последовательнен.
|
|
||||||
|
|
||||||
Для структуры
|
|
||||||
\code{.cpp}
|
|
||||||
struct DateTime PIMETA(simple-stream) {
|
|
||||||
uchar seconds;
|
|
||||||
uchar minutes;
|
|
||||||
uchar hours;
|
|
||||||
uchar days;
|
|
||||||
uchar months;
|
|
||||||
uchar years;
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
создадутся операторы
|
|
||||||
\code{.cpp}
|
|
||||||
BINARY_STREAM_WRITE(DateTime) {
|
|
||||||
s << v.seconds;
|
|
||||||
s << v.minutes;
|
|
||||||
s << v.hours;
|
|
||||||
s << v.days;
|
|
||||||
s << v.months;
|
|
||||||
s << v.years;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
BINARY_STREAM_READ (DateTime) {
|
|
||||||
s >> v.seconds;
|
|
||||||
s >> v.minutes;
|
|
||||||
s >> v.hours;
|
|
||||||
s >> v.days;
|
|
||||||
s >> v.months;
|
|
||||||
s >> v.years;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
Для структуры
|
|
||||||
\code{.cpp}
|
|
||||||
struct DateTime PIMETA(no-stream) {
|
|
||||||
uchar seconds;
|
|
||||||
uchar minutes;
|
|
||||||
uchar hours;
|
|
||||||
uchar days;
|
|
||||||
uchar months;
|
|
||||||
uchar years;
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
не создадутся операторы
|
|
||||||
|
|
||||||
В режиме работы через PIChunkStream также можно указать индивидуальные id,
|
|
||||||
что очень полезно для сохранения обратной совместимости структур разных версий:
|
|
||||||
Для структуры
|
|
||||||
\code{.cpp}
|
|
||||||
struct DateTime {
|
|
||||||
PIMETA(id=10) uchar seconds;
|
|
||||||
PIMETA(id=11) uchar minutes;
|
|
||||||
PIMETA(id=12) uchar hours;
|
|
||||||
PIMETA(id=20) uchar days;
|
|
||||||
PIMETA(id=21) uchar months;
|
|
||||||
PIMETA(id=22) uchar years;
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
\code{.cpp}
|
|
||||||
BINARY_STREAM_WRITE(DateTime) {
|
|
||||||
PIChunkStream cs;
|
|
||||||
cs << cs.chunk(10, v.seconds);
|
|
||||||
cs << cs.chunk(11, v.minutes);
|
|
||||||
cs << cs.chunk(12, v.hours);
|
|
||||||
cs << cs.chunk(20, v.days);
|
|
||||||
cs << cs.chunk(21, v.months);
|
|
||||||
cs << cs.chunk(22, v.years);
|
|
||||||
s << cs.data();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
BINARY_STREAM_READ (DateTime) {
|
|
||||||
PIByteArray csba; s >> csba;
|
|
||||||
PIChunkStream cs(csba);
|
|
||||||
while (!cs.atEnd()) {
|
|
||||||
switch (cs.read()) {
|
|
||||||
case 10: cs.get(v.seconds); break;
|
|
||||||
case 11: cs.get(v.minutes); break;
|
|
||||||
case 12: cs.get(v.hours); break;
|
|
||||||
case 20: cs.get(v.days); break;
|
|
||||||
case 21: cs.get(v.months); break;
|
|
||||||
case 22: cs.get(v.years); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
Если в этом режиме какую-либо переменную надо проигнорировать, то вместо
|
|
||||||
числа id можно указать "-":
|
|
||||||
\code{.cpp}
|
|
||||||
struct DateTime {
|
|
||||||
PIMETA(id=10) uchar seconds;
|
|
||||||
PIMETA(id=11) uchar minutes;
|
|
||||||
PIMETA(id=-) uchar hours;
|
|
||||||
PIMETA(id=20) uchar days;
|
|
||||||
PIMETA(id=21) uchar months;
|
|
||||||
PIMETA(id=-) uchar years;
|
|
||||||
};
|
|
||||||
\endcode
|
|
||||||
\code{.cpp}
|
|
||||||
BINARY_STREAM_WRITE(DateTime) {
|
|
||||||
PIChunkStream cs;
|
|
||||||
cs << cs.chunk(10, v.seconds);
|
|
||||||
cs << cs.chunk(11, v.minutes);
|
|
||||||
cs << cs.chunk(20, v.days);
|
|
||||||
cs << cs.chunk(21, v.months);
|
|
||||||
s << cs.data();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
BINARY_STREAM_READ (DateTime) {
|
|
||||||
PIByteArray csba; s >> csba;
|
|
||||||
PIChunkStream cs(csba);
|
|
||||||
while (!cs.atEnd()) {
|
|
||||||
switch (cs.read()) {
|
|
||||||
case 10: cs.get(v.seconds); break;
|
|
||||||
case 11: cs.get(v.minutes); break;
|
|
||||||
case 20: cs.get(v.days); break;
|
|
||||||
case 21: cs.get(v.months); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
# Интеграция в проект
|
|
||||||
|
|
||||||
При использовании CMake достаточно включить содержимое переменной out_var в приложение
|
|
||||||
или библиотеку, и включить через "#include" сгенерированный заголовочный файл в нужном месте.
|
|
||||||
После этого перечисления и метаинформация будут загружены в момент запуска, до int main(),
|
|
||||||
а операторы станут доступны через заголовочный файл.
|
|
||||||
|
|
||||||
CMakeLists.txt:
|
|
||||||
\code{.cmake}
|
|
||||||
project(myapp)
|
|
||||||
pip_code_model(CCM "structures.h" OPTIONS "-EMs")
|
|
||||||
add_executable(${PROJECT_NAME} ${CPPS} ${CCM})
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
C++:
|
|
||||||
\code{.cpp}
|
|
||||||
#include "ccm_myapp.h"
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
PICodeInfo::EnumInfo * ei = PICODEINFO::enums().value("MyEnum", 0);
|
|
||||||
if (ei) {
|
|
||||||
ei->members.forEach([](const PICodeInfo::EnumeratorInfo & e){piCout << e.name << "=" << e.value;});
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
\~english \page iostream Input/Output stream
|
|
||||||
\~russian \page iostream Поток ввода/вывода
|
|
||||||
|
|
||||||
\~english
|
|
||||||
|
|
||||||
\~russian
|
|
||||||
%PIBinaryStream представляет собой интерфейс бинарной сериализации.
|
|
||||||
Не может быть использован в чистом виде, только в виде миксина или
|
|
||||||
готовых классов: PIByteArray и PIIOBinaryStream.
|
|
||||||
|
|
||||||
|
|
||||||
Используется для сохранения или чтения любых данных. Простые типы читаются/пишутся
|
|
||||||
как блоки памяти, если не созданы конкретные операторы. Сложные типы
|
|
||||||
([нетривиальные](https://ru.cppreference.com/w/cpp/types/is_trivially_copyable))
|
|
||||||
обязаны иметь операторы ввода/вывода, иначе возникнет ошибка компиляции.
|
|
||||||
|
|
||||||
Также поддерживаются контейнеры с типами по таким же правилам.
|
|
||||||
|
|
||||||
Перечисления интерпретируются как int, логические типы как один байт.
|
|
||||||
|
|
||||||
Операторы сохранения добавляют данные в конец потока, а операторы извлечения
|
|
||||||
берут данные из его начала.
|
|
||||||
|
|
||||||
Для облегчения написания операторов есть макросы:
|
|
||||||
* BINARY_STREAM_FRIEND(T) - объявить операторы с доступом к приватному
|
|
||||||
содержимому типа T, необязателен;
|
|
||||||
* BINARY_STREAM_WRITE(T) - запись в поток, "s" - объект потока, "v" - объект типа T;
|
|
||||||
* BINARY_STREAM_READ(T) - чтение из потока, "s" - объект потока, "v" - объект типа T.
|
|
||||||
|
|
||||||
Пример:
|
|
||||||
\~\code{.cpp}
|
|
||||||
#include <pibytearray.h>
|
|
||||||
|
|
||||||
class MyType {
|
|
||||||
BINARY_STREAM_FRIEND(MyType);
|
|
||||||
public:
|
|
||||||
|
|
||||||
void setInt(int v) {m_i = v;}
|
|
||||||
int getInt() const {return m_i;}
|
|
||||||
|
|
||||||
void setString(PIString v) {m_s = v;}
|
|
||||||
PIString getString() const {return m_s;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_i = 0;
|
|
||||||
PIString m_s;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
BINARY_STREAM_WRITE(MyType) {s << v.m_i << v.m_s; return s;}
|
|
||||||
BINARY_STREAM_READ (MyType) {s >> v.m_i >> v.m_s; return s;}
|
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
|
||||||
MyType t_read, t_write;
|
|
||||||
t_write.setInt(10);
|
|
||||||
t_write.setString("text");
|
|
||||||
|
|
||||||
PIByteArray data;
|
|
||||||
data << t_write;
|
|
||||||
|
|
||||||
piCout << data.toHex();
|
|
||||||
|
|
||||||
data >> t_read;
|
|
||||||
piCout << t_read.getInt() << t_read.getString();
|
|
||||||
|
|
||||||
piCout << data.toHex();
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\~english Result:
|
|
||||||
\~russian Результат:
|
|
||||||
\~\code{.cpp}
|
|
||||||
0a000000040000007400650078007400
|
|
||||||
10 text
|
|
||||||
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
|
|
||||||
\~english
|
|
||||||
For store/restore custom data blocks this is PIMemoryBlock class. Stream
|
|
||||||
operators of this class simply store/restore data block to/from stream:
|
|
||||||
|
|
||||||
\~russian
|
|
||||||
Для сохранения/извлечения блоков произвольных данных используется класс PIMemoryBlock.
|
|
||||||
Потоковые операторы для него просто сохраняют/извлекают блоки байтов в/из потока:
|
|
||||||
|
|
||||||
\~\code{.cpp}
|
|
||||||
float a_read[10], a_write[10];
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
|
||||||
a_read [i] = 0.f;
|
|
||||||
a_write[i] = i / 10.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
PIByteArray data;
|
|
||||||
data << PIMemoryBlock(a_write, 10 * sizeof(float));
|
|
||||||
|
|
||||||
piCout << data.toHex();
|
|
||||||
|
|
||||||
data >> PIMemoryBlock(a_read, 10 * sizeof(float));
|
|
||||||
for (int i = 0; i < 10; ++i)
|
|
||||||
piCout << a_read[i];
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\~english Result:
|
|
||||||
\~russian Результат:
|
|
||||||
\~\code{.cpp}
|
|
||||||
00000000cdcccc3dcdcc4c3e9a99993ecdcccc3e0000003f9a99193f3333333fcdcc4c3f6666663f
|
|
||||||
0
|
|
||||||
0.1
|
|
||||||
0.2
|
|
||||||
0.3
|
|
||||||
0.4
|
|
||||||
0.5
|
|
||||||
0.6
|
|
||||||
0.7
|
|
||||||
0.8
|
|
||||||
0.9
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\~english
|
|
||||||
|
|
||||||
\~russian
|
|
||||||
Если при чтении из потока не хватило данных (например, закончился массив или файл), то проверка
|
|
||||||
объекта потока на wasReadError() вернёт true. Рекомендуется делать эту проверку после чтения
|
|
||||||
данных для корректной обработки ошибки.
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
* direct output to console (\a PICout)
|
* direct output to console (\a PICout)
|
||||||
* containers (\a PIVector, \a PIDeque, \a PIVector2D, \a PIStack, \a PIQueue, \a PIMap, \a PISet)
|
* containers (\a PIVector, \a PIDeque, \a PIVector2D, \a PIStack, \a PIQueue, \a PIMap, \a PISet)
|
||||||
* byte array (\a PIByteArray)
|
* byte array (\a PIByteArray)
|
||||||
* serialization (\a PIBinaryStream, \a PITextStream, \a PIIOBinaryStream, \a PIIOTextStream, \a PIChunkStream, \a PIJSON)
|
* serialization (\a PIChunkStream)
|
||||||
* string (\a PIConstChars, \a PIString, \a PIStringList)
|
* string (\a PIConstChars, \a PIString, \a PIStringList)
|
||||||
* base object (events and handlers) (\a PIObject)
|
* base object (events and handlers) (\a PIObject)
|
||||||
* multithreading
|
* multithreading
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
* общение с консолью (\a PICout)
|
* общение с консолью (\a PICout)
|
||||||
* контейнеры (\a PIVector, \a PIDeque, \a PIVector2D, \a PIStack, \a PIQueue, \a PIMap, \a PISet)
|
* контейнеры (\a PIVector, \a PIDeque, \a PIVector2D, \a PIStack, \a PIQueue, \a PIMap, \a PISet)
|
||||||
* байтовый массив (\a PIByteArray)
|
* байтовый массив (\a PIByteArray)
|
||||||
* сериализация (\a PIBinaryStream, \a PITextStream, \a PIIOBinaryStream, \a PIIOTextStream, \a PIChunkStream)
|
* сериализация (\a PIChunkStream)
|
||||||
* строка (\a PIConstChars, \a PIString, \a PIStringList)
|
* строка (\a PIConstChars, \a PIString, \a PIStringList)
|
||||||
* базовый объект (события и обработчики) (\a PIObject)
|
* базовый объект (события и обработчики) (\a PIObject)
|
||||||
* многопоточность
|
* многопоточность
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
#include "pip.h"
|
#include "pip.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,42 +18,43 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "picloudclient.h"
|
#include "picloudclient.h"
|
||||||
|
|
||||||
#include "picloudtcp.h"
|
#include "picloudtcp.h"
|
||||||
|
|
||||||
|
|
||||||
PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode), PICloudBase() {
|
PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode), PICloudBase() {
|
||||||
tcp.setRole(PICloud::TCP::Client);
|
tcp.setRole(PICloud::TCP::Client);
|
||||||
setThreadedReadBufferSize(eth.threadedReadBufferSize());
|
|
||||||
setName("cloud_client");
|
setName("cloud_client");
|
||||||
is_connected = false;
|
is_connected = false;
|
||||||
is_deleted = false;
|
is_deleted = false;
|
||||||
// setReopenEnabled(false);
|
// setReopenEnabled(false);
|
||||||
CONNECTL(ð, connected, [this]() {
|
CONNECTL(ð, connected, [this](){opened_ = true; tcp.sendStart();});
|
||||||
opened_ = true;
|
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
|
||||||
tcp.sendStart();
|
|
||||||
});
|
|
||||||
CONNECT1(void, PIByteArray, &streampacker, packetReceiveEvent, this, _readed);
|
|
||||||
CONNECTL(ð, disconnected, [this](bool){
|
CONNECTL(ð, disconnected, [this](bool){
|
||||||
if (is_deleted) return;
|
if (is_deleted) return;
|
||||||
bool need_disconn = is_connected;
|
bool need_disconn = is_connected;
|
||||||
//piCoutObj << "eth disconnected";
|
//piCoutObj << "eth disconnected";
|
||||||
eth.stop();
|
static_cast<PIThread*>(ð)->stop();
|
||||||
opened_ = false;
|
opened_ = false;
|
||||||
internalDisconnect();
|
internalDisconnect();
|
||||||
if (need_disconn) disconnected();
|
if (need_disconn)
|
||||||
|
disconnected();
|
||||||
//piCoutObj << "eth disconnected done";
|
//piCoutObj << "eth disconnected done";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICloudClient::~PICloudClient() {
|
PICloudClient::~PICloudClient() {
|
||||||
// piCoutObj << "~PICloudClient() ..." << this;
|
//piCoutObj << "~PICloudClient()";
|
||||||
is_deleted = true;
|
PIThread::stop();
|
||||||
stopAndWait();
|
//eth.close();
|
||||||
|
//if (is_connected) disconnected();
|
||||||
close();
|
close();
|
||||||
|
//piCoutObj << "~PICloudClient() closed";
|
||||||
internalDisconnect();
|
internalDisconnect();
|
||||||
// piCoutObj << "~PICloudClient() done" << this;
|
// stop(false);
|
||||||
|
is_deleted = true;
|
||||||
|
internalDisconnect();
|
||||||
|
//piCoutObj << "~PICloudClient() done";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -68,16 +69,9 @@ void PICloudClient::setKeepConnection(bool on) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PICloudClient::interrupt() {
|
|
||||||
cond_buff.notifyOne();
|
|
||||||
cond_connect.notifyOne();
|
|
||||||
eth.interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PICloudClient::openDevice() {
|
bool PICloudClient::openDevice() {
|
||||||
//piCoutObj << "open";// << path();
|
//piCoutObj << "open";// << path();
|
||||||
bool op = eth.connect(PINetworkAddress::resolve(path()), false);
|
bool op = eth.connect(PIEthernet::Address::resolve(path()), false);
|
||||||
if (op) {
|
if (op) {
|
||||||
mutex_connect.lock();
|
mutex_connect.lock();
|
||||||
eth.startThreadedRead();
|
eth.startThreadedRead();
|
||||||
@@ -87,7 +81,7 @@ bool PICloudClient::openDevice() {
|
|||||||
mutex_connect.unlock();
|
mutex_connect.unlock();
|
||||||
if (!conn_ok) {
|
if (!conn_ok) {
|
||||||
mutex_connect.lock();
|
mutex_connect.lock();
|
||||||
eth.stopAndWait();
|
eth.stop();
|
||||||
eth.close();
|
eth.close();
|
||||||
mutex_connect.unlock();
|
mutex_connect.unlock();
|
||||||
}
|
}
|
||||||
@@ -104,28 +98,24 @@ bool PICloudClient::closeDevice() {
|
|||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
internalDisconnect();
|
internalDisconnect();
|
||||||
}
|
}
|
||||||
eth.stopAndWait();
|
eth.stop();
|
||||||
eth.close();
|
eth.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t PICloudClient::readDevice(void * read_to, ssize_t max_size) {
|
int PICloudClient::readDevice(void * read_to, int max_size) {
|
||||||
if (is_deleted || max_size <= 0) return -1;
|
if (is_deleted) return -1;
|
||||||
// piCoutObj << "readDevice ...";
|
//piCoutObj << "readDevice";
|
||||||
if (!is_connected && eth.isClosed()) openDevice();
|
if (!is_connected && eth.isClosed()) openDevice();
|
||||||
ssize_t sz = -1;
|
int sz = -1;
|
||||||
mutex_buff.lock();
|
mutex_buff.lock();
|
||||||
|
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
if (buff.isEmpty()) {
|
sz = piMini(max_size, buff.size());
|
||||||
sz = 0;
|
|
||||||
} else {
|
|
||||||
sz = piMin<ssize_t>(max_size, buff.size_s());
|
|
||||||
memcpy(read_to, buff.data(), sz);
|
memcpy(read_to, buff.data(), sz);
|
||||||
buff.remove(0, sz);
|
buff.remove(0, sz);
|
||||||
}
|
}
|
||||||
if (sz == 0) cond_buff.wait(mutex_buff);
|
|
||||||
}
|
|
||||||
mutex_buff.unlock();
|
mutex_buff.unlock();
|
||||||
if (!is_connected) opened_ = false;
|
if (!is_connected) opened_ = false;
|
||||||
//piCoutObj << "readDevice done" << sz;
|
//piCoutObj << "readDevice done" << sz;
|
||||||
@@ -133,15 +123,14 @@ ssize_t PICloudClient::readDevice(void * read_to, ssize_t max_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t PICloudClient::writeDevice(const void * data, ssize_t size) {
|
int PICloudClient::writeDevice(const void * data, int size) {
|
||||||
if (is_deleted || !is_connected) return -1;
|
if (is_deleted) return -1;
|
||||||
// piCoutObj << "writeDevice" << size;
|
// piCoutObj << "writeDevice";
|
||||||
return tcp.sendData(PIByteArray(data, size));
|
return tcp.sendData(PIByteArray(data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PICloudClient::internalDisconnect() {
|
void PICloudClient::internalDisconnect() {
|
||||||
// piCoutObj << "internalDisconnect";
|
|
||||||
is_connected = false;
|
is_connected = false;
|
||||||
cond_buff.notifyOne();
|
cond_buff.notifyOne();
|
||||||
cond_connect.notifyOne();
|
cond_connect.notifyOne();
|
||||||
@@ -166,26 +155,24 @@ void PICloudClient::_readed(PIByteArray & ba) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PICloud::TCP::Disconnect:
|
case PICloud::TCP::Disconnect:
|
||||||
eth.stop();
|
static_cast<PIThread*>(ð)->stop();
|
||||||
opened_ = false;
|
opened_ = false;
|
||||||
eth.close();
|
eth.close();
|
||||||
break;
|
break;
|
||||||
case PICloud::TCP::Data:
|
case PICloud::TCP::Data:
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
mutex_buff.lock();
|
mutex_buff.lock();
|
||||||
if (buff.size_s() > threadedReadBufferSize()) {
|
|
||||||
piCoutObj << "Error: buffer overflow, drop" << ba.size() << "bytes";
|
|
||||||
mutex_buff.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
buff.append(ba);
|
buff.append(ba);
|
||||||
mutex_buff.unlock();
|
mutex_buff.unlock();
|
||||||
cond_buff.notifyOne();
|
cond_buff.notifyOne();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
//piCoutObj << "readed" << ba.toHex();
|
//piCoutObj << "readed" << ba.toHex();
|
||||||
}
|
}
|
||||||
|
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); // FIXME: sleep here is bad
|
||||||
//piCoutObj << "_readed done";
|
//piCoutObj << "_readed done";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,35 +25,14 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode)
|
|||||||
tcp.setRole(PICloud::TCP::Server);
|
tcp.setRole(PICloud::TCP::Server);
|
||||||
tcp.setServerName(server_name);
|
tcp.setServerName(server_name);
|
||||||
setName("cloud_server__" + server_name);
|
setName("cloud_server__" + server_name);
|
||||||
is_deleted = false;
|
CONNECTU(&streampacker, packetReceiveEvent, this, _readed);
|
||||||
eth.setReopenEnabled(false);
|
CONNECTL(ð, connected, [this](){opened_ = true; piCoutObj << "connected"; tcp.sendStart();});
|
||||||
setThreadedReadBufferSize(eth.threadedReadBufferSize());
|
|
||||||
CONNECT1(void, PIByteArray, &streampacker, packetReceiveEvent, this, _readed);
|
|
||||||
CONNECTL(ð, connected, [this]() {
|
|
||||||
open_mutex.lock();
|
|
||||||
opened_ = true;
|
|
||||||
cvar.notifyOne();
|
|
||||||
open_mutex.unlock();
|
|
||||||
piCoutObj << "connected";
|
|
||||||
tcp.sendStart();
|
|
||||||
});
|
|
||||||
CONNECTL(ð, disconnected, [this](bool){
|
CONNECTL(ð, disconnected, [this](bool){
|
||||||
if (is_deleted) return;
|
|
||||||
piCoutObj << "disconnected";
|
piCoutObj << "disconnected";
|
||||||
clients_mutex.lock();
|
static_cast<PIThread*>(ð)->stop();
|
||||||
for (auto c: clients_) {
|
|
||||||
c->is_connected = false;
|
|
||||||
c->close();
|
|
||||||
}
|
|
||||||
removed_clients_.append(clients_);
|
|
||||||
clients_.clear();
|
|
||||||
index_clients.clear();
|
|
||||||
clients_mutex.unlock();
|
|
||||||
open_mutex.lock();
|
|
||||||
opened_ = false;
|
opened_ = false;
|
||||||
cvar.notifyOne();
|
ping_timer.stop(false);
|
||||||
open_mutex.unlock();
|
piMSleep(100);
|
||||||
ping_timer.stop();
|
|
||||||
});
|
});
|
||||||
CONNECTL(&ping_timer, tickEvent, [this] (void *, int){
|
CONNECTL(&ping_timer, tickEvent, [this] (void *, int){
|
||||||
if (eth.isConnected()) tcp.sendPing();
|
if (eth.isConnected()) tcp.sendPing();
|
||||||
@@ -62,17 +41,8 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode)
|
|||||||
|
|
||||||
|
|
||||||
PICloudServer::~PICloudServer() {
|
PICloudServer::~PICloudServer() {
|
||||||
// piCoutObj << "~PICloudServer ..." << this;
|
|
||||||
is_deleted = true;
|
|
||||||
stop();
|
stop();
|
||||||
close();
|
close();
|
||||||
waitThreadedReadFinished();
|
|
||||||
// piCout << "wait";
|
|
||||||
while (removed_clients_.isNotEmpty()) {
|
|
||||||
Client * c = removed_clients_.take_back();
|
|
||||||
delete c;
|
|
||||||
}
|
|
||||||
// piCoutObj << "~PICloudServer done" << this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -89,71 +59,55 @@ PIVector<PICloudServer::Client *> PICloudServer::clients() const {
|
|||||||
|
|
||||||
|
|
||||||
bool PICloudServer::openDevice() {
|
bool PICloudServer::openDevice() {
|
||||||
piCoutObj << "open device" << path();
|
//piCout << "PICloudServer open device" << path();
|
||||||
if (is_deleted) return false;
|
bool op = eth.connect(PIEthernet::Address::resolve(path()), false);
|
||||||
bool op = eth.connect(PINetworkAddress::resolve(path()), false);
|
|
||||||
if (op) {
|
if (op) {
|
||||||
eth.startThreadedRead();
|
eth.startThreadedRead();
|
||||||
ping_timer.start(5000);
|
ping_timer.start(5000);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
ping_timer.stop();
|
ping_timer.stop(false);
|
||||||
eth.close();
|
eth.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PICloudServer::closeDevice() {
|
bool PICloudServer::closeDevice() {
|
||||||
// piCoutObj << "closeDevice" << this;
|
eth.stop();
|
||||||
eth.stopAndWait();
|
ping_timer.stop(false);
|
||||||
ping_timer.stop();
|
|
||||||
eth.close();
|
|
||||||
cvar.notifyOne();
|
|
||||||
clients_mutex.lock();
|
clients_mutex.lock();
|
||||||
for (auto c : clients_) {
|
for (auto c : clients_) {
|
||||||
c->is_connected = false;
|
|
||||||
c->close();
|
c->close();
|
||||||
|
c->stop();
|
||||||
}
|
}
|
||||||
removed_clients_.append(clients_);
|
|
||||||
clients_.clear();
|
|
||||||
index_clients.clear();
|
|
||||||
clients_mutex.unlock();
|
clients_mutex.unlock();
|
||||||
|
eth.close();
|
||||||
|
for (auto c : clients_)
|
||||||
|
delete c;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t PICloudServer::readDevice(void * read_to, ssize_t max_size) {
|
int PICloudServer::readDevice(void * read_to, int max_size) {
|
||||||
if (is_deleted) return -1;
|
|
||||||
//piCoutObj << "readDevice";
|
//piCoutObj << "readDevice";
|
||||||
open_mutex.lock();
|
if (!opened_) openDevice();
|
||||||
if (isOpened()) cvar.wait(open_mutex);
|
else piMSleep(eth.readTimeout());
|
||||||
open_mutex.unlock();
|
|
||||||
// piCoutObj << "opened_ = " << opened_;
|
|
||||||
// else piMSleep(eth.readTimeout());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t PICloudServer::writeDevice(const void * data, ssize_t max_size) {
|
int PICloudServer::writeDevice(const void * data, int max_size) {
|
||||||
//piCoutObj << "writeDevice";
|
//piCoutObj << "writeDevice";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PICloudServer::interrupt() {
|
|
||||||
eth.interrupt();
|
|
||||||
cvar.notifyOne();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PICloudServer::clientDisconnect(uint client_id) {
|
void PICloudServer::clientDisconnect(uint client_id) {
|
||||||
tcp.sendDisconnected(client_id);
|
tcp.sendDisconnected(client_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PICloudServer::sendData(const PIByteArray & data, uint client_id) {
|
int PICloudServer::sendData(const PIByteArray & data, uint client_id) {
|
||||||
if (!opened_) return -1;
|
|
||||||
return tcp.sendData(data, client_id);
|
return tcp.sendData(data, client_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,16 +115,17 @@ int PICloudServer::sendData(const PIByteArray & data, uint client_id) {
|
|||||||
PICloudServer::Client::Client(PICloudServer * srv, uint id) : server(srv), client_id(id) {
|
PICloudServer::Client::Client(PICloudServer * srv, uint id) : server(srv), client_id(id) {
|
||||||
setMode(PIIODevice::ReadWrite);
|
setMode(PIIODevice::ReadWrite);
|
||||||
setReopenEnabled(false);
|
setReopenEnabled(false);
|
||||||
setThreadedReadBufferSize(server->threadedReadBufferSize());
|
|
||||||
is_connected = true;
|
is_connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICloudServer::Client::~Client() {
|
PICloudServer::Client::~Client() {
|
||||||
// piCoutObj << "~PICloudServer::Client..." << this;
|
if (is_connected) {
|
||||||
|
is_connected = false;
|
||||||
|
cond_buff.notifyOne();
|
||||||
|
}
|
||||||
close();
|
close();
|
||||||
stopAndWait();
|
stop();
|
||||||
// piCoutObj << "~PICloudServer::Client done" << this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -180,7 +135,7 @@ bool PICloudServer::Client::openDevice() {
|
|||||||
|
|
||||||
|
|
||||||
bool PICloudServer::Client::closeDevice() {
|
bool PICloudServer::Client::closeDevice() {
|
||||||
// piCoutObj << "closeDevice" << this;
|
PIThread::stop(false);
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
server->clientDisconnect(client_id);
|
server->clientDisconnect(client_id);
|
||||||
is_connected = false;
|
is_connected = false;
|
||||||
@@ -190,52 +145,37 @@ bool PICloudServer::Client::closeDevice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t PICloudServer::Client::readDevice(void * read_to, ssize_t max_size) {
|
int PICloudServer::Client::readDevice(void * read_to, int max_size) {
|
||||||
if (!is_connected) return -1;
|
if (!is_connected) return -1;
|
||||||
ssize_t sz = -1;
|
int sz = -1;
|
||||||
mutex_buff.lock();
|
mutex_buff.lock();
|
||||||
|
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty() || !is_connected;});
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
if (buff.isEmpty()) {
|
|
||||||
sz = 0;
|
|
||||||
} else {
|
|
||||||
sz = piMini(max_size, buff.size());
|
sz = piMini(max_size, buff.size());
|
||||||
memcpy(read_to, buff.data(), sz);
|
memcpy(read_to, buff.data(), sz);
|
||||||
buff.remove(0, sz);
|
buff.remove(0, sz);
|
||||||
}
|
}
|
||||||
if (sz == 0) cond_buff.wait(mutex_buff);
|
|
||||||
}
|
|
||||||
mutex_buff.unlock();
|
mutex_buff.unlock();
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t PICloudServer::Client::writeDevice(const void * data, ssize_t size) {
|
int PICloudServer::Client::writeDevice(const void * data, int size) {
|
||||||
if (!is_connected) return -1;
|
|
||||||
return server->sendData(PIByteArray(data, size), client_id);
|
return server->sendData(PIByteArray(data, size), client_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PICloudServer::Client::interrupt() {
|
|
||||||
cond_buff.notifyOne();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PICloudServer::Client::pushBuffer(const PIByteArray & ba) {
|
void PICloudServer::Client::pushBuffer(const PIByteArray & ba) {
|
||||||
if (!is_connected) return;
|
if (!is_connected) return;
|
||||||
mutex_buff.lock();
|
mutex_buff.lock();
|
||||||
if (buff.size_s() > threadedReadBufferSize()) {
|
|
||||||
piCoutObj << "Error: buffer overflow, drop" << ba.size() << "bytes";
|
|
||||||
mutex_buff.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
buff.append(ba);
|
buff.append(ba);
|
||||||
cond_buff.notifyOne();
|
cond_buff.notifyOne();
|
||||||
mutex_buff.unlock();
|
mutex_buff.unlock();
|
||||||
|
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100); // FIXME: sleep here is bad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PICloudServer::_readed(PIByteArray & ba) {
|
void PICloudServer::_readed(PIByteArray & ba) {
|
||||||
if (is_deleted) return;
|
|
||||||
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
|
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
|
||||||
if (hdr.second == tcp.role()) {
|
if (hdr.second == tcp.role()) {
|
||||||
switch (hdr.first) {
|
switch (hdr.first) {
|
||||||
@@ -245,12 +185,11 @@ void PICloudServer::_readed(PIByteArray & ba) {
|
|||||||
Client * oc = index_clients.value(id, nullptr);
|
Client * oc = index_clients.value(id, nullptr);
|
||||||
clients_mutex.unlock();
|
clients_mutex.unlock();
|
||||||
if (oc) {
|
if (oc) {
|
||||||
piCoutObj << "Warning: reject client with duplicated ID";
|
|
||||||
tcp.sendDisconnected(id);
|
tcp.sendDisconnected(id);
|
||||||
} else {
|
} else {
|
||||||
|
//piCoutObj << "new Client" << id;
|
||||||
Client * c = new Client(this, id);
|
Client * c = new Client(this, id);
|
||||||
// piCoutObj << "new Client" << id << c;
|
CONNECTU(c, deleted, this, clientDeleted);
|
||||||
CONNECT1(void, PIObject *, c, deleted, this, clientDeleted);
|
|
||||||
clients_mutex.lock();
|
clients_mutex.lock();
|
||||||
clients_ << c;
|
clients_ << c;
|
||||||
index_clients.insert(id, c);
|
index_clients.insert(id, c);
|
||||||
@@ -260,17 +199,13 @@ void PICloudServer::_readed(PIByteArray & ba) {
|
|||||||
} break;
|
} break;
|
||||||
case PICloud::TCP::Disconnect: {
|
case PICloud::TCP::Disconnect: {
|
||||||
uint id = tcp.parseDisconnect(ba);
|
uint id = tcp.parseDisconnect(ba);
|
||||||
// piCoutObj << "Close on logic";
|
//piCoutObj << "remove Client" << id;
|
||||||
clients_mutex.lock();
|
clients_mutex.lock();
|
||||||
Client * oc = index_clients.take(id, nullptr);
|
Client * oc = index_clients.value(id, nullptr);
|
||||||
clients_.removeOne(oc);
|
|
||||||
clients_mutex.unlock();
|
clients_mutex.unlock();
|
||||||
if (oc) {
|
if (oc) {
|
||||||
oc->stopAndWait();
|
|
||||||
oc->is_connected = false;
|
oc->is_connected = false;
|
||||||
oc->close();
|
oc->close();
|
||||||
removed_clients_ << oc;
|
|
||||||
// delete oc;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case PICloud::TCP::Data: {
|
case PICloud::TCP::Data: {
|
||||||
@@ -278,7 +213,7 @@ void PICloudServer::_readed(PIByteArray & ba) {
|
|||||||
clients_mutex.lock();
|
clients_mutex.lock();
|
||||||
Client * oc = index_clients.value(d.first, nullptr);
|
Client * oc = index_clients.value(d.first, nullptr);
|
||||||
clients_mutex.unlock();
|
clients_mutex.unlock();
|
||||||
// piCoutObj << "data for" << d.first << d.second.size();
|
//piCoutObj << "data for" << d.first << d.second.toHex();
|
||||||
if (oc && !d.second.isEmpty()) oc->pushBuffer(d.second);
|
if (oc && !d.second.isEmpty()) oc->pushBuffer(d.second);
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
@@ -289,10 +224,15 @@ void PICloudServer::_readed(PIByteArray & ba) {
|
|||||||
|
|
||||||
void PICloudServer::clientDeleted(PIObject * o) {
|
void PICloudServer::clientDeleted(PIObject * o) {
|
||||||
PICloudServer::Client * c = (PICloudServer::Client*)o;
|
PICloudServer::Client * c = (PICloudServer::Client*)o;
|
||||||
// piCoutObj << "clientDeleted" << c;
|
|
||||||
clients_mutex.lock();
|
clients_mutex.lock();
|
||||||
clients_.removeOne(c);
|
clients_.removeOne(c);
|
||||||
removed_clients_.removeAll(c);
|
auto it = index_clients.makeIterator();
|
||||||
index_clients.removeWhere([c](uint, Client * v) { return v == c; });
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
if (it.value() == c) {
|
||||||
|
index_clients.remove(it.key());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
clients_mutex.unlock();
|
clients_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "picloudtcp.h"
|
#include "picloudtcp.h"
|
||||||
|
|
||||||
#include "pichunkstream.h"
|
|
||||||
#include "picrypt.h"
|
#include "picrypt.h"
|
||||||
|
#include "pichunkstream.h"
|
||||||
#include "piethernet.h"
|
#include "piethernet.h"
|
||||||
#include "pistreampacker.h"
|
#include "pistreampacker.h"
|
||||||
|
|
||||||
@@ -44,8 +43,7 @@ void PICloud::TCP::setRole(PICloud::TCP::Role r) {
|
|||||||
|
|
||||||
void PICloud::TCP::setServerName(const PIString & server_name_) {
|
void PICloud::TCP::setServerName(const PIString & server_name_) {
|
||||||
server_name = server_name_;
|
server_name = server_name_;
|
||||||
suuid =
|
suuid = PICrypt::hash(PIByteArray(server_name_.data(), server_name_.size()), (const unsigned char *)hash_cloud_key, sizeof(hash_cloud_key));
|
||||||
PICrypt::hash(PIByteArray(server_name_.data(), server_name_.size()), (const unsigned char *)hash_cloud_key, sizeof(hash_cloud_key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -134,8 +132,7 @@ PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteA
|
|||||||
PICloud::TCP::Header hdr;
|
PICloud::TCP::Header hdr;
|
||||||
ba >> hdr;
|
ba >> hdr;
|
||||||
if (hdr.version != header.version) {
|
if (hdr.version != header.version) {
|
||||||
piCout << "[PICloud]"
|
piCout << "[PICloud]" << "invalid PICloud::TCP version!";
|
||||||
<< "invalid PICloud::TCP version!";
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret.first = (Type)hdr.type;
|
ret.first = (Type)hdr.type;
|
||||||
@@ -171,14 +168,14 @@ PIByteArray PICloud::TCP::parseConnect_d(PIByteArray & ba) {
|
|||||||
|
|
||||||
|
|
||||||
uint PICloud::TCP::parseConnect(PIByteArray & ba) {
|
uint PICloud::TCP::parseConnect(PIByteArray & ba) {
|
||||||
uint ret = 0;
|
uint ret;
|
||||||
ba >> ret;
|
ba >> ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint PICloud::TCP::parseDisconnect(PIByteArray & ba) {
|
uint PICloud::TCP::parseDisconnect(PIByteArray & ba) {
|
||||||
uint ret = 0;
|
uint ret;
|
||||||
ba >> ret;
|
ba >> ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,16 +38,14 @@ PIByteArray piCompress(const PIByteArray & ba, int level) {
|
|||||||
ulong sz = zba.size();
|
ulong sz = zba.size();
|
||||||
ret = compress2(zba.data(), &sz, ba.data(), ba.size(), level);
|
ret = compress2(zba.data(), &sz, ba.data(), ba.size(), level);
|
||||||
if (ret != Z_OK) {
|
if (ret != Z_OK) {
|
||||||
piCout << "[PICompress]"
|
piCout << "[PICompress]" << "Error: invalid input or not enought memory";
|
||||||
<< "Error: invalid input or not enought memory";
|
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
zba.resize(sz);
|
zba.resize(sz);
|
||||||
zba << ullong(ba.size());
|
zba << ullong(ba.size());
|
||||||
return zba;
|
return zba;
|
||||||
#else
|
#else
|
||||||
piCout << "[PICompress]"
|
piCout << "[PICompress]" << "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library";
|
||||||
<< "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library";
|
|
||||||
#endif
|
#endif
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
@@ -55,10 +53,9 @@ PIByteArray piCompress(const PIByteArray & ba, int level) {
|
|||||||
|
|
||||||
PIByteArray piDecompress(const PIByteArray & zba) {
|
PIByteArray piDecompress(const PIByteArray & zba) {
|
||||||
#ifdef PIP_COMPRESS
|
#ifdef PIP_COMPRESS
|
||||||
ullong sz = 0;
|
ullong sz;
|
||||||
if (zba.size() < sizeof(ullong)) {
|
if (zba.size() < sizeof(ullong)) {
|
||||||
piCout << "[PICompress]"
|
piCout << "[PICompress]" << "Error: invalid input";
|
||||||
<< "Error: invalid input";
|
|
||||||
return zba;
|
return zba;
|
||||||
}
|
}
|
||||||
PIByteArray ba(zba.data(zba.size() - sizeof(ullong)), sizeof(ullong));
|
PIByteArray ba(zba.data(zba.size() - sizeof(ullong)), sizeof(ullong));
|
||||||
@@ -68,14 +65,12 @@ PIByteArray piDecompress(const PIByteArray & zba) {
|
|||||||
ulong s = sz;
|
ulong s = sz;
|
||||||
ret = uncompress(ba.data(), &s, zba.data(), zba.size());
|
ret = uncompress(ba.data(), &s, zba.data(), zba.size());
|
||||||
if (ret != Z_OK) {
|
if (ret != Z_OK) {
|
||||||
piCout << "[PICompress]"
|
piCout << "[PICompress]" << "Error: invalid input or not enought memory";
|
||||||
<< "Error: invalid input or not enought memory";
|
|
||||||
return zba;
|
return zba;
|
||||||
}
|
}
|
||||||
return ba;
|
return ba;
|
||||||
#else
|
#else
|
||||||
piCout << "[PICompress]"
|
piCout << "[PICompress]" << "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library";
|
||||||
<< "Warning: PICompress is disabled, to enable install zlib library and build pip_compress library";
|
|
||||||
#endif
|
#endif
|
||||||
return zba;
|
return zba;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,14 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "piscreen.h"
|
#include "piscreen.h"
|
||||||
|
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
# include <fcntl.h>
|
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
|
# include <fcntl.h>
|
||||||
# include <termios.h>
|
# include <termios.h>
|
||||||
#else
|
#else
|
||||||
# include <wincon.h>
|
|
||||||
# include <wingdi.h>
|
# include <wingdi.h>
|
||||||
|
# include <wincon.h>
|
||||||
# ifndef COMMON_LVB_UNDERSCORE
|
# ifndef COMMON_LVB_UNDERSCORE
|
||||||
# define COMMON_LVB_UNDERSCORE 0x8000
|
# define COMMON_LVB_UNDERSCORE 0x8000
|
||||||
# endif
|
# endif
|
||||||
@@ -52,18 +51,6 @@ PRIVATE_DEFINITION_END(PIScreen::SystemConsole)
|
|||||||
PIScreen::SystemConsole::SystemConsole() {
|
PIScreen::SystemConsole::SystemConsole() {
|
||||||
width = height = pwidth = pheight = 0;
|
width = height = pwidth = pheight = 0;
|
||||||
mouse_x = mouse_y = -1;
|
mouse_x = mouse_y = -1;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIScreen::SystemConsole::~SystemConsole() {
|
|
||||||
#ifdef WINDOWS
|
|
||||||
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
|
|
||||||
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIScreen::SystemConsole::begin() {
|
|
||||||
int w, h;
|
int w, h;
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
PRIVATE->ulcoord.X = 0;
|
PRIVATE->ulcoord.X = 0;
|
||||||
@@ -87,6 +74,18 @@ void PIScreen::SystemConsole::begin() {
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
resize(w, h);
|
resize(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIScreen::SystemConsole::~SystemConsole() {
|
||||||
|
#ifdef WINDOWS
|
||||||
|
SetConsoleMode(PRIVATE->hOut, PRIVATE->smode);
|
||||||
|
SetConsoleTextAttribute(PRIVATE->hOut, PRIVATE->dattr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIScreen::SystemConsole::begin() {
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
|
SetConsoleMode(PRIVATE->hOut, ENABLE_WRAP_AT_EOL_OUTPUT);
|
||||||
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
||||||
@@ -94,7 +93,6 @@ void PIScreen::SystemConsole::begin() {
|
|||||||
PRIVATE->bc.Y = 0;
|
PRIVATE->bc.Y = 0;
|
||||||
#endif
|
#endif
|
||||||
clear();
|
clear();
|
||||||
clearScreen();
|
|
||||||
hideCursor();
|
hideCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,14 +243,10 @@ void PIScreen::SystemConsole::print() {
|
|||||||
#define BACKGROUND_MASK (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
|
#define BACKGROUND_MASK (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
|
||||||
ushort PIScreen::SystemConsole::attributes(const PIScreenTypes::Cell & c) {
|
ushort PIScreen::SystemConsole::attributes(const PIScreenTypes::Cell & c) {
|
||||||
WORD attr = PRIVATE->dattr;
|
WORD attr = PRIVATE->dattr;
|
||||||
if (c.format.flags & Bold)
|
if (c.format.flags & Bold) attr |= FOREGROUND_INTENSITY;
|
||||||
attr |= FOREGROUND_INTENSITY;
|
else attr &= ~FOREGROUND_INTENSITY;
|
||||||
else
|
if (c.format.flags & Underline) attr |= COMMON_LVB_UNDERSCORE;
|
||||||
attr &= ~FOREGROUND_INTENSITY;
|
else attr &= ~COMMON_LVB_UNDERSCORE;
|
||||||
if (c.format.flags & Underline)
|
|
||||||
attr |= COMMON_LVB_UNDERSCORE;
|
|
||||||
else
|
|
||||||
attr &= ~COMMON_LVB_UNDERSCORE;
|
|
||||||
switch (c.format.color_char) {
|
switch (c.format.color_char) {
|
||||||
case Black: attr = (attr & ~FOREGROUND_MASK); break;
|
case Black: attr = (attr & ~FOREGROUND_MASK); break;
|
||||||
case Red: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED; break;
|
case Red: attr = (attr & ~FOREGROUND_MASK) | FOREGROUND_RED; break;
|
||||||
@@ -297,8 +291,7 @@ void PIScreen::SystemConsole::clearLine() {
|
|||||||
|
|
||||||
void PIScreen::SystemConsole::newLine() {
|
void PIScreen::SystemConsole::newLine() {
|
||||||
getWinCurCoord();
|
getWinCurCoord();
|
||||||
PRIVATE->ccoord.X = 0;
|
PRIVATE->ccoord.X = 0; PRIVATE->ccoord.Y++;
|
||||||
PRIVATE->ccoord.Y++;
|
|
||||||
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
|
SetConsoleCursorPosition(PRIVATE->hOut, PRIVATE->ccoord);
|
||||||
}
|
}
|
||||||
#else // WINDOWS
|
#else // WINDOWS
|
||||||
@@ -364,16 +357,8 @@ void PIScreen::SystemConsole::clearScreen() {
|
|||||||
void PIScreen::SystemConsole::clearScreenLower() {
|
void PIScreen::SystemConsole::clearScreenLower() {
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
getWinCurCoord();
|
getWinCurCoord();
|
||||||
FillConsoleOutputAttribute(PRIVATE->hOut,
|
FillConsoleOutputAttribute(PRIVATE->hOut, PRIVATE->dattr, width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
|
||||||
PRIVATE->dattr,
|
FillConsoleOutputCharacter(PRIVATE->hOut, ' ', width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X, PRIVATE->ccoord, &PRIVATE->written);
|
||||||
width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X,
|
|
||||||
PRIVATE->ccoord,
|
|
||||||
&PRIVATE->written);
|
|
||||||
FillConsoleOutputCharacter(PRIVATE->hOut,
|
|
||||||
' ',
|
|
||||||
width * height - width * PRIVATE->ccoord.Y + PRIVATE->ccoord.X,
|
|
||||||
PRIVATE->ccoord,
|
|
||||||
&PRIVATE->written);
|
|
||||||
#else
|
#else
|
||||||
printf("\e[0m\e[J");
|
printf("\e[0m\e[J");
|
||||||
#endif
|
#endif
|
||||||
@@ -398,7 +383,7 @@ void PIScreen::SystemConsole::showCursor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// PIScreen
|
|
||||||
|
|
||||||
PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawer_(console.cells), root("rootTile") {
|
PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawer_(console.cells), root("rootTile") {
|
||||||
setName("screen");
|
setName("screen");
|
||||||
@@ -406,17 +391,18 @@ PIScreen::PIScreen(bool startNow, PIKbdListener::KBFunc slot): PIThread(), drawe
|
|||||||
needLockRun(true);
|
needLockRun(true);
|
||||||
mouse_ = false;
|
mouse_ = false;
|
||||||
ret_func = slot;
|
ret_func = slot;
|
||||||
tile_focus = tile_dialog = nullptr;
|
tile_focus = tile_dialog = 0;
|
||||||
root.screen = this;
|
root.screen = this;
|
||||||
listener = new PIKbdListener(key_eventS, this, startNow);
|
listener = new PIKbdListener(key_eventS, this, startNow);
|
||||||
CONNECT1(void, PIKbdListener::MouseEvent, listener, mouseEvent, this, mouse_event);
|
CONNECTU(listener, mouseEvent, this, mouse_event);
|
||||||
CONNECT1(void, PIKbdListener::WheelEvent, listener, wheelEvent, this, wheel_event);
|
CONNECTU(listener, wheelEvent, this, wheel_event);
|
||||||
if (startNow) start();
|
if (startNow) start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIScreen::~PIScreen() {
|
PIScreen::~PIScreen() {
|
||||||
if (isRunning()) stop();
|
if (isRunning())
|
||||||
|
stop();
|
||||||
PIThread::waitForFinish(10);
|
PIThread::waitForFinish(10);
|
||||||
listener->waitForFinish(10);
|
listener->waitForFinish(10);
|
||||||
delete listener;
|
delete listener;
|
||||||
@@ -436,12 +422,14 @@ void PIScreen::key_event(PIKbdListener::KeyEvent key) {
|
|||||||
return;
|
return;
|
||||||
*/
|
*/
|
||||||
PIScreenTile * rtile = rootTile();
|
PIScreenTile * rtile = rootTile();
|
||||||
if (tile_dialog) rtile = tile_dialog;
|
if (tile_dialog)
|
||||||
|
rtile = tile_dialog;
|
||||||
bool used = nextFocus(rtile, key);
|
bool used = nextFocus(rtile, key);
|
||||||
if (used) return;
|
if (used) return;
|
||||||
if (!used && tile_focus) {
|
if (!used && tile_focus) {
|
||||||
if (tile_focus->visible) {
|
if (tile_focus->visible) {
|
||||||
if (tile_focus->keyEvent(key)) return;
|
if (tile_focus->keyEvent(key))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret_func != 0) ret_func(key, data_);
|
if (ret_func != 0) ret_func(key, data_);
|
||||||
@@ -467,6 +455,7 @@ PIVector<PIScreenTile *> PIScreen::prepareMouse(PIKbdListener::MouseEvent * e) {
|
|||||||
ff = true;
|
ff = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return tl;
|
return tl;
|
||||||
}
|
}
|
||||||
@@ -499,13 +488,15 @@ void PIScreen::wheel_event(PIKbdListener::WheelEvent we) {
|
|||||||
if (tl.isEmpty()) return;
|
if (tl.isEmpty()) return;
|
||||||
piForeachR (PIScreenTile * t, tl)
|
piForeachR (PIScreenTile * t, tl)
|
||||||
if (t->wheelEvent(we)) break;
|
if (t->wheelEvent(we)) break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIScreen::nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key) {
|
bool PIScreen::nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key) {
|
||||||
PIVector<PIScreenTile*> vtl = rt->children(true), ftl;
|
PIVector<PIScreenTile*> vtl = rt->children(true), ftl;
|
||||||
piForeach (PIScreenTile * t, vtl) {
|
piForeach (PIScreenTile * t, vtl) {
|
||||||
if (t->focus_flags[CanHasFocus]) ftl << t;
|
if (t->focus_flags[CanHasFocus])
|
||||||
|
ftl << t;
|
||||||
}
|
}
|
||||||
int ind = -1;
|
int ind = -1;
|
||||||
for (int i = 0; i < ftl.size_s(); ++i)
|
for (int i = 0; i < ftl.size_s(); ++i)
|
||||||
@@ -513,15 +504,18 @@ bool PIScreen::nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key) {
|
|||||||
ind = i;
|
ind = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ind < 0) tile_focus = 0;
|
if (ind < 0)
|
||||||
|
tile_focus = 0;
|
||||||
if (ftl.isEmpty())
|
if (ftl.isEmpty())
|
||||||
tile_focus = 0;
|
tile_focus = 0;
|
||||||
else {
|
else {
|
||||||
if (tile_focus)
|
if (tile_focus)
|
||||||
if (!tile_focus->visible) tile_focus = 0;
|
if (!tile_focus->visible)
|
||||||
|
tile_focus = 0;
|
||||||
int next = tile_focus ? 0 : 1;
|
int next = tile_focus ? 0 : 1;
|
||||||
if (tile_focus) {
|
if (tile_focus) {
|
||||||
if (tile_focus->focus_flags[NextByTab] && key.key == PIKbdListener::Tab) next = 1;
|
if (tile_focus->focus_flags[NextByTab] && key.key == PIKbdListener::Tab)
|
||||||
|
next = 1;
|
||||||
if (tile_focus->focus_flags[NextByArrowsHorizontal]) {
|
if (tile_focus->focus_flags[NextByArrowsHorizontal]) {
|
||||||
if (key.key == PIKbdListener::LeftArrow) next = -1;
|
if (key.key == PIKbdListener::LeftArrow) next = -1;
|
||||||
if (key.key == PIKbdListener::RightArrow) next = 1;
|
if (key.key == PIKbdListener::RightArrow) next = 1;
|
||||||
@@ -556,19 +550,22 @@ void PIScreen::tileEventInternal(PIScreenTile * t, TileEvent e) {
|
|||||||
|
|
||||||
|
|
||||||
void PIScreen::tileRemovedInternal(PIScreenTile * t) {
|
void PIScreen::tileRemovedInternal(PIScreenTile * t) {
|
||||||
if (tile_dialog == t) tile_dialog = 0;
|
if (tile_dialog == t)
|
||||||
|
tile_dialog = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIScreen::tileSetFocusInternal(PIScreenTile * t) {
|
void PIScreen::tileSetFocusInternal(PIScreenTile * t) {
|
||||||
PIScreenTile * rt = rootTile();
|
PIScreenTile * rt = rootTile();
|
||||||
if (tile_dialog) rt = tile_dialog;
|
if (tile_dialog)
|
||||||
|
rt = tile_dialog;
|
||||||
PIVector<PIScreenTile*> tl = rt->children(), ftl;
|
PIVector<PIScreenTile*> tl = rt->children(), ftl;
|
||||||
piForeach (PIScreenTile * i, tl)
|
piForeach (PIScreenTile * i, tl)
|
||||||
i->has_focus = false;
|
i->has_focus = false;
|
||||||
tile_focus = t;
|
tile_focus = t;
|
||||||
if (!tile_focus) return;
|
if (!tile_focus) return;
|
||||||
if (tile_focus->focus_flags[CanHasFocus]) tile_focus->has_focus = true;
|
if (tile_focus->focus_flags[CanHasFocus])
|
||||||
|
tile_focus->has_focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -591,7 +588,7 @@ void PIScreen::waitForFinish() {
|
|||||||
|
|
||||||
|
|
||||||
void PIScreen::stop(bool clear) {
|
void PIScreen::stop(bool clear) {
|
||||||
PIThread::stopAndWait();
|
PIThread::stop(true);
|
||||||
if (clear) console.clearScreen();
|
if (clear) console.clearScreen();
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
fflush(0);
|
fflush(0);
|
||||||
@@ -623,13 +620,8 @@ void PIScreen::run() {
|
|||||||
tile_dialog->height_ = sh;
|
tile_dialog->height_ = sh;
|
||||||
tile_dialog->layout();
|
tile_dialog->layout();
|
||||||
int dx = tile_dialog->x_ - 1, dy = tile_dialog->y_ - 1, dw = tile_dialog->width_, dh = tile_dialog->height_;
|
int dx = tile_dialog->x_ - 1, dy = tile_dialog->y_ - 1, dw = tile_dialog->width_, dh = tile_dialog->height_;
|
||||||
drawer_.drawFrame(dx,
|
drawer_.drawFrame(dx, dy, dx + dw + 1, dy + dh + 1, (Color)tile_dialog->back_format.color_char,
|
||||||
dy,
|
(Color)tile_dialog->back_format.color_back, (CharFlags)tile_dialog->back_format.flags);
|
||||||
dx + dw + 1,
|
|
||||||
dy + dh + 1,
|
|
||||||
(Color)tile_dialog->back_format.color_char,
|
|
||||||
(Color)tile_dialog->back_format.color_back,
|
|
||||||
(CharFlags)tile_dialog->back_format.flags);
|
|
||||||
tile_dialog->drawEventInternal(&drawer_);
|
tile_dialog->drawEventInternal(&drawer_);
|
||||||
}
|
}
|
||||||
console.print();
|
console.print();
|
||||||
@@ -645,6 +637,8 @@ void PIScreen::end() {
|
|||||||
PIScreenTile * PIScreen::tileByName(const PIString & name) {
|
PIScreenTile * PIScreen::tileByName(const PIString & name) {
|
||||||
PIVector<PIScreenTile*> tl(tiles());
|
PIVector<PIScreenTile*> tl(tiles());
|
||||||
piForeach (PIScreenTile * t, tl)
|
piForeach (PIScreenTile * t, tl)
|
||||||
if (t->name() == name) return t;
|
if (t->name() == name)
|
||||||
|
return t;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,16 @@ TileVars::TileVars(const PIString & n): PIScreenTile(n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TileVars::sizeHint(int & w, int & h) const {}
|
void TileVars::sizeHint(int &w, int &h) const {
|
||||||
|
|
||||||
void TileVars::drawEvent(PIScreenDrawer * d) {}
|
}
|
||||||
|
|
||||||
|
void TileVars::drawEvent(PIScreenDrawer *d) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PIScreenConsoleTile::PIScreenConsoleTile() {}
|
PIScreenConsoleTile::PIScreenConsoleTile() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,24 +117,26 @@ void PIScreenDrawer::drawLine(int x0, int y0, int x1, int y1, const PIChar & c,
|
|||||||
float dy = (y1 - y0) / float(piAbsi(x1 - x0)), cy = y0;
|
float dy = (y1 - y0) / float(piAbsi(x1 - x0)), cy = y0;
|
||||||
int dx = x0 < x1 ? 1 : -1;
|
int dx = x0 < x1 ? 1 : -1;
|
||||||
for (int i = x0; i != x1; i += dx) {
|
for (int i = x0; i != x1; i += dx) {
|
||||||
x = i;
|
x = i; y = piRound(cy);
|
||||||
y = piRound(cy);
|
if (x >= 0 && x < width && y >= 0 && y < height)
|
||||||
if (x >= 0 && x < width && y >= 0 && y < height) cells[y][x] = cc;
|
cells[y][x] = cc;
|
||||||
cy += dy;
|
cy += dy;
|
||||||
}
|
}
|
||||||
y = piRound(cy);
|
y = piRound(cy);
|
||||||
if (x1 >= 0 && x1 < width && y >= 0 && y < height) cells[y][x1] = cc;
|
if (x1 >= 0 && x1 < width && y >= 0 && y < height)
|
||||||
|
cells[y][x1] = cc;
|
||||||
} else {
|
} else {
|
||||||
float dx = (x1 - x0) / float(piAbsi(y1 - y0)), cx = x0;
|
float dx = (x1 - x0) / float(piAbsi(y1 - y0)), cx = x0;
|
||||||
int dy = y0 < y1 ? 1 : -1;
|
int dy = y0 < y1 ? 1 : -1;
|
||||||
for (int i = y0; i != y1; i += dy) {
|
for (int i = y0; i != y1; i += dy) {
|
||||||
x = piRound(cx);
|
x = piRound(cx); y = i;
|
||||||
y = i;
|
if (x >= 0 && x < width && y >= 0 && y < height)
|
||||||
if (x >= 0 && x < width && y >= 0 && y < height) cells[y][x] = cc;
|
cells[y][x] = cc;
|
||||||
cx += dx;
|
cx += dx;
|
||||||
}
|
}
|
||||||
x = piRound(cx);
|
x = piRound(cx);
|
||||||
if (x >= 0 && x < width && y1 >= 0 && y1 < height) cells[y1][x] = cc;
|
if (x >= 0 && x < width && y1 >= 0 && y1 < height)
|
||||||
|
cells[y1][x] = cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,16 +157,19 @@ void PIScreenDrawer::drawRect(int x0, int y0, int x1, int y1, const PIChar & c,
|
|||||||
if (j >= 0 && j < height) {
|
if (j >= 0 && j < height) {
|
||||||
PIVector<Cell> & cv(cells[j]);
|
PIVector<Cell> & cv(cells[j]);
|
||||||
for (int i = x0; i != x1; i += dx)
|
for (int i = x0; i != x1; i += dx)
|
||||||
if (i >= 0 && i < width) cv[i] = cc;
|
if (i >= 0 && i < width)
|
||||||
|
cv[i] = cc;
|
||||||
}
|
}
|
||||||
j = xs[k];
|
j = xs[k];
|
||||||
if (j >= 0 && j < width) {
|
if (j >= 0 && j < width) {
|
||||||
for (int i = y0; i != y1; i += dy)
|
for (int i = y0; i != y1; i += dy)
|
||||||
if (i >= 0 && i < height) cells[i][j] = cc;
|
if (i >= 0 && i < height)
|
||||||
|
cells[i][j] = cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int i = x1, j = y1;
|
int i = x1, j = y1;
|
||||||
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
if (i >= 0 && i < width && j >= 0 && j < height)
|
||||||
|
cells[j][i] = cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -184,26 +189,24 @@ void PIScreenDrawer::drawFrame(int x0, int y0, int x1, int y1, Color col_char, C
|
|||||||
PIVector<Cell> & cv(cells[j]);
|
PIVector<Cell> & cv(cells[j]);
|
||||||
cc.symbol = artChar(LineHorizontal);
|
cc.symbol = artChar(LineHorizontal);
|
||||||
for (int i = x0 + 1; i != x1; i += dx)
|
for (int i = x0 + 1; i != x1; i += dx)
|
||||||
if (i >= 0 && i < width) cv[i] = cc;
|
if (i >= 0 && i < width)
|
||||||
|
cv[i] = cc;
|
||||||
}
|
}
|
||||||
j = xs[k];
|
j = xs[k];
|
||||||
if (j >= 0 && j < width) {
|
if (j >= 0 && j < width) {
|
||||||
cc.symbol = artChar(LineVertical);
|
cc.symbol = artChar(LineVertical);
|
||||||
for (int i = y0 + 1; i != y1; i += dy)
|
for (int i = y0 + 1; i != y1; i += dy)
|
||||||
if (i >= 0 && i < height) cells[i][j] = cc;
|
if (i >= 0 && i < height)
|
||||||
|
cells[i][j] = cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int i = x0, j = y0;
|
int i = x0, j = y0; cc.symbol = artChar(CornerTopLeft);
|
||||||
cc.symbol = artChar(CornerTopLeft);
|
|
||||||
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
||||||
i = x1, j = y0;
|
i = x1, j = y0; cc.symbol = artChar(CornerTopRight);
|
||||||
cc.symbol = artChar(CornerTopRight);
|
|
||||||
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
||||||
i = x0, j = y1;
|
i = x0, j = y1; cc.symbol = artChar(CornerBottomLeft);
|
||||||
cc.symbol = artChar(CornerBottomLeft);
|
|
||||||
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
||||||
i = x1, j = y1;
|
i = x1, j = y1; cc.symbol = artChar(CornerBottomRight);
|
||||||
cc.symbol = artChar(CornerBottomRight);
|
|
||||||
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
if (i >= 0 && i < width && j >= 0 && j < height) cells[j][i] = cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +224,8 @@ void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, const PIChar & c,
|
|||||||
if (j >= 0 && j < height) {
|
if (j >= 0 && j < height) {
|
||||||
PIVector<Cell> & cv(cells[j]);
|
PIVector<Cell> & cv(cells[j]);
|
||||||
for (int i = x0; i != x1; i += dx)
|
for (int i = x0; i != x1; i += dx)
|
||||||
if (i >= 0 && i < width) cv[i] = cc;
|
if (i >= 0 && i < width)
|
||||||
|
cv[i] = cc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +241,8 @@ void PIScreenDrawer::fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<
|
|||||||
PIVector<Cell> & cv(cells[y0 + j]);
|
PIVector<Cell> & cv(cells[y0 + j]);
|
||||||
PIVector<Cell> & contv(content[j]);
|
PIVector<Cell> & contv(content[j]);
|
||||||
for (int i = 0; i < piMini(w, contv.size_s()); ++i)
|
for (int i = 0; i < piMini(w, contv.size_s()); ++i)
|
||||||
if ((i + x0) >= 0 && (i + x0) < width) cv[x0 + i] = contv[i];
|
if ((i + x0) >= 0 && (i + x0) < width)
|
||||||
|
cv[x0 + i] = contv[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "piscreentile.h"
|
#include "piscreentile.h"
|
||||||
|
|
||||||
#include "piscreendrawer.h"
|
#include "piscreendrawer.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -42,7 +41,8 @@ PIScreenTile::PIScreenTile(const PIString & n, Direction d, SizePolicy p): PIObj
|
|||||||
|
|
||||||
PIScreenTile::~PIScreenTile() {
|
PIScreenTile::~PIScreenTile() {
|
||||||
//piCout << this << "~";
|
//piCout << this << "~";
|
||||||
if (screen) screen->tileRemovedInternal(this);
|
if (screen)
|
||||||
|
screen->tileRemovedInternal(this);
|
||||||
setScreen(0);
|
setScreen(0);
|
||||||
deleteChildren();
|
deleteChildren();
|
||||||
if (!parent) return;
|
if (!parent) return;
|
||||||
@@ -79,7 +79,8 @@ void PIScreenTile::removeTile(PIScreenTile * t) {
|
|||||||
PIVector<PIScreenTile * > PIScreenTile::children(bool only_visible) {
|
PIVector<PIScreenTile * > PIScreenTile::children(bool only_visible) {
|
||||||
PIVector<PIScreenTile * > ret;
|
PIVector<PIScreenTile * > ret;
|
||||||
piForeach (PIScreenTile * t, tiles)
|
piForeach (PIScreenTile * t, tiles)
|
||||||
if (t->visible || !only_visible) ret << t << t->children(only_visible);
|
if (t->visible || !only_visible)
|
||||||
|
ret << t << t->children(only_visible);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +88,8 @@ PIVector<PIScreenTile *> PIScreenTile::children(bool only_visible) {
|
|||||||
PIScreenTile * PIScreenTile::childUnderMouse(int x, int y) {
|
PIScreenTile * PIScreenTile::childUnderMouse(int x, int y) {
|
||||||
piForeach (PIScreenTile * t, tiles) {
|
piForeach (PIScreenTile * t, tiles) {
|
||||||
if (!t->visible) continue;
|
if (!t->visible) continue;
|
||||||
if (x >= t->x_ && (x - t->x_) < t->width_ && y >= t->y_ && (y - t->y_) < t->height_) {
|
if (x >= t->x_ && (x - t->x_) < t->width_ &&
|
||||||
|
y >= t->y_ && (y - t->y_) < t->height_) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,14 +129,7 @@ void PIScreenTile::drawEventInternal(PIScreenDrawer * d) {
|
|||||||
if (!visible) {
|
if (!visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
d->fillRect(x_,
|
d->fillRect(x_, y_, x_ + width_, y_ + height_, back_symbol, (Color)back_format.color_char, (Color)back_format.color_back, back_format.flags);
|
||||||
y_,
|
|
||||||
x_ + width_,
|
|
||||||
y_ + height_,
|
|
||||||
back_symbol,
|
|
||||||
(Color)back_format.color_char,
|
|
||||||
(Color)back_format.color_back,
|
|
||||||
back_format.flags);
|
|
||||||
drawEvent(d);
|
drawEvent(d);
|
||||||
piForeach (PIScreenTile * t, tiles)
|
piForeach (PIScreenTile * t, tiles)
|
||||||
t->drawEventInternal(d);
|
t->drawEventInternal(d);
|
||||||
@@ -146,10 +141,8 @@ void PIScreenTile::sizeHint(int & w, int & h) const {
|
|||||||
h = 0;
|
h = 0;
|
||||||
if (tiles.isEmpty()) return;
|
if (tiles.isEmpty()) return;
|
||||||
int sl = spacing * (tiles.size_s() - 1);
|
int sl = spacing * (tiles.size_s() - 1);
|
||||||
if (direction == Horizontal)
|
if (direction == Horizontal) w += sl;
|
||||||
w += sl;
|
else h += sl;
|
||||||
else
|
|
||||||
h += sl;
|
|
||||||
piForeachC (PIScreenTile * t, tiles) {
|
piForeachC (PIScreenTile * t, tiles) {
|
||||||
if (!t->visible) continue;
|
if (!t->visible) continue;
|
||||||
int cw(0), ch(0);
|
int cw(0), ch(0);
|
||||||
@@ -157,11 +150,9 @@ void PIScreenTile::sizeHint(int & w, int & h) const {
|
|||||||
cw = piClampi(cw, t->minimumWidth, t->maximumWidth);
|
cw = piClampi(cw, t->minimumWidth, t->maximumWidth);
|
||||||
ch = piClampi(ch, t->minimumHeight, t->maximumHeight);
|
ch = piClampi(ch, t->minimumHeight, t->maximumHeight);
|
||||||
if (direction == Horizontal) {
|
if (direction == Horizontal) {
|
||||||
w += cw;
|
w += cw; h = piMaxi(h, ch);
|
||||||
h = piMaxi(h, ch);
|
|
||||||
} else {
|
} else {
|
||||||
h += ch;
|
h += ch; w = piMaxi(w, cw);
|
||||||
w = piMaxi(w, cw);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w += marginLeft + marginRight;
|
w += marginLeft + marginRight;
|
||||||
@@ -219,7 +210,8 @@ void PIScreenTile::layout() {
|
|||||||
for (int j = 0; j < tiles.size_s(); ++j) {
|
for (int j = 0; j < tiles.size_s(); ++j) {
|
||||||
if (i == j) continue;
|
if (i == j) continue;
|
||||||
if (max_tl[j]) continue;
|
if (max_tl[j]) continue;
|
||||||
if (tiles[j]->size_policy == pol && tiles[j]->visible && tiles[j]->needLayout()) asizes[j] += pas;
|
if (tiles[j]->size_policy == pol && tiles[j]->visible && tiles[j]->needLayout())
|
||||||
|
asizes[j] += pas;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,7 +241,8 @@ void PIScreenTile::layout() {
|
|||||||
t->height_ = hints[i];
|
t->height_ = hints[i];
|
||||||
cy += hints[i] + spacing;
|
cy += hints[i] + spacing;
|
||||||
}
|
}
|
||||||
if (t->pw != t->width_ || t->ph != t->height_) t->resizeEvent(t->width_, t->height_);
|
if (t->pw != t->width_ || t->ph != t->height_)
|
||||||
|
t->resizeEvent(t->width_, t->height_);
|
||||||
t->pw = t->width_;
|
t->pw = t->width_;
|
||||||
t->ph = t->height_;
|
t->ph = t->height_;
|
||||||
t->layout();
|
t->layout();
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "piscreentiles.h"
|
#include "piscreentiles.h"
|
||||||
|
|
||||||
#include "piscreendrawer.h"
|
#include "piscreendrawer.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@ void TileSimple::drawEvent(PIScreenDrawer * d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TileScrollBar
|
|
||||||
|
|
||||||
TileScrollBar::TileScrollBar(const PIString & n) {
|
TileScrollBar::TileScrollBar(const PIString & n) {
|
||||||
direction = Vertical;
|
direction = Vertical;
|
||||||
@@ -123,7 +122,7 @@ bool TileScrollBar::mouseEvent(PIKbdListener::MouseEvent me) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TileList
|
|
||||||
|
|
||||||
TileList::TileList(const PIString & n, SelectionMode sm): PIScreenTile(n) {
|
TileList::TileList(const PIString & n, SelectionMode sm): PIScreenTile(n) {
|
||||||
alignment = Left;
|
alignment = Left;
|
||||||
@@ -189,7 +188,9 @@ bool TileList::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
lhei = height_ - 2;
|
lhei = height_ - 2;
|
||||||
int oo(0), osp = piMini(3, lhei / 4);
|
int oo(0), osp = piMini(3, lhei / 4);
|
||||||
switch (key.key) {
|
switch (key.key) {
|
||||||
case PIKbdListener::PageUp: cur -= lhei / 2; oo -= lhei / 2;
|
case PIKbdListener::PageUp:
|
||||||
|
cur -= lhei / 2;
|
||||||
|
oo -= lhei / 2;
|
||||||
case PIKbdListener::UpArrow:
|
case PIKbdListener::UpArrow:
|
||||||
cur--;
|
cur--;
|
||||||
oo--;
|
oo--;
|
||||||
@@ -206,8 +207,7 @@ bool TileList::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
switch (selection_mode) {
|
switch (selection_mode) {
|
||||||
case NoSelection: return false;
|
case NoSelection: return false;
|
||||||
case SingleSelection:
|
case SingleSelection:
|
||||||
if (selected.isEmpty())
|
if (selected.isEmpty()) selected << cur;
|
||||||
selected << cur;
|
|
||||||
else {
|
else {
|
||||||
bool add = !selected[cur];
|
bool add = !selected[cur];
|
||||||
selected.clear();
|
selected.clear();
|
||||||
@@ -216,10 +216,8 @@ bool TileList::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
raiseEvent(TileEvent(SelectionChanged));
|
raiseEvent(TileEvent(SelectionChanged));
|
||||||
return true;
|
return true;
|
||||||
case MultiSelection:
|
case MultiSelection:
|
||||||
if (selected[cur])
|
if (selected[cur]) selected.remove(cur);
|
||||||
selected.remove(cur);
|
else selected << cur;
|
||||||
else
|
|
||||||
selected << cur;
|
|
||||||
raiseEvent(TileEvent(SelectionChanged));
|
raiseEvent(TileEvent(SelectionChanged));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -240,14 +238,17 @@ bool TileList::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
if (offset >= content.size_s() - lhei) offset = content.size_s() - lhei;
|
if (offset >= content.size_s() - lhei) offset = content.size_s() - lhei;
|
||||||
if (offset < 0) offset = 0;
|
if (offset < 0) offset = 0;
|
||||||
return true;
|
return true;
|
||||||
case PIKbdListener::Home: cur = offset = 0; return true;
|
case PIKbdListener::Home:
|
||||||
|
cur = offset = 0;
|
||||||
|
return true;
|
||||||
case PIKbdListener::End:
|
case PIKbdListener::End:
|
||||||
cur = content.size_s() - 1;
|
cur = content.size_s() - 1;
|
||||||
offset = content.size_s() - lhei;
|
offset = content.size_s() - lhei;
|
||||||
if (offset < 0) offset = 0;
|
if (offset < 0) offset = 0;
|
||||||
return true;
|
return true;
|
||||||
case PIKbdListener::Return:
|
case PIKbdListener::Return:
|
||||||
if (cur >= 0 && cur < content.size_s()) raiseEvent(TileEvent(RowPressed, cur));
|
if (cur >= 0 && cur < content.size_s())
|
||||||
|
raiseEvent(TileEvent(RowPressed, cur));
|
||||||
return true;
|
return true;
|
||||||
case '*':
|
case '*':
|
||||||
if (selection_mode == TileList::MultiSelection) {
|
if (selection_mode == TileList::MultiSelection) {
|
||||||
@@ -277,8 +278,12 @@ bool TileList::mouseEvent(PIKbdListener::MouseEvent me) {
|
|||||||
if (mp < 0 || mp >= content.size_s()) return true;
|
if (mp < 0 || mp >= content.size_s()) return true;
|
||||||
cur = mp;
|
cur = mp;
|
||||||
switch (me.action) {
|
switch (me.action) {
|
||||||
case PIKbdListener::MouseButtonPress: mouse_sel = !selected.contains(cur); break;
|
case PIKbdListener::MouseButtonPress:
|
||||||
case PIKbdListener::MouseButtonDblClick: keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return)); return true;
|
mouse_sel = !selected.contains(cur);
|
||||||
|
break;
|
||||||
|
case PIKbdListener::MouseButtonDblClick:
|
||||||
|
keyEvent(PIKbdListener::KeyEvent(PIKbdListener::Return));
|
||||||
|
return true;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if (me.buttons[PIKbdListener::MouseRight]) {
|
if (me.buttons[PIKbdListener::MouseRight]) {
|
||||||
@@ -289,10 +294,8 @@ bool TileList::mouseEvent(PIKbdListener::MouseEvent me) {
|
|||||||
raiseEvent(TileEvent(SelectionChanged));
|
raiseEvent(TileEvent(SelectionChanged));
|
||||||
break;
|
break;
|
||||||
case MultiSelection:
|
case MultiSelection:
|
||||||
if (mouse_sel)
|
if (mouse_sel) selected << cur;
|
||||||
selected << cur;
|
else selected.remove(cur);
|
||||||
else
|
|
||||||
selected.remove(cur);
|
|
||||||
raiseEvent(TileEvent(SelectionChanged));
|
raiseEvent(TileEvent(SelectionChanged));
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
@@ -308,7 +311,7 @@ bool TileList::wheelEvent(PIKbdListener::WheelEvent we) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TileButton
|
|
||||||
|
|
||||||
TileButton::TileButton(const PIString & n): PIScreenTile(n) {
|
TileButton::TileButton(const PIString & n): PIScreenTile(n) {
|
||||||
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
|
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
|
||||||
@@ -348,7 +351,7 @@ bool TileButton::mouseEvent(PIKbdListener::MouseEvent me) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TileButtons
|
|
||||||
|
|
||||||
TileButtons::TileButtons(const PIString & n): PIScreenTile(n) {
|
TileButtons::TileButtons(const PIString & n): PIScreenTile(n) {
|
||||||
focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
|
focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
|
||||||
@@ -384,7 +387,8 @@ void TileButtons::drawEvent(PIScreenDrawer * d) {
|
|||||||
case PIScreenTypes::Right: dx = width_ - shw; break;
|
case PIScreenTypes::Right: dx = width_ - shw; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if (direction == PIScreenTypes::Horizontal) cx += dx;
|
if (direction == PIScreenTypes::Horizontal)
|
||||||
|
cx += dx;
|
||||||
for (int i = 0; i < content.size_s(); ++i) {
|
for (int i = 0; i < content.size_s(); ++i) {
|
||||||
Color cb = Cyan;
|
Color cb = Cyan;
|
||||||
Color ct = Black;
|
Color ct = Black;
|
||||||
@@ -426,7 +430,9 @@ bool TileButtons::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
if (cur >= content.size_s()) cur = content.size_s() - 1;
|
if (cur >= content.size_s()) cur = content.size_s() - 1;
|
||||||
return true;
|
return true;
|
||||||
case PIKbdListener::Space:
|
case PIKbdListener::Space:
|
||||||
case PIKbdListener::Return: raiseEvent(TileEvent(ButtonSelected, cur)); return true;
|
case PIKbdListener::Return:
|
||||||
|
raiseEvent(TileEvent(ButtonSelected, cur));
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
return PIScreenTile::keyEvent(key);
|
return PIScreenTile::keyEvent(key);
|
||||||
}
|
}
|
||||||
@@ -435,7 +441,8 @@ bool TileButtons::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
bool TileButtons::mouseEvent(PIKbdListener::MouseEvent me) {
|
bool TileButtons::mouseEvent(PIKbdListener::MouseEvent me) {
|
||||||
if (me.action == PIKbdListener::MouseMove || me.action == PIKbdListener::MouseButtonPress) {
|
if (me.action == PIKbdListener::MouseMove || me.action == PIKbdListener::MouseButtonPress) {
|
||||||
for (int i = 0; i < btn_rects.size_s(); ++i)
|
for (int i = 0; i < btn_rects.size_s(); ++i)
|
||||||
if (me.x >= btn_rects[i].x0 && me.x < btn_rects[i].x1 && me.y >= btn_rects[i].y0 && me.y < btn_rects[i].y1) {
|
if (me.x >= btn_rects[i].x0 && me.x < btn_rects[i].x1 &&
|
||||||
|
me.y >= btn_rects[i].y0 && me.y < btn_rects[i].y1) {
|
||||||
cur = i;
|
cur = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -447,7 +454,7 @@ bool TileButtons::mouseEvent(PIKbdListener::MouseEvent me) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TileCheck
|
|
||||||
|
|
||||||
TileCheck::TileCheck(const PIString & n): PIScreenTile(n) {
|
TileCheck::TileCheck(const PIString & n): PIScreenTile(n) {
|
||||||
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
|
focus_flags = CanHasFocus | NextByTab | NextByArrowsAll | FocusOnMouse;
|
||||||
@@ -492,7 +499,7 @@ bool TileCheck::mouseEvent(PIKbdListener::MouseEvent me) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TileProgress
|
|
||||||
|
|
||||||
TileProgress::TileProgress(const PIString & n): PIScreenTile(n) {
|
TileProgress::TileProgress(const PIString & n): PIScreenTile(n) {
|
||||||
maximum = 100.;
|
maximum = 100.;
|
||||||
@@ -525,23 +532,25 @@ void TileProgress::drawEvent(PIScreenDrawer * d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TilePICout
|
|
||||||
|
|
||||||
TilePICout::TilePICout(const PIString & n): TileList(n) {
|
TilePICout::TilePICout(const PIString & n): TileList(n) {
|
||||||
max_lines = 1024;
|
max_lines = 1024;
|
||||||
selection_mode = TileList::SingleSelection;
|
selection_mode = TileList::SingleSelection;
|
||||||
PICout::setOutputDevices(PICout::Buffer);
|
PICout::setOutputDevices(PICout::Buffer);
|
||||||
|
PICout::setBufferActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TilePICout::drawEvent(PIScreenDrawer * d) {
|
void TilePICout::drawEvent(PIScreenDrawer * d) {
|
||||||
PIString out = PICout::getBufferAndClear();
|
PIString out = PICout::buffer(true);
|
||||||
if (!out.isEmpty()) {
|
if (!out.isEmpty()) {
|
||||||
PIStringList l = out.split("\n");
|
PIStringList l = out.split("\n");
|
||||||
bool scroll = (cur == content.size_s() - 1) || !has_focus;
|
bool scroll = (cur == content.size_s() - 1) || !has_focus;
|
||||||
piForeachC (PIString & s, l)
|
piForeachC (PIString & s, l)
|
||||||
content << TileList::Row(s.trimmed(), format);
|
content << TileList::Row(s.trimmed(), format);
|
||||||
if (content.size_s() > max_lines) content.remove(0, content.size_s() - max_lines);
|
if (content.size_s() > max_lines)
|
||||||
|
content.remove(0, content.size_s() - max_lines);
|
||||||
if (scroll) {
|
if (scroll) {
|
||||||
offset = piMaxi(0, content.size_s() - lhei);
|
offset = piMaxi(0, content.size_s() - lhei);
|
||||||
cur = content.size_s() - 1;
|
cur = content.size_s() - 1;
|
||||||
@@ -561,7 +570,7 @@ bool TilePICout::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TileInput
|
|
||||||
|
|
||||||
TileInput::TileInput(const PIString & n): PIScreenTile(n) {
|
TileInput::TileInput(const PIString & n): PIScreenTile(n) {
|
||||||
focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
|
focus_flags = CanHasFocus | NextByTab | FocusOnMouse;
|
||||||
@@ -583,8 +592,10 @@ void TileInput::sizeHint(int & w, int & h) const {
|
|||||||
void TileInput::drawEvent(PIScreenDrawer * d) {
|
void TileInput::drawEvent(PIScreenDrawer * d) {
|
||||||
PIString ps = text.mid(offset, width_ - 2);
|
PIString ps = text.mid(offset, width_ - 2);
|
||||||
d->drawText(x_ + 1, y_, ps, (Color)format.color_char, Transparent, (CharFlags)format.flags);
|
d->drawText(x_ + 1, y_, ps, (Color)format.color_char, Transparent, (CharFlags)format.flags);
|
||||||
if (offset > 0) d->drawText(x_, y_, "<", Green, Black, Bold);
|
if (offset > 0)
|
||||||
if (text.size_s() - offset >= width_ - 2) d->drawText(x_ + width_ - 1, y_, ">", Green, Black, Bold);
|
d->drawText(x_, y_, "<", Green, Black, Bold);
|
||||||
|
if (text.size_s() - offset >= width_ - 2)
|
||||||
|
d->drawText(x_ + width_ - 1, y_, ">", Green, Black, Bold);
|
||||||
if (!has_focus) return;
|
if (!has_focus) return;
|
||||||
Color cb = (Color)format.color_char, cc = (Color)format.color_back;
|
Color cb = (Color)format.color_char, cc = (Color)format.color_back;
|
||||||
if (tm_blink.elapsed_m() >= 650) {
|
if (tm_blink.elapsed_m() >= 650) {
|
||||||
@@ -637,7 +648,8 @@ bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
reserCursor();
|
reserCursor();
|
||||||
return true;
|
return true;
|
||||||
case PIKbdListener::Backspace:
|
case PIKbdListener::Backspace:
|
||||||
if (cur > text.size_s() || text.isEmpty()) return true;
|
if (cur > text.size_s() || text.isEmpty())
|
||||||
|
return true;
|
||||||
text.remove(cur - 1, 1);
|
text.remove(cur - 1, 1);
|
||||||
cur--;
|
cur--;
|
||||||
if (cur > text.size_s()) cur = text.size_s();
|
if (cur > text.size_s()) cur = text.size_s();
|
||||||
@@ -647,7 +659,8 @@ bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
reserCursor();
|
reserCursor();
|
||||||
return true;
|
return true;
|
||||||
case PIKbdListener::Delete:
|
case PIKbdListener::Delete:
|
||||||
if (cur >= text.size_s() || text.isEmpty()) return true;
|
if (cur >= text.size_s() || text.isEmpty())
|
||||||
|
return true;
|
||||||
text.remove(cur, 1);
|
text.remove(cur, 1);
|
||||||
if (cur < 0) cur = 0;
|
if (cur < 0) cur = 0;
|
||||||
if (cur > text.size_s()) cur = text.size_s();
|
if (cur > text.size_s()) cur = text.size_s();
|
||||||
@@ -673,7 +686,8 @@ bool TileInput::keyEvent(PIKbdListener::KeyEvent key) {
|
|||||||
case PIKbdListener::F9:
|
case PIKbdListener::F9:
|
||||||
case PIKbdListener::F10:
|
case PIKbdListener::F10:
|
||||||
case PIKbdListener::F11:
|
case PIKbdListener::F11:
|
||||||
case PIKbdListener::F12: break;
|
case PIKbdListener::F12:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
text.insert(cur, PIChar((ushort)key.key));
|
text.insert(cur, PIChar((ushort)key.key));
|
||||||
cur++;
|
cur++;
|
||||||
|
|||||||
@@ -16,19 +16,17 @@
|
|||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "piterminal.h"
|
|
||||||
|
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
|
#include "piterminal.h"
|
||||||
#include "pisharedmemory.h"
|
#include "pisharedmemory.h"
|
||||||
#ifndef MICRO_PIP
|
#ifndef MICRO_PIP
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
# include <wincon.h>
|
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <wingdi.h>
|
# include <wingdi.h>
|
||||||
|
# include <wincon.h>
|
||||||
# include <winuser.h>
|
# include <winuser.h>
|
||||||
#else
|
#else
|
||||||
# include "piprocess.h"
|
# include "piprocess.h"
|
||||||
|
|
||||||
# include <csignal>
|
# include <csignal>
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
@@ -125,7 +123,8 @@ PITerminal::PITerminal(): PIThread() {
|
|||||||
|
|
||||||
|
|
||||||
PITerminal::~PITerminal() {
|
PITerminal::~PITerminal() {
|
||||||
if (isRunning()) stop();
|
if (isRunning())
|
||||||
|
stop();
|
||||||
PIThread::waitForFinish(10);
|
PIThread::waitForFinish(10);
|
||||||
destroy();
|
destroy();
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
@@ -166,8 +165,7 @@ void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
//piCout << "write" << ba.size();
|
//piCout << "write" << ba.size();
|
||||||
if (!ba.isEmpty())
|
if (!ba.isEmpty()) write(ba);
|
||||||
write(ba);
|
|
||||||
else {
|
else {
|
||||||
PIByteArray msg;
|
PIByteArray msg;
|
||||||
PIVector<PIKbdListener::KeyEvent> ke;
|
PIVector<PIKbdListener::KeyEvent> ke;
|
||||||
@@ -187,8 +185,7 @@ void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers
|
|||||||
case PIKbdListener::UpArrow:
|
case PIKbdListener::UpArrow:
|
||||||
case PIKbdListener::DownArrow:
|
case PIKbdListener::DownArrow:
|
||||||
case PIKbdListener::RightArrow:
|
case PIKbdListener::RightArrow:
|
||||||
case PIKbdListener::LeftArrow:
|
case PIKbdListener::LeftArrow: if (PRIVATE->DEC.value(CKM, false)) flags = 1;
|
||||||
if (PRIVATE->DEC.value(CKM, false)) flags = 1;
|
|
||||||
/*case PIKbdListener::Home: //break;
|
/*case PIKbdListener::Home: //break;
|
||||||
case PIKbdListener::End: //break;
|
case PIKbdListener::End: //break;
|
||||||
case PIKbdListener::PageUp: //ba << uchar('\e') << uchar('[') << uchar('5') << uchar('~'); break;
|
case PIKbdListener::PageUp: //ba << uchar('\e') << uchar('[') << uchar('5') << uchar('~'); break;
|
||||||
@@ -238,8 +235,7 @@ void PITerminal::write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers
|
|||||||
|
|
||||||
|
|
||||||
void PITerminal::write(PIKbdListener::KeyEvent ke) {
|
void PITerminal::write(PIKbdListener::KeyEvent ke) {
|
||||||
if (isSpecialKey(ke.key))
|
if (isSpecialKey(ke.key)) write((PIKbdListener::SpecialKey)ke.key, ke.modifiers);
|
||||||
write((PIKbdListener::SpecialKey)ke.key, ke.modifiers);
|
|
||||||
else {
|
else {
|
||||||
PIByteArray ba;
|
PIByteArray ba;
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
@@ -257,7 +253,8 @@ PIVector<PIVector<PIScreenTypes::Cell>> PITerminal::content() {
|
|||||||
PIVector<PIVector<PIScreenTypes::Cell> > ret = cells;
|
PIVector<PIVector<PIScreenTypes::Cell> > ret = cells;
|
||||||
if (cursor_blink && cursor_visible)
|
if (cursor_blink && cursor_visible)
|
||||||
if (cursor_x >= 0 && cursor_x < size_x)
|
if (cursor_x >= 0 && cursor_x < size_x)
|
||||||
if (cursor_y >= 0 && cursor_y < size_y) ret[cursor_y][cursor_x].format.flags ^= PIScreenTypes::Inverse;
|
if (cursor_y >= 0 && cursor_y < size_y)
|
||||||
|
ret[cursor_y][cursor_x].format.flags ^= PIScreenTypes::Inverse;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,15 +395,16 @@ void PITerminal::run() {
|
|||||||
}
|
}
|
||||||
bool parse = PRIVATE->read_buf.size_s() >= BUFFER_SIZE;
|
bool parse = PRIVATE->read_buf.size_s() >= BUFFER_SIZE;
|
||||||
if (PRIVATE->read_buf.size_s() == 1)
|
if (PRIVATE->read_buf.size_s() == 1)
|
||||||
if (PRIVATE->read_buf[0] < 0x80) parse = true;
|
if (PRIVATE->read_buf[0] < 0x80)
|
||||||
|
parse = true;
|
||||||
if (parse) {
|
if (parse) {
|
||||||
parseInput(PIString::fromUTF8(PRIVATE->read_buf));
|
parseInput(PIString(PRIVATE->read_buf));
|
||||||
PRIVATE->read_buf.clear();
|
PRIVATE->read_buf.clear();
|
||||||
}
|
}
|
||||||
//printf("%s", PRIVATE->read_buf.data());
|
//printf("%s", PRIVATE->read_buf.data());
|
||||||
}
|
}
|
||||||
if (!used && !PRIVATE->last_read && !PRIVATE->read_buf.isEmpty()) {
|
if (!used && !PRIVATE->last_read && !PRIVATE->read_buf.isEmpty()) {
|
||||||
parseInput(PIString::fromUTF8(PRIVATE->read_buf));
|
parseInput(PIString(PRIVATE->read_buf));
|
||||||
PRIVATE->read_buf.clear();
|
PRIVATE->read_buf.clear();
|
||||||
}
|
}
|
||||||
PRIVATE->last_read = false;
|
PRIVATE->last_read = false;
|
||||||
@@ -447,8 +445,7 @@ void PITerminal::parseInput(const PIString & s) {
|
|||||||
if (s[i] == '\r') continue;
|
if (s[i] == '\r') continue;
|
||||||
if (s[i] == '\n') {
|
if (s[i] == '\n') {
|
||||||
//piCoutObj << "new line";
|
//piCoutObj << "new line";
|
||||||
for (int i = PRIVATE->cur_x; i < size_x; ++i)
|
for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i].format = PRIVATE->cur_format;
|
||||||
cells[PRIVATE->cur_y][i].format = PRIVATE->cur_format;
|
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
PRIVATE->cur_x = 0;
|
PRIVATE->cur_x = 0;
|
||||||
moveCursor(0, 1);
|
moveCursor(0, 1);
|
||||||
@@ -501,8 +498,7 @@ void PITerminal::applyEscSeq(PIString es) {
|
|||||||
case 1047:
|
case 1047:
|
||||||
if (val) {
|
if (val) {
|
||||||
PRIVATE->cells_save = cells;
|
PRIVATE->cells_save = cells;
|
||||||
for (int i = 0; i < size_y; ++i)
|
for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell);
|
||||||
cells[i].fill(def_cell);
|
|
||||||
} else {
|
} else {
|
||||||
cells = PRIVATE->cells_save;
|
cells = PRIVATE->cells_save;
|
||||||
}
|
}
|
||||||
@@ -528,14 +524,8 @@ void PITerminal::applyEscSeq(PIString es) {
|
|||||||
default: {
|
default: {
|
||||||
bool col = false, target = false;
|
bool col = false, target = false;
|
||||||
int cid = av % 10;
|
int cid = av % 10;
|
||||||
if (av >= 30 && av <= 37) {
|
if (av >= 30 && av <= 37) {col = true; target = false;}
|
||||||
col = true;
|
if (av >= 40 && av <= 47) {col = true; target = true;}
|
||||||
target = false;
|
|
||||||
}
|
|
||||||
if (av >= 40 && av <= 47) {
|
|
||||||
col = true;
|
|
||||||
target = true;
|
|
||||||
}
|
|
||||||
if (col) {
|
if (col) {
|
||||||
int cfl = 0;
|
int cfl = 0;
|
||||||
switch (cid) {
|
switch (cid) {
|
||||||
@@ -596,29 +586,25 @@ void PITerminal::applyEscSeq(PIString es) {
|
|||||||
}
|
}
|
||||||
if (es.back() == 'A') { // cursor up
|
if (es.back() == 'A') { // cursor up
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
|
||||||
PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1);
|
PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1);
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
}
|
}
|
||||||
if (es.back() == 'B') { // cursor down
|
if (es.back() == 'B') { // cursor down
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
|
||||||
PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1);
|
PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1);
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
}
|
}
|
||||||
if (es.back() == 'C' || es.back() == 'a') { // cursor forward, next column
|
if (es.back() == 'C' || es.back() == 'a') { // cursor forward, next column
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
|
||||||
PRIVATE->cur_x = piClamp(PRIVATE->cur_x + v, 0, size_x - 1);
|
PRIVATE->cur_x = piClamp(PRIVATE->cur_x + v, 0, size_x - 1);
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
}
|
}
|
||||||
if (es.back() == 'D') { // cursor back
|
if (es.back() == 'D') { // cursor back
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
|
||||||
PRIVATE->cur_x = piClamp(PRIVATE->cur_x - v, 0, size_x - 1);
|
PRIVATE->cur_x = piClamp(PRIVATE->cur_x - v, 0, size_x - 1);
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
}
|
}
|
||||||
@@ -630,91 +616,65 @@ void PITerminal::applyEscSeq(PIString es) {
|
|||||||
}
|
}
|
||||||
if (es.back() == 'd') { // goto line
|
if (es.back() == 'd') { // goto line
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
|
||||||
PRIVATE->cur_x = 0;
|
PRIVATE->cur_x = 0;
|
||||||
PRIVATE->cur_y = piClamp(v - 1, 0, size_y - 1);
|
PRIVATE->cur_y = piClamp(v - 1, 0, size_y - 1);
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
}
|
}
|
||||||
if (es.back() == 'E' || es.back() == 'e') { // next line
|
if (es.back() == 'E' || es.back() == 'e') { // next line
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
|
||||||
PRIVATE->cur_x = 0;
|
PRIVATE->cur_x = 0;
|
||||||
PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1);
|
PRIVATE->cur_y = piClamp(PRIVATE->cur_y + v, 0, size_y - 1);
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
}
|
}
|
||||||
if (es.back() == 'F') { // previous line
|
if (es.back() == 'F') { // previous line
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
|
||||||
PRIVATE->cur_x = 0;
|
PRIVATE->cur_x = 0;
|
||||||
PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1);
|
PRIVATE->cur_y = piClamp(PRIVATE->cur_y - v, 0, size_y - 1);
|
||||||
PRIVATE->line_format = PRIVATE->cur_format;
|
PRIVATE->line_format = PRIVATE->cur_format;
|
||||||
}
|
}
|
||||||
if (es.back() == 'L') { // insert lines
|
if (es.back() == 'L') { // insert lines
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
for (int i = piClamp(size_y - 1, PRIVATE->win_y0, PRIVATE->win_y1); i >= piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1); --i) cells[i] = cells[i - v];
|
||||||
for (int i = piClamp(size_y - 1, PRIVATE->win_y0, PRIVATE->win_y1);
|
for (int j = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1); j < piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1); ++j)
|
||||||
i >= piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1);
|
for (int i = 0; i < PRIVATE->cur_x; ++i) cells[j][i] = def_cell;
|
||||||
--i)
|
|
||||||
cells[i] = cells[i - v];
|
|
||||||
for (int j = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1);
|
|
||||||
j < piClamp(PRIVATE->cur_y + v, PRIVATE->win_y0, PRIVATE->win_y1);
|
|
||||||
++j)
|
|
||||||
for (int i = 0; i < PRIVATE->cur_x; ++i)
|
|
||||||
cells[j][i] = def_cell;
|
|
||||||
}
|
}
|
||||||
if (es.back() == 'M') { // delete lines
|
if (es.back() == 'M') { // delete lines
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
for (int i = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1); i < piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1); ++i) cells[i] = cells[i + v];
|
||||||
for (int i = piClamp(PRIVATE->cur_y, PRIVATE->win_y0, PRIVATE->win_y1);
|
|
||||||
i < piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1);
|
|
||||||
++i)
|
|
||||||
cells[i] = cells[i + v];
|
|
||||||
for (int j = piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1); j < piClamp(size_y, PRIVATE->win_y0, PRIVATE->win_y1); ++j)
|
for (int j = piClamp(size_y - v, PRIVATE->win_y0, PRIVATE->win_y1); j < piClamp(size_y, PRIVATE->win_y0, PRIVATE->win_y1); ++j)
|
||||||
for (int i = 0; i < PRIVATE->cur_x; ++i)
|
for (int i = 0; i < PRIVATE->cur_x; ++i) cells[j][i] = def_cell;
|
||||||
cells[j][i] = def_cell;
|
|
||||||
}
|
}
|
||||||
if (es.back() == 'P') { // delete characters
|
if (es.back() == 'P') { // delete characters
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
for (int i = PRIVATE->cur_x; i < size_x - v; ++i) cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i + v];
|
||||||
for (int i = PRIVATE->cur_x; i < size_x - v; ++i)
|
for (int i = size_x - v; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
|
||||||
cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i + v];
|
|
||||||
for (int i = size_x - v; i < size_x; ++i)
|
|
||||||
cells[PRIVATE->cur_y][i] = def_cell;
|
|
||||||
}
|
}
|
||||||
if (es.back() == '@') { // delete characters
|
if (es.back() == '@') { // delete characters
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt(); if (v == 0) v = 1;
|
||||||
if (v == 0) v = 1;
|
for (int i = size_x - 1; i >= PRIVATE->cur_x + v; --i) cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i - v];
|
||||||
for (int i = size_x - 1; i >= PRIVATE->cur_x + v; --i)
|
for (int i = PRIVATE->cur_x; i < PRIVATE->cur_x + v; ++i) cells[PRIVATE->cur_y][i] = def_cell;
|
||||||
cells[PRIVATE->cur_y][i] = cells[PRIVATE->cur_y][i - v];
|
|
||||||
for (int i = PRIVATE->cur_x; i < PRIVATE->cur_x + v; ++i)
|
|
||||||
cells[PRIVATE->cur_y][i] = def_cell;
|
|
||||||
}
|
}
|
||||||
if (es.back() == 'J') { // erase data
|
if (es.back() == 'J') { // erase data
|
||||||
es.cutLeft(1).cutRight(1);
|
es.cutLeft(1).cutRight(1);
|
||||||
int v = es.toInt();
|
int v = es.toInt();
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case 0:
|
case 0:
|
||||||
for (int i = PRIVATE->cur_x; i < size_x; ++i)
|
for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
|
||||||
cells[PRIVATE->cur_y][i] = def_cell;
|
for (int i = PRIVATE->cur_y + 1; i < size_y; ++i) cells[i].fill(def_cell);
|
||||||
for (int i = PRIVATE->cur_y + 1; i < size_y; ++i)
|
|
||||||
cells[i].fill(def_cell);
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
for (int i = 0; i <= PRIVATE->cur_x; ++i)
|
for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
|
||||||
cells[PRIVATE->cur_y][i] = def_cell;
|
for (int i = 0; i < PRIVATE->cur_y; ++i) cells[i].fill(def_cell);
|
||||||
for (int i = 0; i < PRIVATE->cur_y; ++i)
|
|
||||||
cells[i].fill(def_cell);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for (int i = 0; i < size_y; ++i)
|
for (int i = 0; i < size_y; ++i) cells[i].fill(def_cell);
|
||||||
cells[i].fill(def_cell);
|
|
||||||
//PRIVATE->cur_x = PRIVATE->cur_y = 0;
|
//PRIVATE->cur_x = PRIVATE->cur_y = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -724,14 +684,14 @@ void PITerminal::applyEscSeq(PIString es) {
|
|||||||
int v = es.toInt();
|
int v = es.toInt();
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case 0:
|
case 0:
|
||||||
for (int i = PRIVATE->cur_x; i < size_x; ++i)
|
for (int i = PRIVATE->cur_x; i < size_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
|
||||||
cells[PRIVATE->cur_y][i] = def_cell;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
for (int i = 0; i <= PRIVATE->cur_x; ++i)
|
for (int i = 0; i <= PRIVATE->cur_x; ++i) cells[PRIVATE->cur_y][i] = def_cell;
|
||||||
cells[PRIVATE->cur_y][i] = def_cell;
|
break;
|
||||||
|
case 2:
|
||||||
|
cells[PRIVATE->cur_y].fill(def_cell);
|
||||||
break;
|
break;
|
||||||
case 2: cells[PRIVATE->cur_y].fill(def_cell); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -761,10 +721,8 @@ void PITerminal::moveCursor(int dx, int dy) {
|
|||||||
|
|
||||||
|
|
||||||
int PITerminal::termType(const PIString & t) {
|
int PITerminal::termType(const PIString & t) {
|
||||||
if (t == "xterm")
|
if (t == "xterm") return PIKbdListener::vt_xterm;
|
||||||
return PIKbdListener::vt_xterm;
|
else if (t == "linux") return PIKbdListener::vt_linux;
|
||||||
else if (t == "linux")
|
|
||||||
return PIKbdListener::vt_linux;
|
|
||||||
return PIKbdListener::vt_none;
|
return PIKbdListener::vt_none;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -809,28 +767,12 @@ bool PITerminal::initialize() {
|
|||||||
PIString shmh = PIString::fromNumber(randomi() % 10000);
|
PIString shmh = PIString::fromNumber(randomi() % 10000);
|
||||||
PIString pname = "\\\\.\\pipe\\piterm" + shmh;
|
PIString pname = "\\\\.\\pipe\\piterm" + shmh;
|
||||||
PIString cmd = "piterminal \"" + shmh + "\" \"" + pname + "\"";
|
PIString cmd = "piterminal \"" + shmh + "\" \"" + pname + "\"";
|
||||||
if (!CreateProcessA(0,
|
if(!CreateProcessA(0, (LPSTR)cmd.dataAscii(), 0, 0, false, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, 0, 0, &PRIVATE->si, &PRIVATE->pi)) {
|
||||||
(LPSTR)cmd.dataAscii(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&PRIVATE->si,
|
|
||||||
&PRIVATE->pi)) {
|
|
||||||
piCoutObj << "CreateProcess error," << errorString();
|
piCoutObj << "CreateProcess error," << errorString();
|
||||||
destroy();
|
destroy();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PRIVATE->pipe = CreateNamedPipeA((LPSTR)pname.dataAscii(),
|
PRIVATE->pipe = CreateNamedPipe((LPSTR)pname.dataAscii(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 2, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 1000, NULL);
|
||||||
PIPE_ACCESS_DUPLEX,
|
|
||||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
|
||||||
2,
|
|
||||||
PIPE_BUFFER_SIZE,
|
|
||||||
PIPE_BUFFER_SIZE,
|
|
||||||
1000,
|
|
||||||
NULL);
|
|
||||||
if (PRIVATE->pipe == INVALID_HANDLE_VALUE) {
|
if (PRIVATE->pipe == INVALID_HANDLE_VALUE) {
|
||||||
piCoutObj << "CreateNamedPipe error," << errorString();
|
piCoutObj << "CreateNamedPipe error," << errorString();
|
||||||
destroy();
|
destroy();
|
||||||
@@ -855,8 +797,7 @@ bool PITerminal::initialize() {
|
|||||||
resize(dsize_x, dsize_y);
|
resize(dsize_x, dsize_y);
|
||||||
#else
|
#else
|
||||||
# ifdef HAS_FORKPTY
|
# ifdef HAS_FORKPTY
|
||||||
char pty[256];
|
char pty[256]; memset(pty, 0, 256);
|
||||||
memset(pty, 0, 256);
|
|
||||||
winsize ws;
|
winsize ws;
|
||||||
ws.ws_col = dsize_x;
|
ws.ws_col = dsize_x;
|
||||||
ws.ws_row = dsize_y;
|
ws.ws_row = dsize_y;
|
||||||
@@ -936,8 +877,10 @@ void PITerminal::destroy() {
|
|||||||
//piCout << "destroy" << size_y;
|
//piCout << "destroy" << size_y;
|
||||||
#else
|
#else
|
||||||
# ifdef HAS_FORKPTY
|
# ifdef HAS_FORKPTY
|
||||||
if (PRIVATE->pid != 0) kill(PRIVATE->pid, SIGKILL);
|
if (PRIVATE->pid != 0)
|
||||||
if (PRIVATE->fd != 0) ::close(PRIVATE->fd);
|
kill(PRIVATE->pid, SIGKILL);
|
||||||
|
if (PRIVATE->fd != 0)
|
||||||
|
::close(PRIVATE->fd);
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
initPrivate();
|
initPrivate();
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ PIAuth::State PIAuth::receive(PIByteArray & ba) {
|
|||||||
rinfo = crypt.decrypt(rinfo, secret_key, &ok);
|
rinfo = crypt.decrypt(rinfo, secret_key, &ok);
|
||||||
if (!ok) return disconnect(ba, "Error while exchange keys");
|
if (!ok) return disconnect(ba, "Error while exchange keys");
|
||||||
state = Connected;
|
state = Connected;
|
||||||
connected(PIString::fromUTF8(rinfo));
|
connected(rinfo);
|
||||||
ba << (int)state << crypt.generateRandomBuff(randomi()%PIAUTH_NOISE_MAX_SIZE);
|
ba << (int)state << crypt.generateRandomBuff(randomi()%PIAUTH_NOISE_MAX_SIZE);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,7 @@
|
|||||||
# include <sodium.h>
|
# include <sodium.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PICRYPT_DISABLED_WARNING \
|
#define PICRYPT_DISABLED_WARNING piCout << "[PICrypt]" << "Warning: PICrypt is disabled, to enable install sodium library and rebuild pip";
|
||||||
piCout << "[PICrypt]" \
|
|
||||||
<< "Warning: PICrypt is disabled, to enable install sodium library and rebuild pip";
|
|
||||||
|
|
||||||
const char hash_def_key[] = "_picrypt_\0\0\0\0\0\0\0";
|
const char hash_def_key[] = "_picrypt_\0\0\0\0\0\0\0";
|
||||||
const int hash_def_key_size = 9;
|
const int hash_def_key_size = 9;
|
||||||
@@ -32,9 +30,7 @@ const int hash_def_key_size = 9;
|
|||||||
|
|
||||||
PICrypt::PICrypt() {
|
PICrypt::PICrypt() {
|
||||||
#ifdef PIP_CRYPT
|
#ifdef PIP_CRYPT
|
||||||
if (!init())
|
if (!init()) piCout << "[PICrypt]" << "Error while initialize sodium!";
|
||||||
piCout << "[PICrypt]"
|
|
||||||
<< "Error while initialize sodium!";
|
|
||||||
nonce_.resize(crypto_secretbox_NONCEBYTES);
|
nonce_.resize(crypto_secretbox_NONCEBYTES);
|
||||||
key_.resize(crypto_secretbox_KEYBYTES);
|
key_.resize(crypto_secretbox_KEYBYTES);
|
||||||
randombytes_buf(key_.data(), key_.size());
|
randombytes_buf(key_.data(), key_.size());
|
||||||
@@ -80,7 +76,8 @@ PIByteArray PICrypt::crypt(const PIByteArray & data) {
|
|||||||
PIByteArray PICrypt::crypt(const PIByteArray & data, PIByteArray key) {
|
PIByteArray PICrypt::crypt(const PIByteArray & data, PIByteArray key) {
|
||||||
PIByteArray ret;
|
PIByteArray ret;
|
||||||
#ifdef PIP_CRYPT
|
#ifdef PIP_CRYPT
|
||||||
if (key.size() != crypto_secretbox_KEYBYTES) key.resize(crypto_secretbox_KEYBYTES, ' ');
|
if (key.size() != crypto_secretbox_KEYBYTES)
|
||||||
|
key.resize(crypto_secretbox_KEYBYTES, ' ');
|
||||||
//return PIByteArray();
|
//return PIByteArray();
|
||||||
if (!init()) return ret;
|
if (!init()) return ret;
|
||||||
PIByteArray n;
|
PIByteArray n;
|
||||||
@@ -119,7 +116,8 @@ PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, bool * ok) {
|
|||||||
PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, PIByteArray key, bool *ok) {
|
PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, PIByteArray key, bool *ok) {
|
||||||
PIByteArray ret;
|
PIByteArray ret;
|
||||||
#ifdef PIP_CRYPT
|
#ifdef PIP_CRYPT
|
||||||
if (key.size() != crypto_secretbox_KEYBYTES) key.resize(crypto_secretbox_KEYBYTES, ' ');
|
if (key.size() != crypto_secretbox_KEYBYTES)
|
||||||
|
key.resize(crypto_secretbox_KEYBYTES, ' ');
|
||||||
/*if (ok) *ok = false;
|
/*if (ok) *ok = false;
|
||||||
return PIByteArray();
|
return PIByteArray();
|
||||||
}*/
|
}*/
|
||||||
@@ -136,8 +134,7 @@ PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, PIByteArray key, bo
|
|||||||
if (ok) *ok = false;
|
if (ok) *ok = false;
|
||||||
// piCout << "[PICrypt]" << "bad key_";
|
// piCout << "[PICrypt]" << "bad key_";
|
||||||
return PIByteArray();
|
return PIByteArray();
|
||||||
} else if (ok)
|
} else if (ok) *ok = true;
|
||||||
*ok = true;
|
|
||||||
#else
|
#else
|
||||||
PICRYPT_DISABLED_WARNING
|
PICRYPT_DISABLED_WARNING
|
||||||
#endif
|
#endif
|
||||||
@@ -198,13 +195,10 @@ size_t PICrypt::sizeHash() {
|
|||||||
ullong PICrypt::shorthash(const PIString& s, PIByteArray key) {
|
ullong PICrypt::shorthash(const PIString& s, PIByteArray key) {
|
||||||
ullong hash = 0;
|
ullong hash = 0;
|
||||||
#ifdef PIP_CRYPT
|
#ifdef PIP_CRYPT
|
||||||
if (crypto_shorthash_BYTES != sizeof(hash))
|
if (crypto_shorthash_BYTES != sizeof(hash)) piCout << "[PICrypt]" << "internal error: bad hash size";
|
||||||
piCout << "[PICrypt]"
|
|
||||||
<< "internal error: bad hash size";
|
|
||||||
if (!init()) return hash;
|
if (!init()) return hash;
|
||||||
if (key.size() != crypto_shorthash_KEYBYTES) {
|
if (key.size() != crypto_shorthash_KEYBYTES) {
|
||||||
piCout << "[PICrypt]"
|
piCout << "[PICrypt]" << "invalid key size" << key.size() << ", shoud be" << crypto_shorthash_KEYBYTES << ", filled zeros";
|
||||||
<< "invalid key size" << key.size() << ", shoud be" << crypto_shorthash_KEYBYTES << ", filled zeros";
|
|
||||||
key.resize(crypto_shorthash_KEYBYTES, 0);
|
key.resize(crypto_shorthash_KEYBYTES, 0);
|
||||||
}
|
}
|
||||||
PIByteArray in(s.data(), s.size());
|
PIByteArray in(s.data(), s.size());
|
||||||
@@ -351,13 +345,16 @@ PIByteArray PICrypt::crypt(const PIByteArray & data, const PIByteArray & public_
|
|||||||
PIByteArray ret;
|
PIByteArray ret;
|
||||||
#ifdef PIP_CRYPT
|
#ifdef PIP_CRYPT
|
||||||
if (!init()) return ret;
|
if (!init()) return ret;
|
||||||
if (public_key.size() != crypto_box_PUBLICKEYBYTES) return ret;
|
if (public_key.size() != crypto_box_PUBLICKEYBYTES)
|
||||||
if (secret_key.size() != crypto_box_SECRETKEYBYTES) return ret;
|
return ret;
|
||||||
|
if (secret_key.size() != crypto_box_SECRETKEYBYTES)
|
||||||
|
return ret;
|
||||||
PIByteArray n;
|
PIByteArray n;
|
||||||
ret.resize(data.size() + crypto_box_MACBYTES);
|
ret.resize(data.size() + crypto_box_MACBYTES);
|
||||||
n.resize(crypto_box_NONCEBYTES);
|
n.resize(crypto_box_NONCEBYTES);
|
||||||
randombytes_buf(n.data(), n.size());
|
randombytes_buf(n.data(), n.size());
|
||||||
if (crypto_box_easy(ret.data(), data.data(), data.size(), n.data(), public_key.data(), secret_key.data()) != 0) return PIByteArray();
|
if (crypto_box_easy(ret.data(), data.data(), data.size(), n.data(), public_key.data(), secret_key.data()) != 0)
|
||||||
|
return PIByteArray();
|
||||||
ret.append(n);
|
ret.append(n);
|
||||||
#else
|
#else
|
||||||
PICRYPT_DISABLED_WARNING
|
PICRYPT_DISABLED_WARNING
|
||||||
@@ -386,13 +383,11 @@ PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, const PIByteArray &
|
|||||||
n.resize(crypto_secretbox_NONCEBYTES);
|
n.resize(crypto_secretbox_NONCEBYTES);
|
||||||
ret.resize(crypt_data.size() - n.size() - crypto_secretbox_MACBYTES);
|
ret.resize(crypt_data.size() - n.size() - crypto_secretbox_MACBYTES);
|
||||||
memcpy(n.data(), crypt_data.data(crypt_data.size() - n.size()), n.size());
|
memcpy(n.data(), crypt_data.data(crypt_data.size() - n.size()), n.size());
|
||||||
if (crypto_box_open_easy(ret.data(), crypt_data.data(), crypt_data.size() - n.size(), n.data(), public_key.data(), secret_key.data()) !=
|
if (crypto_box_open_easy(ret.data(), crypt_data.data(), crypt_data.size() - n.size(), n.data(), public_key.data(), secret_key.data()) != 0) {
|
||||||
0) {
|
|
||||||
if (ok) *ok = false;
|
if (ok) *ok = false;
|
||||||
// piCout << "[PICrypt]" << "bad key_";
|
// piCout << "[PICrypt]" << "bad key_";
|
||||||
return PIByteArray();
|
return PIByteArray();
|
||||||
} else if (ok)
|
} else if (ok) *ok = true;
|
||||||
*ok = true;
|
|
||||||
#else
|
#else
|
||||||
PICRYPT_DISABLED_WARNING
|
PICRYPT_DISABLED_WARNING
|
||||||
#endif
|
#endif
|
||||||
@@ -410,16 +405,8 @@ PIByteArray PICrypt::passwordHash(const PIString & password, const PIByteArray &
|
|||||||
n.resize(crypto_pwhash_SALTBYTES);
|
n.resize(crypto_pwhash_SALTBYTES);
|
||||||
// randombytes_buf(n.data(), n.size());
|
// randombytes_buf(n.data(), n.size());
|
||||||
// crypto_shorthash(n.data(), seed.data(), seed.size(), PIByteArray(crypto_shorthash_KEYBYTES).data());
|
// crypto_shorthash(n.data(), seed.data(), seed.size(), PIByteArray(crypto_shorthash_KEYBYTES).data());
|
||||||
int r = crypto_pwhash(ph.data(),
|
int r = crypto_pwhash(ph.data(), ph.size(), (const char*)pass.data(), pass.size(), n.data(), crypto_pwhash_argon2i_opslimit_moderate(), crypto_pwhash_argon2i_memlimit_moderate(), crypto_pwhash_ALG_ARGON2I13);
|
||||||
ph.size(),
|
//crypto_pwhash_str(out, (const char*)pass.data(), pass.size(), crypto_pwhash_argon2i_opslimit_moderate(), crypto_pwhash_argon2i_memlimit_moderate());
|
||||||
(const char *)pass.data(),
|
|
||||||
pass.size(),
|
|
||||||
n.data(),
|
|
||||||
crypto_pwhash_argon2i_opslimit_moderate(),
|
|
||||||
crypto_pwhash_argon2i_memlimit_moderate(),
|
|
||||||
crypto_pwhash_ALG_ARGON2I13);
|
|
||||||
// crypto_pwhash_str(out, (const char*)pass.data(), pass.size(), crypto_pwhash_argon2i_opslimit_moderate(),
|
|
||||||
// crypto_pwhash_argon2i_memlimit_moderate());
|
|
||||||
pass.fill(0);
|
pass.fill(0);
|
||||||
if (r != 0) return PIByteArray();
|
if (r != 0) return PIByteArray();
|
||||||
return ph;
|
return ph;
|
||||||
@@ -447,7 +434,8 @@ bool PICrypt::init() {
|
|||||||
if (inited) return true;
|
if (inited) return true;
|
||||||
//piCout << "[PICrypt]" << "init ...";
|
//piCout << "[PICrypt]" << "init ...";
|
||||||
inited = sodium_init();
|
inited = sodium_init();
|
||||||
if (!inited) inited = sodium_init();
|
if (!inited)
|
||||||
|
inited = sodium_init();
|
||||||
//piCout << "[PICrypt]" << "init" << inited;
|
//piCout << "[PICrypt]" << "init" << inited;
|
||||||
return inited;
|
return inited;
|
||||||
#else
|
#else
|
||||||
@@ -455,3 +443,6 @@ bool PICrypt::init() {
|
|||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,30 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pifft.h"
|
#include "pifft.h"
|
||||||
|
|
||||||
#include "pifft_p.h"
|
#include "pifft_p.h"
|
||||||
|
|
||||||
|
|
||||||
#define _PIFFTW_CPP(type) \
|
#define _PIFFTW_CPP(type) \
|
||||||
_PIFFTW_P_##type##_::_PIFFTW_P_##type##_() { \
|
_PIFFTW_P_##type##_::_PIFFTW_P_##type##_() {impl = new PIFFTW_Private<type>();;} \
|
||||||
impl = new PIFFTW_Private<type>(); \
|
_PIFFTW_P_##type##_::~_PIFFTW_P_##type##_() {delete (PIFFTW_Private<type>*)impl;} \
|
||||||
; \
|
const PIVector<complex<type> > & _PIFFTW_P_##type##_::calcFFT(const PIVector<complex<type> > & in) {return ((PIFFTW_Private<type>*)impl)->calcFFT(in);} \
|
||||||
} \
|
const PIVector<complex<type> > & _PIFFTW_P_##type##_::calcFFTR(const PIVector<type> & in) {return ((PIFFTW_Private<type>*)impl)->calcFFT(in);} \
|
||||||
_PIFFTW_P_##type##_::~_PIFFTW_P_##type##_() { \
|
const PIVector<complex<type> > & _PIFFTW_P_##type##_::calcFFTI(const PIVector<complex<type> > & in) {return ((PIFFTW_Private<type>*)impl)->calcFFTinverse(in);} \
|
||||||
delete (PIFFTW_Private<type> *)impl; \
|
void _PIFFTW_P_##type##_::preparePlan(int size, int op) {return ((PIFFTW_Private<type>*)impl)->preparePlan(size, op);}
|
||||||
} \
|
|
||||||
const PIVector<complex<type>> & _PIFFTW_P_##type##_::calcFFT(const PIVector<complex<type>> & in) { \
|
|
||||||
return ((PIFFTW_Private<type> *)impl)->calcFFT(in); \
|
|
||||||
} \
|
|
||||||
const PIVector<complex<type>> & _PIFFTW_P_##type##_::calcFFTR(const PIVector<type> & in) { \
|
|
||||||
return ((PIFFTW_Private<type> *)impl)->calcFFT(in); \
|
|
||||||
} \
|
|
||||||
const PIVector<complex<type>> & _PIFFTW_P_##type##_::calcFFTI(const PIVector<complex<type>> & in) { \
|
|
||||||
return ((PIFFTW_Private<type> *)impl)->calcFFTinverse(in); \
|
|
||||||
} \
|
|
||||||
void _PIFFTW_P_##type##_::preparePlan(int size, int op) { \
|
|
||||||
return ((PIFFTW_Private<type> *)impl)->preparePlan(size, op); \
|
|
||||||
}
|
|
||||||
|
|
||||||
_PIFFTW_CPP(float)
|
_PIFFTW_CPP(float)
|
||||||
_PIFFTW_CPP(double)
|
_PIFFTW_CPP(double)
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
#ifndef PIFFT_P_H
|
#ifndef PIFFT_P_H
|
||||||
#define PIFFT_P_H
|
#define PIFFT_P_H
|
||||||
|
|
||||||
#include "picout.h"
|
|
||||||
#include "pivector.h"
|
#include "pivector.h"
|
||||||
|
#include "picout.h"
|
||||||
#if defined(PIP_FFTW) || defined(PIP_FFTWf) || defined(PIP_FFTWl) || defined(PIP_FFTWq)
|
#if defined(PIP_FFTW) || defined(PIP_FFTWf) || defined(PIP_FFTWl) || defined(PIP_FFTWq)
|
||||||
# include "fftw3.h"
|
# include "fftw3.h"
|
||||||
#else
|
#else
|
||||||
@@ -36,7 +36,8 @@
|
|||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class PIFFTW_Private {
|
class PIFFTW_Private
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit PIFFTW_Private() {
|
explicit PIFFTW_Private() {
|
||||||
plan = 0;
|
plan = 0;
|
||||||
@@ -50,7 +51,7 @@ public:
|
|||||||
const PIVector<complex<T> > & calcFFT(const PIVector<complex<T> > & in) {
|
const PIVector<complex<T> > & calcFFT(const PIVector<complex<T> > & in) {
|
||||||
if (prepare != PlanParams(in.size(), fo_complex)) {
|
if (prepare != PlanParams(in.size(), fo_complex)) {
|
||||||
p_out.resize(in.size());
|
p_out.resize(in.size());
|
||||||
// piCout << "[PIFFTW]" << "creating plan";
|
piCout << "[PIFFTW]" << "creating plan";
|
||||||
p_createPlan_c2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_FORWARD, FFTW_ESTIMATE | FFTW_UNALIGNED);
|
p_createPlan_c2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_FORWARD, FFTW_ESTIMATE | FFTW_UNALIGNED);
|
||||||
prepare = PlanParams(in.size(), fo_complex);
|
prepare = PlanParams(in.size(), fo_complex);
|
||||||
}
|
}
|
||||||
@@ -60,7 +61,7 @@ public:
|
|||||||
const PIVector<complex<T> > & calcFFT(const PIVector<T> & in) {
|
const PIVector<complex<T> > & calcFFT(const PIVector<T> & in) {
|
||||||
if (prepare != PlanParams(in.size(), fo_real)) {
|
if (prepare != PlanParams(in.size(), fo_real)) {
|
||||||
p_out.resize(in.size());
|
p_out.resize(in.size());
|
||||||
// piCout << "[PIFFTW]" << "creating plan";
|
piCout << "[PIFFTW]" << "creating plan";
|
||||||
p_createPlan_r2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_ESTIMATE | FFTW_UNALIGNED);
|
p_createPlan_r2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_ESTIMATE | FFTW_UNALIGNED);
|
||||||
prepare = PlanParams(in.size(), fo_real);
|
prepare = PlanParams(in.size(), fo_real);
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ public:
|
|||||||
const PIVector<complex<T> > & calcFFTinverse(const PIVector<complex<T> > & in) {
|
const PIVector<complex<T> > & calcFFTinverse(const PIVector<complex<T> > & in) {
|
||||||
if (prepare != PlanParams(in.size(), fo_inverse)) {
|
if (prepare != PlanParams(in.size(), fo_inverse)) {
|
||||||
p_out.resize(in.size());
|
p_out.resize(in.size());
|
||||||
// piCout << "[PIFFTW]" << "creating plan";
|
piCout << "[PIFFTW]" << "creating plan";
|
||||||
p_createPlan_c2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_BACKWARD, FFTW_ESTIMATE | FFTW_UNALIGNED);
|
p_createPlan_c2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_BACKWARD, FFTW_ESTIMATE | FFTW_UNALIGNED);
|
||||||
prepare = PlanParams(in.size(), fo_inverse);
|
prepare = PlanParams(in.size(), fo_inverse);
|
||||||
}
|
}
|
||||||
@@ -78,11 +79,7 @@ public:
|
|||||||
return p_out;
|
return p_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FFT_Operation {
|
enum FFT_Operation {fo_real, fo_complex, fo_inverse};
|
||||||
fo_real,
|
|
||||||
fo_complex,
|
|
||||||
fo_inverse
|
|
||||||
};
|
|
||||||
|
|
||||||
void preparePlan(int size, int op) {
|
void preparePlan(int size, int op) {
|
||||||
p_inr.clear();
|
p_inr.clear();
|
||||||
@@ -104,7 +101,9 @@ public:
|
|||||||
p_out.resize(size);
|
p_out.resize(size);
|
||||||
p_createPlan_c2c_1d(plan, size, p_in.data(), p_out.data(), FFTW_BACKWARD, FFTW_MEASURE | FFTW_UNALIGNED);
|
p_createPlan_c2c_1d(plan, size, p_in.data(), p_out.data(), FFTW_BACKWARD, FFTW_MEASURE | FFTW_UNALIGNED);
|
||||||
break;
|
break;
|
||||||
default: size = 0; break;
|
default:
|
||||||
|
size = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
prepare = PlanParams(size, (FFT_Operation)op);
|
prepare = PlanParams(size, (FFT_Operation)op);
|
||||||
}
|
}
|
||||||
@@ -118,14 +117,8 @@ public:
|
|||||||
inline void p_makeThreadSafe() {}
|
inline void p_makeThreadSafe() {}
|
||||||
|
|
||||||
struct PlanParams {
|
struct PlanParams {
|
||||||
PlanParams() {
|
PlanParams() {size = 0; op = fo_complex;}
|
||||||
size = 0;
|
PlanParams(int size_, FFT_Operation op_) {size = size_; op = op_;}
|
||||||
op = fo_complex;
|
|
||||||
}
|
|
||||||
PlanParams(int size_, FFT_Operation op_) {
|
|
||||||
size = size_;
|
|
||||||
op = op_;
|
|
||||||
}
|
|
||||||
bool isValid() {return size > 0;}
|
bool isValid() {return size > 0;}
|
||||||
bool operator ==(const PlanParams & v) const {return (v.size == size) && (v.op == op);}
|
bool operator ==(const PlanParams & v) const {return (v.size == size) && (v.op == op);}
|
||||||
bool operator !=(const PlanParams & v) const {return !(*this == v);}
|
bool operator !=(const PlanParams & v) const {return !(*this == v);}
|
||||||
@@ -142,104 +135,44 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
#ifdef PIP_FFTWf
|
#ifdef PIP_FFTWf
|
||||||
template<>
|
template<> inline void PIFFTW_Private<float>::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) {
|
||||||
inline void PIFFTW_Private<float>::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) {
|
plan = fftwf_plan_dft_1d(size, (fftwf_complex *)in, (fftwf_complex *)out, dir, flags);}
|
||||||
plan = fftwf_plan_dft_1d(size, (fftwf_complex *)in, (fftwf_complex *)out, dir, flags);
|
template<> inline void PIFFTW_Private<float>::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) {
|
||||||
}
|
plan = fftwf_plan_dft_r2c_1d(size, (float *)in, (fftwf_complex *)out, flags);}
|
||||||
template<>
|
template<> inline void PIFFTW_Private<float>::p_executePlan(void * plan) {fftwf_execute((fftwf_plan)plan);}
|
||||||
inline void PIFFTW_Private<float>::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) {
|
template<> inline void PIFFTW_Private<float>::p_executePlan_c2c(void * plan, const void * in, void * out) {fftwf_execute_dft((fftwf_plan)plan, (fftwf_complex *)in, (fftwf_complex *)out);}
|
||||||
plan = fftwf_plan_dft_r2c_1d(size, (float *)in, (fftwf_complex *)out, flags);
|
template<> inline void PIFFTW_Private<float>::p_executePlan_r2c(void * plan, const void * in, void * out) {fftwf_execute_dft_r2c((fftwf_plan)plan, (float *)in, (fftwf_complex *)out);}
|
||||||
}
|
template<> inline void PIFFTW_Private<float>::p_destroyPlan(void *& plan) {if (plan) fftwf_destroy_plan((fftwf_plan)plan); plan = 0;}
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<float>::p_executePlan(void * plan) {
|
|
||||||
fftwf_execute((fftwf_plan)plan);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<float>::p_executePlan_c2c(void * plan, const void * in, void * out) {
|
|
||||||
fftwf_execute_dft((fftwf_plan)plan, (fftwf_complex *)in, (fftwf_complex *)out);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<float>::p_executePlan_r2c(void * plan, const void * in, void * out) {
|
|
||||||
fftwf_execute_dft_r2c((fftwf_plan)plan, (float *)in, (fftwf_complex *)out);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<float>::p_destroyPlan(void *& plan) {
|
|
||||||
if (plan) fftwf_destroy_plan((fftwf_plan)plan);
|
|
||||||
plan = 0;
|
|
||||||
}
|
|
||||||
# ifdef PIP_FFTWf_THREADSAFE
|
# ifdef PIP_FFTWf_THREADSAFE
|
||||||
template<>
|
template<> inline void PIFFTW_Private<float>::p_makeThreadSafe() {fftwf_make_planner_thread_safe();}
|
||||||
inline void PIFFTW_Private<float>::p_makeThreadSafe() {
|
|
||||||
fftwf_make_planner_thread_safe();
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
#endif // PIP_FFTWf
|
#endif // PIP_FFTWf
|
||||||
|
|
||||||
#ifdef PIP_FFTW
|
#ifdef PIP_FFTW
|
||||||
template<>
|
template<> inline void PIFFTW_Private<double>::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) {
|
||||||
inline void PIFFTW_Private<double>::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) {
|
plan = fftw_plan_dft_1d(size, (fftw_complex *)in, (fftw_complex *)out, dir, flags);}
|
||||||
plan = fftw_plan_dft_1d(size, (fftw_complex *)in, (fftw_complex *)out, dir, flags);
|
template<> inline void PIFFTW_Private<double>::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) {
|
||||||
}
|
plan = fftw_plan_dft_r2c_1d(size, (double *)in, (fftw_complex *)out, flags);}
|
||||||
template<>
|
template<> inline void PIFFTW_Private<double>::p_executePlan(void * plan) {fftw_execute((fftw_plan)plan);}
|
||||||
inline void PIFFTW_Private<double>::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) {
|
template<> inline void PIFFTW_Private<double>::p_executePlan_c2c(void * plan, const void * in, void * out) {fftw_execute_dft((fftw_plan)plan, (fftw_complex *)in, (fftw_complex *)out);}
|
||||||
plan = fftw_plan_dft_r2c_1d(size, (double *)in, (fftw_complex *)out, flags);
|
template<> inline void PIFFTW_Private<double>::p_executePlan_r2c(void * plan, const void * in, void * out) {fftw_execute_dft_r2c((fftw_plan)plan, (double *)in, (fftw_complex *)out);}
|
||||||
}
|
template<> inline void PIFFTW_Private<double>::p_destroyPlan(void *& plan) {if (plan) fftw_destroy_plan((fftw_plan)plan); plan = 0;}
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<double>::p_executePlan(void * plan) {
|
|
||||||
fftw_execute((fftw_plan)plan);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<double>::p_executePlan_c2c(void * plan, const void * in, void * out) {
|
|
||||||
fftw_execute_dft((fftw_plan)plan, (fftw_complex *)in, (fftw_complex *)out);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<double>::p_executePlan_r2c(void * plan, const void * in, void * out) {
|
|
||||||
fftw_execute_dft_r2c((fftw_plan)plan, (double *)in, (fftw_complex *)out);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<double>::p_destroyPlan(void *& plan) {
|
|
||||||
if (plan) fftw_destroy_plan((fftw_plan)plan);
|
|
||||||
plan = 0;
|
|
||||||
}
|
|
||||||
# ifdef PIP_FFTW_THREADSAFE
|
# ifdef PIP_FFTW_THREADSAFE
|
||||||
template<>
|
template<> inline void PIFFTW_Private<double>::p_makeThreadSafe() {fftw_make_planner_thread_safe();}
|
||||||
inline void PIFFTW_Private<double>::p_makeThreadSafe() {
|
|
||||||
fftw_make_planner_thread_safe();
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
#endif // PIP_FFTW
|
#endif // PIP_FFTW
|
||||||
|
|
||||||
#ifdef PIP_FFTWl
|
#ifdef PIP_FFTWl
|
||||||
template<>
|
template<> inline void PIFFTW_Private<ldouble>::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) {
|
||||||
inline void PIFFTW_Private<ldouble>::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) {
|
plan = fftwl_plan_dft_1d(size, (fftwl_complex *)in, (fftwl_complex *)out, dir, flags);}
|
||||||
plan = fftwl_plan_dft_1d(size, (fftwl_complex *)in, (fftwl_complex *)out, dir, flags);
|
template<> inline void PIFFTW_Private<ldouble>::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) {
|
||||||
}
|
plan = fftwl_plan_dft_r2c_1d(size, (ldouble *)in, (fftwl_complex *)out, flags);}
|
||||||
template<>
|
template<> inline void PIFFTW_Private<ldouble>::p_executePlan(void * plan) {fftwl_execute((fftwl_plan)plan);}
|
||||||
inline void PIFFTW_Private<ldouble>::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) {
|
template<> inline void PIFFTW_Private<ldouble>::p_executePlan_c2c(void * plan, const void * in, void * out) {fftwl_execute_dft((fftwl_plan)plan, (fftwl_complex *)in, (fftwl_complex *)out);}
|
||||||
plan = fftwl_plan_dft_r2c_1d(size, (ldouble *)in, (fftwl_complex *)out, flags);
|
template<> inline void PIFFTW_Private<ldouble>::p_executePlan_r2c(void * plan, const void * in, void * out) {fftwl_execute_dft_r2c((fftwl_plan)plan, (ldouble *)in, (fftwl_complex *)out);}
|
||||||
}
|
template<> inline void PIFFTW_Private<ldouble>::p_destroyPlan(void *& plan) {if (plan) fftwl_destroy_plan((fftwl_plan)plan); plan = 0;}
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<ldouble>::p_executePlan(void * plan) {
|
|
||||||
fftwl_execute((fftwl_plan)plan);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<ldouble>::p_executePlan_c2c(void * plan, const void * in, void * out) {
|
|
||||||
fftwl_execute_dft((fftwl_plan)plan, (fftwl_complex *)in, (fftwl_complex *)out);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<ldouble>::p_executePlan_r2c(void * plan, const void * in, void * out) {
|
|
||||||
fftwl_execute_dft_r2c((fftwl_plan)plan, (ldouble *)in, (fftwl_complex *)out);
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline void PIFFTW_Private<ldouble>::p_destroyPlan(void *& plan) {
|
|
||||||
if (plan) fftwl_destroy_plan((fftwl_plan)plan);
|
|
||||||
plan = 0;
|
|
||||||
}
|
|
||||||
# ifdef PIP_FFTWl_THREADSAFE
|
# ifdef PIP_FFTWl_THREADSAFE
|
||||||
template<>
|
template<> inline void PIFFTW_Private<ldouble>::p_makeThreadSafe() {fftwl_make_planner_thread_safe();}
|
||||||
inline void PIFFTW_Private<ldouble>::p_makeThreadSafe() {
|
|
||||||
fftwl_make_planner_thread_safe();
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
#endif // PIP_FFTWl
|
#endif // PIP_FFTWl
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ void PIBroadcast::setMulticastPort(ushort port) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIBroadcast::setMulticastAddress(const PINetworkAddress & addr) {
|
void PIBroadcast::setMulticastAddress(const PIEthernet::Address & addr) {
|
||||||
PIMutexLocker ml(mcast_mutex);
|
PIMutexLocker ml(mcast_mutex);
|
||||||
mcast_address = addr;
|
mcast_address = addr;
|
||||||
_reinit = true;
|
_reinit = true;
|
||||||
@@ -126,16 +126,16 @@ void PIBroadcast::destroyAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIBroadcast::initAll(PIVector<PINetworkAddress> al) {
|
void PIBroadcast::initAll(PIVector<PIEthernet::Address> al) {
|
||||||
PIMutexLocker ml(mcast_mutex);
|
PIMutexLocker ml(mcast_mutex);
|
||||||
destroyAll();
|
destroyAll();
|
||||||
_reinit = false;
|
_reinit = false;
|
||||||
prev_al = al;
|
prev_al = al;
|
||||||
al.removeAll(PINetworkAddress("127.0.0.1"));
|
al.removeAll(PIEthernet::Address("127.0.0.1"));
|
||||||
al << mcast_address;
|
al << mcast_address;
|
||||||
eth_mcast.clear();
|
eth_mcast.clear();
|
||||||
PIEthernet::InterfaceList ifaces = PIEthernet::interfaces();
|
PIEthernet::InterfaceList ifaces = PIEthernet::interfaces();
|
||||||
piForeachC(PINetworkAddress & a, al) {
|
piForeachC (PIEthernet::Address & a, al) {
|
||||||
PIEthernet * ce = 0;
|
PIEthernet * ce = 0;
|
||||||
//piCout << "mcast try" << a;
|
//piCout << "mcast try" << a;
|
||||||
if (_channels[Multicast]) {
|
if (_channels[Multicast]) {
|
||||||
@@ -151,7 +151,7 @@ void PIBroadcast::initAll(PIVector<PINetworkAddress> al) {
|
|||||||
//piCout << "mcast " << ce->readAddress() << ce->sendAddress();
|
//piCout << "mcast " << ce->readAddress() << ce->sendAddress();
|
||||||
if (ce->open()) {
|
if (ce->open()) {
|
||||||
eth_mcast << ce;
|
eth_mcast << ce;
|
||||||
CONNECT2(void, const uchar *, ssize_t, ce, threadedReadEvent, this, mcastRead);
|
CONNECTU(ce, threadedReadEvent, this, mcastRead);
|
||||||
} else {
|
} else {
|
||||||
delete ce;
|
delete ce;
|
||||||
}
|
}
|
||||||
@@ -166,14 +166,14 @@ void PIBroadcast::initAll(PIVector<PINetworkAddress> al) {
|
|||||||
ce->setName("PIMulticast_" + a.toString());
|
ce->setName("PIMulticast_" + a.toString());
|
||||||
ce->setParameters(PIEthernet::Broadcast);
|
ce->setParameters(PIEthernet::Broadcast);
|
||||||
const PIEthernet::Interface * cint = ifaces.getByAddress(a.ipString());
|
const PIEthernet::Interface * cint = ifaces.getByAddress(a.ipString());
|
||||||
PINetworkAddress nm((cint == 0) ? "255.255.255.0" : cint->netmask);
|
PIEthernet::Address nm((cint == 0) ? "255.255.255.0" : cint->netmask);
|
||||||
ce->setSendAddress(PIEthernet::getBroadcast(a, nm).ipString(), bcast_port);
|
ce->setSendAddress(PIEthernet::getBroadcast(a, nm).ipString(), bcast_port);
|
||||||
if (!_send_only) {
|
if (!_send_only) {
|
||||||
ce->setReadAddress(PINetworkAddress(a.ip(), bcast_port));
|
ce->setReadAddress(PIEthernet::Address(a.ip(), bcast_port));
|
||||||
//piCout << "bcast " << ce->readAddress() << ce->sendAddress();
|
//piCout << "bcast " << ce->readAddress() << ce->sendAddress();
|
||||||
if (ce->open()) {
|
if (ce->open()) {
|
||||||
eth_mcast << ce;
|
eth_mcast << ce;
|
||||||
CONNECT2(void, const uchar *, ssize_t, ce, threadedReadEvent, this, mcastRead);
|
CONNECTU(ce, threadedReadEvent, this, mcastRead);
|
||||||
} else {
|
} else {
|
||||||
delete ce;
|
delete ce;
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ void PIBroadcast::initAll(PIVector<PINetworkAddress> al) {
|
|||||||
eth_lo->setName("PIMulticast_loopback");
|
eth_lo->setName("PIMulticast_loopback");
|
||||||
if (!_send_only) {
|
if (!_send_only) {
|
||||||
eth_lo->setParameter(PIEthernet::ReuseAddress, false);
|
eth_lo->setParameter(PIEthernet::ReuseAddress, false);
|
||||||
CONNECT2(void, const uchar *, ssize_t, eth_lo, threadedReadEvent, this, mcastRead);
|
CONNECTU(eth_lo, threadedReadEvent, this, mcastRead);
|
||||||
for (int i = 0; i < lo_pcnt; ++i) {
|
for (int i = 0; i < lo_pcnt; ++i) {
|
||||||
eth_lo->setReadAddress("127.0.0.1", lo_port + i);
|
eth_lo->setReadAddress("127.0.0.1", lo_port + i);
|
||||||
if (eth_lo->open()) {
|
if (eth_lo->open()) {
|
||||||
@@ -210,8 +210,7 @@ void PIBroadcast::send(const PIByteArray & data) {
|
|||||||
PIByteArray cd = cryptData(data);
|
PIByteArray cd = cryptData(data);
|
||||||
if (cd.isEmpty()) return;
|
if (cd.isEmpty()) return;
|
||||||
PIMutexLocker ml(mcast_mutex);
|
PIMutexLocker ml(mcast_mutex);
|
||||||
piForeach(PIEthernet * e, eth_mcast)
|
piForeach (PIEthernet * e, eth_mcast) e->send(cd);
|
||||||
e->send(cd);
|
|
||||||
if (eth_lo) {
|
if (eth_lo) {
|
||||||
for (int i = 0; i < lo_pcnt; ++i) {
|
for (int i = 0; i < lo_pcnt; ++i) {
|
||||||
eth_lo->send("127.0.0.1", lo_port + i, cd);
|
eth_lo->send("127.0.0.1", lo_port + i, cd);
|
||||||
@@ -228,8 +227,7 @@ void PIBroadcast::startRead() {
|
|||||||
}
|
}
|
||||||
if (_send_only) return;
|
if (_send_only) return;
|
||||||
PIMutexLocker ml(mcast_mutex);
|
PIMutexLocker ml(mcast_mutex);
|
||||||
piForeach(PIEthernet * e, eth_mcast)
|
piForeach (PIEthernet * e, eth_mcast) e->startThreadedRead();
|
||||||
e->startThreadedRead();
|
|
||||||
if (eth_lo) eth_lo->startThreadedRead();
|
if (eth_lo) eth_lo->startThreadedRead();
|
||||||
_started = true;
|
_started = true;
|
||||||
}
|
}
|
||||||
@@ -238,8 +236,7 @@ void PIBroadcast::startRead() {
|
|||||||
void PIBroadcast::stopRead() {
|
void PIBroadcast::stopRead() {
|
||||||
if (isRunning()) stop();
|
if (isRunning()) stop();
|
||||||
PIMutexLocker ml(mcast_mutex);
|
PIMutexLocker ml(mcast_mutex);
|
||||||
piForeach(PIEthernet * e, eth_mcast)
|
piForeach (PIEthernet * e, eth_mcast) e->stopThreadedRead();
|
||||||
e->stopThreadedRead();
|
|
||||||
if (eth_lo) eth_lo->stopThreadedRead();
|
if (eth_lo) eth_lo->stopThreadedRead();
|
||||||
_started = false;
|
_started = false;
|
||||||
}
|
}
|
||||||
@@ -251,7 +248,7 @@ void PIBroadcast::reinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIBroadcast::mcastRead(const uchar * data, ssize_t size) {
|
void PIBroadcast::mcastRead(uchar * data, int size) {
|
||||||
PIByteArray cd = decryptData(PIByteArray(data, size));
|
PIByteArray cd = decryptData(PIByteArray(data, size));
|
||||||
if (cd.isEmpty()) return;
|
if (cd.isEmpty()) return;
|
||||||
received(cd);
|
received(cd);
|
||||||
@@ -260,7 +257,7 @@ void PIBroadcast::mcastRead(const uchar * data, ssize_t size) {
|
|||||||
|
|
||||||
|
|
||||||
void PIBroadcast::run() {
|
void PIBroadcast::run() {
|
||||||
PIVector<PINetworkAddress> al = PIEthernet::allAddresses();
|
PIVector<PIEthernet::Address> al = PIEthernet::allAddresses();
|
||||||
mcast_mutex.lock();
|
mcast_mutex.lock();
|
||||||
bool r = _reinit, ac = (al != prev_al);
|
bool r = _reinit, ac = (al != prev_al);
|
||||||
mcast_mutex.unlock();
|
mcast_mutex.unlock();
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ PIEthUtilBase::PIEthUtilBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIEthUtilBase::~PIEthUtilBase() {}
|
PIEthUtilBase::~PIEthUtilBase() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIEthUtilBase::setCryptEnabled(bool on) {
|
void PIEthUtilBase::setCryptEnabled(bool on) {
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
# pragma GCC diagnostic ignored "-Wnonnull"
|
# pragma GCC diagnostic ignored "-Wnonnull"
|
||||||
#endif
|
#endif
|
||||||
#include "pistreampacker.h"
|
#include "pistreampacker.h"
|
||||||
|
|
||||||
#include "piiodevice.h"
|
#include "piiodevice.h"
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# pragma GCC diagnostic pop
|
# pragma GCC diagnostic pop
|
||||||
@@ -62,8 +61,7 @@ PIStreamPacker::PIStreamPacker(PIIODevice * dev): PIObject() {
|
|||||||
void PIStreamPacker::setCryptSizeEnabled(bool on) {
|
void PIStreamPacker::setCryptSizeEnabled(bool on) {
|
||||||
crypt_size = on;
|
crypt_size = on;
|
||||||
if (crypt_size) {
|
if (crypt_size) {
|
||||||
PIByteArray ba;
|
PIByteArray ba; ba << int(0);
|
||||||
ba << int(0);
|
|
||||||
size_crypted_size = cryptData(ba).size_s();
|
size_crypted_size = cryptData(ba).size_s();
|
||||||
} else
|
} else
|
||||||
size_crypted_size = sizeof(int);
|
size_crypted_size = sizeof(int);
|
||||||
@@ -85,10 +83,8 @@ void PIStreamPacker::send(const PIByteArray & data) {
|
|||||||
//piCout << "crypt_frag send" << fcnt << "frags";
|
//piCout << "crypt_frag send" << fcnt << "frags";
|
||||||
PIByteArray frag;
|
PIByteArray frag;
|
||||||
for (int i = 0; i < fcnt; ++i) {
|
for (int i = 0; i < fcnt; ++i) {
|
||||||
if (i == fcnt - 1)
|
if (i == fcnt - 1) frag = PIByteArray(data.data(fst), data.size_s() - fst);
|
||||||
frag = PIByteArray(data.data(fst), data.size_s() - fst);
|
else frag = PIByteArray(data.data(fst), crypt_frag_size);
|
||||||
else
|
|
||||||
frag = PIByteArray(data.data(fst), crypt_frag_size);
|
|
||||||
fst += crypt_frag_size;
|
fst += crypt_frag_size;
|
||||||
cd << cryptData(frag);
|
cd << cryptData(frag);
|
||||||
}
|
}
|
||||||
@@ -99,18 +95,15 @@ void PIStreamPacker::send(const PIByteArray & data) {
|
|||||||
PIByteArray hdr, part;
|
PIByteArray hdr, part;
|
||||||
hdr << packet_sign;
|
hdr << packet_sign;
|
||||||
if (crypt_size) {
|
if (crypt_size) {
|
||||||
PIByteArray crsz;
|
PIByteArray crsz; crsz << int(cd.size_s());
|
||||||
crsz << int(cd.size_s());
|
|
||||||
hdr.append(cryptData(crsz));
|
hdr.append(cryptData(crsz));
|
||||||
} else
|
} else
|
||||||
hdr << int(cd.size_s());
|
hdr << int(cd.size_s());
|
||||||
cd.insert(0, hdr);
|
cd.insert(0, hdr);
|
||||||
int pcnt = (cd.size_s() - 1) / max_packet_size + 1, pst = 0;
|
int pcnt = (cd.size_s() - 1) / max_packet_size + 1, pst = 0;
|
||||||
for (int i = 0; i < pcnt; ++i) {
|
for (int i = 0; i < pcnt; ++i) {
|
||||||
if (i == pcnt - 1)
|
if (i == pcnt - 1) part = PIByteArray(cd.data(pst), cd.size_s() - pst);
|
||||||
part = PIByteArray(cd.data(pst), cd.size_s() - pst);
|
else part = PIByteArray(cd.data(pst), max_packet_size);
|
||||||
else
|
|
||||||
part = PIByteArray(cd.data(pst), max_packet_size);
|
|
||||||
//piCout << "send" << part.size();
|
//piCout << "send" << part.size();
|
||||||
sendRequest(part);
|
sendRequest(part);
|
||||||
pst += max_packet_size;
|
pst += max_packet_size;
|
||||||
@@ -118,7 +111,7 @@ void PIStreamPacker::send(const PIByteArray & data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIStreamPacker::received(const uchar * readed, ssize_t size) {
|
void PIStreamPacker::received(uchar * readed, int size) {
|
||||||
received(PIByteArray(readed, size));
|
received(PIByteArray(readed, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,10 +126,8 @@ void PIStreamPacker::received(const PIByteArray & data) {
|
|||||||
ushort sign(0);
|
ushort sign(0);
|
||||||
memcpy(&sign, stream.data(), 2);
|
memcpy(&sign, stream.data(), 2);
|
||||||
if (sign != packet_sign) {
|
if (sign != packet_sign) {
|
||||||
if (aggressive_optimization)
|
if (aggressive_optimization) stream.clear();
|
||||||
stream.clear();
|
else stream.pop_front();
|
||||||
else
|
|
||||||
stream.pop_front();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int sz = -1;
|
int sz = -1;
|
||||||
@@ -145,10 +136,8 @@ void PIStreamPacker::received(const PIByteArray & data) {
|
|||||||
memcpy(crsz.data(), stream.data(2), size_crypted_size);
|
memcpy(crsz.data(), stream.data(2), size_crypted_size);
|
||||||
crsz = decryptData(crsz);
|
crsz = decryptData(crsz);
|
||||||
if (crsz.size() < sizeof(sz)) {
|
if (crsz.size() < sizeof(sz)) {
|
||||||
if (aggressive_optimization)
|
if (aggressive_optimization) stream.clear();
|
||||||
stream.clear();
|
else stream.pop_front();
|
||||||
else
|
|
||||||
stream.pop_front();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
crsz >> sz;
|
crsz >> sz;
|
||||||
@@ -156,16 +145,15 @@ void PIStreamPacker::received(const PIByteArray & data) {
|
|||||||
memcpy(&sz, stream.data(2), size_crypted_size);
|
memcpy(&sz, stream.data(2), size_crypted_size);
|
||||||
}
|
}
|
||||||
if (sz < 0) {
|
if (sz < 0) {
|
||||||
if (aggressive_optimization)
|
if (aggressive_optimization) stream.clear();
|
||||||
stream.clear();
|
else stream.pop_front();
|
||||||
else
|
|
||||||
stream.pop_front();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
stream.remove(0, hdr_size);
|
stream.remove(0, hdr_size);
|
||||||
packet.clear();
|
packet.clear();
|
||||||
packet_size = sz;
|
packet_size = sz;
|
||||||
if (packet_size == 0) packet_size = -1;
|
if (packet_size == 0)
|
||||||
|
packet_size = -1;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
int ps = piMini(stream.size_s(), packet_size - packet.size_s());
|
int ps = piMini(stream.size_s(), packet_size - packet.size_s());
|
||||||
@@ -207,9 +195,8 @@ void PIStreamPacker::received(const PIByteArray & data) {
|
|||||||
|
|
||||||
void PIStreamPacker::assignDevice(PIIODevice * dev) {
|
void PIStreamPacker::assignDevice(PIIODevice * dev) {
|
||||||
if (!dev) return;
|
if (!dev) return;
|
||||||
if (!dev->infoFlags()[PIIODevice::Reliable]) {
|
if (!dev->infoFlags()[PIIODevice::Reliable])
|
||||||
piCoutObj << "Warning! Not recommended to use with non-reliable" << dev;
|
piCoutObj << "Warning! Not recommended to use with non-reliable" << dev;
|
||||||
}
|
CONNECTU(dev, threadedReadEvent, this, received);
|
||||||
CONNECT2(void, const uchar *, ssize_t, dev, threadedReadEvent, this, received);
|
CONNECTU(this, sendRequest, dev, write);
|
||||||
CONNECT1(void, PIByteArray, this, sendRequest, dev, write);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,3 +50,4 @@ luabridge::LuaRef PILuaProgram::getGlobal(const PIString & name) {
|
|||||||
luabridge::Namespace PILuaProgram::getGlobalNamespace() {
|
luabridge::Namespace PILuaProgram::getGlobalNamespace() {
|
||||||
return luabridge::getGlobalNamespace(PRIVATE->lua_state);
|
return luabridge::getGlobalNamespace(PRIVATE->lua_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,8 @@
|
|||||||
#include "pistreampacker.h"
|
#include "pistreampacker.h"
|
||||||
|
|
||||||
|
|
||||||
class PIP_CLOUD_EXPORT PICloudBase {
|
class PIP_CLOUD_EXPORT PICloudBase
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
PICloudBase();
|
PICloudBase();
|
||||||
|
|
||||||
|
|||||||
@@ -32,11 +32,9 @@
|
|||||||
|
|
||||||
//! \brief PICloudClient
|
//! \brief PICloudClient
|
||||||
|
|
||||||
class PIP_CLOUD_EXPORT PICloudClient
|
class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase
|
||||||
: public PIIODevice
|
{
|
||||||
, public PICloudBase {
|
PIIODEVICE(PICloudClient, "")
|
||||||
PIIODEVICE(PICloudClient, "");
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
||||||
virtual ~PICloudClient();
|
virtual ~PICloudClient();
|
||||||
@@ -44,18 +42,16 @@ public:
|
|||||||
void setServerName(const PIString & server_name);
|
void setServerName(const PIString & server_name);
|
||||||
void setKeepConnection(bool on);
|
void setKeepConnection(bool on);
|
||||||
bool isConnected() const {return is_connected;}
|
bool isConnected() const {return is_connected;}
|
||||||
ssize_t bytesAvailable() const override { return buff.size(); }
|
|
||||||
void interrupt() override;
|
|
||||||
|
|
||||||
EVENT(connected);
|
EVENT(connected)
|
||||||
EVENT(disconnected);
|
EVENT(disconnected)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool openDevice() override;
|
bool openDevice();
|
||||||
bool closeDevice() override;
|
bool closeDevice();
|
||||||
ssize_t readDevice(void * read_to, ssize_t max_size) override;
|
int readDevice(void * read_to, int max_size);
|
||||||
ssize_t writeDevice(const void * data, ssize_t size) override;
|
int writeDevice(const void * data, int size);
|
||||||
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
|
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EVENT_HANDLER1(void, _readed, PIByteArray &, data);
|
EVENT_HANDLER1(void, _readed, PIByteArray &, data);
|
||||||
|
|||||||
@@ -51,8 +51,8 @@
|
|||||||
#ifndef PICLOUDMODULE_H
|
#ifndef PICLOUDMODULE_H
|
||||||
#define PICLOUDMODULE_H
|
#define PICLOUDMODULE_H
|
||||||
|
|
||||||
|
#include "picloudtcp.h"
|
||||||
#include "picloudclient.h"
|
#include "picloudclient.h"
|
||||||
#include "picloudserver.h"
|
#include "picloudserver.h"
|
||||||
#include "picloudtcp.h"
|
|
||||||
|
|
||||||
#endif // PICLOUDMODULE_H
|
#endif // PICLOUDMODULE_H
|
||||||
|
|||||||
@@ -30,32 +30,26 @@
|
|||||||
#include "piconditionvar.h"
|
#include "piconditionvar.h"
|
||||||
|
|
||||||
|
|
||||||
class PIP_CLOUD_EXPORT PICloudServer
|
class PIP_CLOUD_EXPORT PICloudServer: public PIIODevice, public PICloudBase
|
||||||
: public PIIODevice
|
{
|
||||||
, public PICloudBase {
|
PIIODEVICE(PICloudServer, "")
|
||||||
PIIODEVICE(PICloudServer, "");
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! PICloudServer
|
//! PICloudServer
|
||||||
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
|
||||||
virtual ~PICloudServer();
|
virtual ~PICloudServer();
|
||||||
|
|
||||||
class Client : public PIIODevice {
|
class Client : public PIIODevice {
|
||||||
PIIODEVICE(PICloudServer::Client, "");
|
PIIODEVICE(PICloudServer::Client, "")
|
||||||
friend class PICloudServer;
|
friend class PICloudServer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Client(PICloudServer * srv = nullptr, uint id = 0);
|
Client(PICloudServer * srv = nullptr, uint id = 0);
|
||||||
virtual ~Client();
|
virtual ~Client();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool openDevice() override;
|
bool openDevice();
|
||||||
bool closeDevice() override;
|
bool closeDevice();
|
||||||
ssize_t readDevice(void * read_to, ssize_t max_size) override;
|
int readDevice(void * read_to, int max_size);
|
||||||
ssize_t writeDevice(const void * data, ssize_t size) override;
|
int writeDevice(const void * data, int size);
|
||||||
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
|
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
|
||||||
ssize_t bytesAvailable() const override { return buff.size(); }
|
|
||||||
void interrupt() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void pushBuffer(const PIByteArray & ba);
|
void pushBuffer(const PIByteArray & ba);
|
||||||
@@ -71,14 +65,13 @@ public:
|
|||||||
|
|
||||||
PIVector<PICloudServer::Client *> clients() const;
|
PIVector<PICloudServer::Client *> clients() const;
|
||||||
|
|
||||||
EVENT1(newConnection, PICloudServer::Client *, client);
|
EVENT1(newConnection, PICloudServer::Client * , client)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool openDevice() override;
|
bool openDevice();
|
||||||
bool closeDevice() override;
|
bool closeDevice();
|
||||||
ssize_t readDevice(void * read_to, ssize_t max_size) override;
|
int readDevice(void * read_to, int max_size);
|
||||||
ssize_t writeDevice(const void * data, ssize_t max_size) override;
|
int writeDevice(const void * data, int max_size);
|
||||||
void interrupt() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EVENT_HANDLER1(void, _readed, PIByteArray &, ba);
|
EVENT_HANDLER1(void, _readed, PIByteArray &, ba);
|
||||||
@@ -87,13 +80,9 @@ private:
|
|||||||
int sendData(const PIByteArray & data, uint client_id);
|
int sendData(const PIByteArray & data, uint client_id);
|
||||||
|
|
||||||
PIVector<Client *> clients_;
|
PIVector<Client *> clients_;
|
||||||
PIVector<Client *> removed_clients_;
|
|
||||||
PIMap<uint, Client *> index_clients;
|
PIMap<uint, Client *> index_clients;
|
||||||
PITimer ping_timer;
|
PITimer ping_timer;
|
||||||
PIConditionVariable cvar;
|
|
||||||
PIMutex open_mutex;
|
|
||||||
mutable PIMutex clients_mutex;
|
mutable PIMutex clients_mutex;
|
||||||
std::atomic_bool is_deleted;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PICLOUDSERVER_H
|
#endif // PICLOUDSERVER_H
|
||||||
|
|||||||
@@ -26,9 +26,9 @@
|
|||||||
#ifndef PICLOUDTCP_H
|
#ifndef PICLOUDTCP_H
|
||||||
#define PICLOUDTCP_H
|
#define PICLOUDTCP_H
|
||||||
|
|
||||||
#include "pimutex.h"
|
|
||||||
#include "pip_cloud_export.h"
|
#include "pip_cloud_export.h"
|
||||||
#include "pistring.h"
|
#include "pistring.h"
|
||||||
|
#include "pimutex.h"
|
||||||
|
|
||||||
|
|
||||||
class PIEthernet;
|
class PIEthernet;
|
||||||
@@ -37,6 +37,7 @@ class PIStreamPacker;
|
|||||||
namespace PICloud {
|
namespace PICloud {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PIP_CLOUD_EXPORT TCP {
|
class PIP_CLOUD_EXPORT TCP {
|
||||||
public:
|
public:
|
||||||
enum Version {
|
enum Version {
|
||||||
@@ -90,8 +91,9 @@ private:
|
|||||||
PIString server_name;
|
PIString server_name;
|
||||||
PIStreamPacker * streampacker;
|
PIStreamPacker * streampacker;
|
||||||
PIMutex mutex_send;
|
PIMutex mutex_send;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace PICloud
|
}
|
||||||
|
|
||||||
#endif // PICLOUDTCP_H
|
#endif // PICLOUDTCP_H
|
||||||
|
|||||||
@@ -18,68 +18,45 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "picodeinfo.h"
|
#include "picodeinfo.h"
|
||||||
|
|
||||||
#include "pivariant.h"
|
#include "pivariant.h"
|
||||||
|
|
||||||
|
|
||||||
PIString PICodeInfo::EnumInfo::memberName(int value_) const {
|
PIString PICodeInfo::EnumInfo::memberName(int value_) const {
|
||||||
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
|
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
|
||||||
if (e.value == value_) return e.name.toString();
|
if (e.value == value_)
|
||||||
|
return e.name.toString();
|
||||||
return PIString();
|
return PIString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const {
|
int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const {
|
||||||
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
|
piForeachC (PICodeInfo::EnumeratorInfo & e, members)
|
||||||
if (e.name.toString() == name_) return e.value;
|
if (e.name.toString() == name_)
|
||||||
|
return e.value;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIVariantTypes::Enum PICodeInfo::EnumInfo::toPIVariantEnum() {
|
PIVariantTypes::Enum PICodeInfo::EnumInfo::toPIVariantEnum() {
|
||||||
PIVariantTypes::Enum en(name.toString());
|
PIVariantTypes::Enum en(name.toString());
|
||||||
for (auto m: members)
|
for (auto m: members) en << m.toPIVariantEnumerator();
|
||||||
en << m.toPIVariantEnumerator();
|
|
||||||
if (!en.isEmpty()) en.selectValue(members.front().value);
|
if (!en.isEmpty()) en.selectValue(members.front().value);
|
||||||
return en;
|
return en;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIMap<PIConstChars, PICodeInfo::ClassInfo * > * PICodeInfo::classesInfo;
|
||||||
|
PIMap<PIConstChars, PICodeInfo::EnumInfo * > * PICodeInfo::enumsInfo;
|
||||||
|
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * PICodeInfo::accessValueFunctions;
|
||||||
|
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * PICodeInfo::accessTypeFunctions;
|
||||||
|
|
||||||
|
bool __PICodeInfoInitializer__::_inited_ = false;
|
||||||
|
|
||||||
|
|
||||||
PIVariant PICodeInfo::getMemberAsVariant(const void * p, const char * class_name, const char * member_name) {
|
PIVariant PICodeInfo::getMemberAsVariant(const void * p, const char * class_name, const char * member_name) {
|
||||||
if (!p || !class_name || !member_name) return PIVariant();
|
if (!p || !class_name || !member_name || !accessTypeFunctions || !accessValueFunctions) return PIVariant();
|
||||||
AccessTypeFunction atf = PICODEINFO::accessTypeFunctions().value(class_name, (AccessTypeFunction) nullptr);
|
AccessTypeFunction atf = accessTypeFunctions->value(class_name, (AccessTypeFunction)0);
|
||||||
AccessValueFunction avf = PICODEINFO::accessValueFunctions().value(class_name, (AccessValueFunction) nullptr);
|
AccessValueFunction avf = accessValueFunctions->value(class_name, (AccessValueFunction)0);
|
||||||
if (!atf || !avf) return PIVariant();
|
if (!atf || !avf) return PIVariant();
|
||||||
return PIVariant::fromValue(avf(p, member_name), PIStringAscii(atf(member_name)));
|
return PIVariant::fromValue(avf(p, member_name), PIStringAscii(atf(member_name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICodeInfo::__Storage__::__Storage__() {
|
|
||||||
classesInfo = new PIMap<PIConstChars, ClassInfo *>;
|
|
||||||
enumsInfo = new PIMap<PIConstChars, EnumInfo *>;
|
|
||||||
accessValueFunctions = new PIMap<PIConstChars, AccessValueFunction>;
|
|
||||||
accessTypeFunctions = new PIMap<PIConstChars, AccessTypeFunction>;
|
|
||||||
(*enumsInfo)[""] = new EnumInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PICodeInfo::__Storage__::~__Storage__() {
|
|
||||||
piDeleteAll(classesInfo->values());
|
|
||||||
piDeleteAll(enumsInfo->values());
|
|
||||||
piDeleteSafety(classesInfo);
|
|
||||||
piDeleteSafety(enumsInfo);
|
|
||||||
piDeleteSafety(accessValueFunctions);
|
|
||||||
piDeleteSafety(accessTypeFunctions);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PICodeInfo::__Storage__ * PICodeInfo::__Storage__::instance() {
|
|
||||||
static __Storage__ ret;
|
|
||||||
return &ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PICodeInfo::ClassInfoInterface classesInfo;
|
|
||||||
PICodeInfo::EnumsInfoInterface enumsInfo;
|
|
||||||
PICodeInfo::AccessValueFunctionInterface accessValueFunctions;
|
|
||||||
PICodeInfo::AccessTypeFunctionInterface accessTypeFunctions;
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*! \file picodeinfo.h
|
/*! \file picodeinfo.h
|
||||||
* \ingroup Code
|
* \ingroup Code
|
||||||
* \~\brief
|
* \~\brief
|
||||||
* \~english C++ code info structs. See \ref code_model.
|
* \~english C++ code info structs
|
||||||
* \~russian Структуры для C++ кода. Подробнее \ref code_model.
|
* \~russian Структуры для C++ кода
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
PIP - Platform Independent Primitives
|
PIP - Platform Independent Primitives
|
||||||
@@ -34,24 +34,17 @@
|
|||||||
|
|
||||||
class PIVariant;
|
class PIVariant;
|
||||||
|
|
||||||
//! \~english Namespace contains structures for code generation. See \ref code_model.
|
|
||||||
//! \~russian Пространство имен содержит структуры для кодогенерации. Подробнее \ref code_model.
|
|
||||||
namespace PICodeInfo {
|
namespace PICodeInfo {
|
||||||
|
|
||||||
|
|
||||||
//! \~english
|
|
||||||
//! Type modifiers
|
|
||||||
//! \~russian
|
|
||||||
//! Модификаторы типа
|
|
||||||
enum TypeFlag {
|
enum TypeFlag {
|
||||||
NoFlag,
|
NoFlag,
|
||||||
Const /** const */ = 0x01,
|
Const = 0x01,
|
||||||
Static /** static */ = 0x02,
|
Static = 0x02,
|
||||||
Mutable /** mutable */ = 0x04,
|
Mutable = 0x04,
|
||||||
Volatile /** volatile */ = 0x08,
|
Volatile = 0x08,
|
||||||
Inline /** inline */ = 0x10,
|
Inline = 0x10,
|
||||||
Virtual /** virtual */ = 0x20,
|
Virtual = 0x20,
|
||||||
Extern /** extern */ = 0x40
|
Extern = 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
|
typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
|
||||||
@@ -59,151 +52,49 @@ typedef PIMap<PIString, PIString> MetaMap;
|
|||||||
typedef PIByteArray(*AccessValueFunction)(const void *, const char *);
|
typedef PIByteArray(*AccessValueFunction)(const void *, const char *);
|
||||||
typedef const char*(*AccessTypeFunction)(const char *);
|
typedef const char*(*AccessTypeFunction)(const char *);
|
||||||
|
|
||||||
|
|
||||||
//! \~english Type information
|
|
||||||
//! \~russian Информация о типе
|
|
||||||
struct PIP_EXPORT TypeInfo {
|
struct PIP_EXPORT TypeInfo {
|
||||||
TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {
|
TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {name = n; type = t; flags = f; bits = b;}
|
||||||
name = n;
|
|
||||||
type = t;
|
|
||||||
flags = f;
|
|
||||||
bits = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns if variable if bitfield
|
|
||||||
//! \~russian Возвращает битовым ли полем является переменная
|
|
||||||
bool isBitfield() const {return bits > 0;}
|
bool isBitfield() const {return bits > 0;}
|
||||||
|
|
||||||
//! \~english Custom PIMETA content
|
|
||||||
//! \~russian Произвольное содержимое PIMETA
|
|
||||||
MetaMap meta;
|
MetaMap meta;
|
||||||
|
|
||||||
//! \~english Name
|
|
||||||
//! \~russian Имя
|
|
||||||
PIConstChars name;
|
PIConstChars name;
|
||||||
|
|
||||||
//! \~english Type
|
|
||||||
//! \~russian Тип
|
|
||||||
PIConstChars type;
|
PIConstChars type;
|
||||||
|
|
||||||
//! \~english Modifiers
|
|
||||||
//! \~russian Модификаторы
|
|
||||||
PICodeInfo::TypeFlags flags;
|
PICodeInfo::TypeFlags flags;
|
||||||
|
|
||||||
//! \~english Bitfield variable bit count
|
|
||||||
//! \~russian Количество бит битового поля
|
|
||||||
int bits;
|
int bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \~english Method information
|
|
||||||
//! \~russian Информация о методе
|
|
||||||
struct PIP_EXPORT FunctionInfo {
|
struct PIP_EXPORT FunctionInfo {
|
||||||
//! \~english Custom PIMETA content
|
|
||||||
//! \~russian Произвольное содержимое PIMETA
|
|
||||||
MetaMap meta;
|
MetaMap meta;
|
||||||
|
|
||||||
//! \~english Name
|
|
||||||
//! \~russian Имя
|
|
||||||
PIConstChars name;
|
PIConstChars name;
|
||||||
|
|
||||||
//! \~english Return type
|
|
||||||
//! \~russian Возвращаемые тип
|
|
||||||
TypeInfo return_type;
|
TypeInfo return_type;
|
||||||
|
|
||||||
//! \~english Arguments types
|
|
||||||
//! \~russian Типы аргументов
|
|
||||||
PIVector<PICodeInfo::TypeInfo> arguments;
|
PIVector<PICodeInfo::TypeInfo> arguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \~english Class or struct information
|
|
||||||
//! \~russian Информация о классе или структуре
|
|
||||||
struct PIP_EXPORT ClassInfo {
|
struct PIP_EXPORT ClassInfo {
|
||||||
ClassInfo() {has_name = true;}
|
ClassInfo() {has_name = true;}
|
||||||
|
|
||||||
//! \~english Custom PIMETA content
|
|
||||||
//! \~russian Произвольное содержимое PIMETA
|
|
||||||
MetaMap meta;
|
MetaMap meta;
|
||||||
|
|
||||||
//! \~english Has name or not
|
|
||||||
//! \~russian Имеет или нет имя
|
|
||||||
bool has_name;
|
bool has_name;
|
||||||
|
|
||||||
//! \~english Type
|
|
||||||
//! \~russian Тип
|
|
||||||
PIConstChars type;
|
PIConstChars type;
|
||||||
|
|
||||||
//! \~english Name
|
|
||||||
//! \~russian Имя
|
|
||||||
PIConstChars name;
|
PIConstChars name;
|
||||||
|
|
||||||
//! \~english Parent names
|
|
||||||
//! \~russian Имена родителей
|
|
||||||
PIVector<PIConstChars> parents;
|
PIVector<PIConstChars> parents;
|
||||||
|
|
||||||
//! \~english Variables
|
|
||||||
//! \~russian Переменные
|
|
||||||
PIVector<PICodeInfo::TypeInfo> variables;
|
PIVector<PICodeInfo::TypeInfo> variables;
|
||||||
|
|
||||||
//! \~english Methods
|
|
||||||
//! \~russian Методы
|
|
||||||
PIVector<PICodeInfo::FunctionInfo> functions;
|
PIVector<PICodeInfo::FunctionInfo> functions;
|
||||||
|
|
||||||
//! \~english Subclass list
|
|
||||||
//! \~russian Список наследников
|
|
||||||
PIVector<PICodeInfo::ClassInfo * > children_info;
|
PIVector<PICodeInfo::ClassInfo * > children_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \~english Enumerator information
|
|
||||||
//! \~russian Информация об элементе перечисления
|
|
||||||
struct PIP_EXPORT EnumeratorInfo {
|
struct PIP_EXPORT EnumeratorInfo {
|
||||||
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {
|
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {name = n; value = v;}
|
||||||
name = n;
|
|
||||||
value = v;
|
|
||||||
}
|
|
||||||
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name.toString());}
|
PIVariantTypes::Enumerator toPIVariantEnumerator() {return PIVariantTypes::Enumerator(value, name.toString());}
|
||||||
|
|
||||||
//! \~english Custom PIMETA content
|
|
||||||
//! \~russian Произвольное содержимое PIMETA
|
|
||||||
MetaMap meta;
|
MetaMap meta;
|
||||||
|
|
||||||
//! \~english Name
|
|
||||||
//! \~russian Имя
|
|
||||||
PIConstChars name;
|
PIConstChars name;
|
||||||
|
|
||||||
//! \~english Value
|
|
||||||
//! \~russian Значение
|
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \~english Enum information
|
|
||||||
//! \~russian Информация о перечислении
|
|
||||||
struct PIP_EXPORT EnumInfo {
|
struct PIP_EXPORT EnumInfo {
|
||||||
//! \~english Returns member name with value "value"
|
|
||||||
//! \~russian Возвращает имя элемента со значением "value"
|
|
||||||
PIString memberName(int value) const;
|
PIString memberName(int value) const;
|
||||||
|
|
||||||
//! \~english Returns member value with name "name"
|
|
||||||
//! \~russian Возвращает значение элемента с именем "name"
|
|
||||||
int memberValue(const PIString & name) const;
|
int memberValue(const PIString & name) const;
|
||||||
|
|
||||||
//! \~english Returns as PIVariantTypes::Enum
|
|
||||||
//! \~russian Возвращает как PIVariantTypes::Enum
|
|
||||||
PIVariantTypes::Enum toPIVariantEnum();
|
PIVariantTypes::Enum toPIVariantEnum();
|
||||||
|
|
||||||
//! \~english Custom PIMETA content
|
|
||||||
//! \~russian Произвольное содержимое PIMETA
|
|
||||||
MetaMap meta;
|
MetaMap meta;
|
||||||
|
|
||||||
//! \~english Name
|
|
||||||
//! \~russian Имя
|
|
||||||
PIConstChars name;
|
PIConstChars name;
|
||||||
|
|
||||||
//! \~english Members
|
|
||||||
//! \~russian Элементы
|
|
||||||
PIVector<PICodeInfo::EnumeratorInfo> members;
|
PIVector<PICodeInfo::EnumeratorInfo> members;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,26 +107,22 @@ inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
|
|||||||
if (v.flags[Static]) s << "static ";
|
if (v.flags[Static]) s << "static ";
|
||||||
if (v.flags[Const]) s << "const ";
|
if (v.flags[Const]) s << "const ";
|
||||||
s << v.type;
|
s << v.type;
|
||||||
if (!v.name.isEmpty()) s << " " << v.name;
|
if (!v.name.isEmpty())
|
||||||
|
s << " " << v.name;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PICout operator<<(PICout s, const PICodeInfo::EnumeratorInfo & v) {
|
inline PICout operator <<(PICout s, const PICodeInfo::EnumeratorInfo & v) {s << v.name << " = " << v.value << " Meta" << v.meta; return s;}
|
||||||
s << v.name << " = " << v.value << " Meta" << v.meta;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
|
inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) {
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "class " << v.name;
|
s << "class " << v.name;
|
||||||
if (!v.parents.isEmpty()) {
|
if (!v.parents.isEmpty()) {
|
||||||
s << ": ";
|
s << ": ";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (const auto & i: v.parents) {
|
for (const auto & i: v.parents) {
|
||||||
if (first)
|
if (first) first = false;
|
||||||
first = false;
|
else s << ", ";
|
||||||
else
|
|
||||||
s << ", ";
|
|
||||||
s << i;
|
s << i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,132 +131,51 @@ inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
|
|||||||
s << PICoutManipulators::Tab << i.return_type << " " << i.name << "(";
|
s << PICoutManipulators::Tab << i.return_type << " " << i.name << "(";
|
||||||
bool fa = true;
|
bool fa = true;
|
||||||
for (const auto & a: i.arguments) {
|
for (const auto & a: i.arguments) {
|
||||||
if (fa)
|
if (fa) fa = false;
|
||||||
fa = false;
|
else s << ", ";
|
||||||
else
|
|
||||||
s << ", ";
|
|
||||||
s << a;
|
s << a;
|
||||||
}
|
}
|
||||||
s << ") Meta" << i.meta << ";\n";
|
s << ") Meta" << i.meta << ";\n";
|
||||||
}
|
}
|
||||||
if (!v.functions.isEmpty() && !v.variables.isEmpty()) s << "\n";
|
if (!v.functions.isEmpty() && !v.variables.isEmpty())
|
||||||
|
s << "\n";
|
||||||
for (const auto & i: v.variables) {
|
for (const auto & i: v.variables) {
|
||||||
s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n";
|
s << PICoutManipulators::Tab << i << " Meta" << i.meta << ";\n";
|
||||||
}
|
}
|
||||||
s << "}\n";
|
s << "}\n";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
|
inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) {
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "enum " << v.name << " Meta" << v.meta << " {\n";
|
s << "enum " << v.name << " Meta" << v.meta << " {\n";
|
||||||
for (const auto & i: v.members) {
|
for (const auto & i: v.members) {
|
||||||
bool f = true;
|
bool f = true;
|
||||||
if (f)
|
if (f) f = false;
|
||||||
f = false;
|
else s << ", ";
|
||||||
else
|
|
||||||
s << ", ";
|
|
||||||
s << PICoutManipulators::Tab << i << "\n";
|
s << PICoutManipulators::Tab << i << "\n";
|
||||||
}
|
}
|
||||||
s << "}\n";
|
s << "}\n";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::ClassInfo * > * classesInfo;
|
||||||
class PIP_EXPORT __Storage__ {
|
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::EnumInfo * > * enumsInfo;
|
||||||
__Storage__();
|
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
|
||||||
~__Storage__();
|
extern PIP_EXPORT PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
|
||||||
|
|
||||||
public:
|
|
||||||
static __Storage__ * instance();
|
|
||||||
|
|
||||||
PIMap<PIConstChars, PICodeInfo::ClassInfo *> * classesInfo;
|
|
||||||
PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo;
|
|
||||||
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
|
|
||||||
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
|
|
||||||
|
|
||||||
private:
|
|
||||||
NO_COPY_CLASS(__Storage__)
|
|
||||||
};
|
|
||||||
|
|
||||||
class PIP_EXPORT __StorageAccess__ {
|
|
||||||
public:
|
|
||||||
//! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name
|
|
||||||
//! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени
|
|
||||||
static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes() { return *(__Storage__::instance()->classesInfo); }
|
|
||||||
|
|
||||||
//! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name
|
|
||||||
//! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени
|
|
||||||
static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { return *(__Storage__::instance()->enumsInfo); }
|
|
||||||
|
|
||||||
static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() {
|
|
||||||
return *(__Storage__::instance()->accessValueFunctions);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() {
|
|
||||||
return *(__Storage__::instance()->accessTypeFunctions);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PICODEINFO PICodeInfo::__StorageAccess__
|
|
||||||
|
|
||||||
|
|
||||||
class PIP_EXPORT ClassInfoInterface {
|
|
||||||
public:
|
|
||||||
const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()") {
|
|
||||||
return __Storage__::instance()->classesInfo;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static ClassInfoInterface classesInfo;
|
|
||||||
|
|
||||||
|
|
||||||
class PIP_EXPORT EnumsInfoInterface {
|
|
||||||
public:
|
|
||||||
const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()") {
|
|
||||||
return __Storage__::instance()->enumsInfo;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static EnumsInfoInterface enumsInfo;
|
|
||||||
|
|
||||||
|
|
||||||
class PIP_EXPORT AccessValueFunctionInterface {
|
|
||||||
public:
|
|
||||||
const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessValueFunctions()") {
|
|
||||||
return __Storage__::instance()->accessValueFunctions;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static AccessValueFunctionInterface accessValueFunctions;
|
|
||||||
|
|
||||||
|
|
||||||
class PIP_EXPORT AccessTypeFunctionInterface {
|
|
||||||
public:
|
|
||||||
const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()") {
|
|
||||||
return __Storage__::instance()->accessTypeFunctions;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static AccessTypeFunctionInterface accessTypeFunctions;
|
|
||||||
|
|
||||||
|
|
||||||
STATIC_INITIALIZER_BEGIN
|
|
||||||
NO_UNUSED(classesInfo);
|
|
||||||
NO_UNUSED(enumsInfo);
|
|
||||||
NO_UNUSED(accessValueFunctions);
|
|
||||||
NO_UNUSED(accessTypeFunctions);
|
|
||||||
STATIC_INITIALIZER_END
|
|
||||||
|
|
||||||
|
|
||||||
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {
|
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {
|
||||||
if (!p || !class_name || !member_name) return PIByteArray();
|
if (!p || !class_name || !member_name || !accessValueFunctions) return PIByteArray();
|
||||||
AccessValueFunction af = PICODEINFO::accessValueFunctions().value(class_name, (AccessValueFunction)0);
|
AccessValueFunction af = accessValueFunctions->value(class_name, (AccessValueFunction)0);
|
||||||
if (!af) return PIByteArray();
|
if (!af) return PIByteArray();
|
||||||
return af(p, member_name);
|
return af(p, member_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char * getMemberType(const char * class_name, const char * member_name) {
|
inline const char * getMemberType(const char * class_name, const char * member_name) {
|
||||||
if (!class_name || !member_name) return "";
|
if (!class_name || !member_name || !accessTypeFunctions) return "";
|
||||||
AccessTypeFunction af = PICODEINFO::accessTypeFunctions().value(class_name, (AccessTypeFunction)0);
|
AccessTypeFunction af = accessTypeFunctions->value(class_name, (AccessTypeFunction)0);
|
||||||
if (!af) return "";
|
if (!af) return "";
|
||||||
return af(member_name);
|
return af(member_name);
|
||||||
}
|
}
|
||||||
@@ -378,14 +184,26 @@ PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name,
|
|||||||
|
|
||||||
|
|
||||||
template<typename T, typename std::enable_if< std::is_assignable<T&, const T&>::value, int>::type = 0>
|
template<typename T, typename std::enable_if< std::is_assignable<T&, const T&>::value, int>::type = 0>
|
||||||
void serialize(PIByteArray & ret, const T & v) {
|
void serialize(PIByteArray & ret, const T & v) {ret << v;}
|
||||||
ret << v;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename std::enable_if<!std::is_assignable<T&, const T&>::value, int>::type = 0>
|
template<typename T, typename std::enable_if<!std::is_assignable<T&, const T&>::value, int>::type = 0>
|
||||||
void serialize(PIByteArray & ret, const T & v) {}
|
void serialize(PIByteArray & ret, const T & v) {}
|
||||||
|
|
||||||
} // namespace PICodeInfo
|
}
|
||||||
|
|
||||||
|
class PIP_EXPORT __PICodeInfoInitializer__ {
|
||||||
|
public:
|
||||||
|
__PICodeInfoInitializer__() {
|
||||||
|
if (_inited_) return;
|
||||||
|
_inited_ = true;
|
||||||
|
PICodeInfo::classesInfo = new PIMap<PIConstChars, PICodeInfo::ClassInfo * >;
|
||||||
|
PICodeInfo::enumsInfo = new PIMap<PIConstChars, PICodeInfo::EnumInfo * >;
|
||||||
|
PICodeInfo::accessValueFunctions = new PIMap<PIConstChars, PICodeInfo::AccessValueFunction>;
|
||||||
|
PICodeInfo::accessTypeFunctions = new PIMap<PIConstChars, PICodeInfo::AccessTypeFunction>;
|
||||||
|
}
|
||||||
|
static bool _inited_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static __PICodeInfoInitializer__ __picodeinfoinitializer__;
|
||||||
|
|
||||||
#endif // PICODEINFO_H
|
#endif // PICODEINFO_H
|
||||||
|
|||||||
@@ -35,11 +35,9 @@
|
|||||||
//!
|
//!
|
||||||
//! \~english
|
//! \~english
|
||||||
//! These files provides parsing C++ code and storage to use results of \a pip_cmg utility.
|
//! These files provides parsing C++ code and storage to use results of \a pip_cmg utility.
|
||||||
//! See \ref code_model.
|
|
||||||
//!
|
//!
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! Эти файлы обеспечивают разбор C++ кода и хранение результатов работы утилиты \a pip_cmg.
|
//! Эти файлы обеспечивают разбор C++ кода и хранение результатов работы утилиты \a pip_cmg.
|
||||||
//! Подробнее \ref code_model.
|
|
||||||
//!
|
//!
|
||||||
//! \~\authors
|
//! \~\authors
|
||||||
//! \~english
|
//! \~english
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "picodeparser.h"
|
#include "picodeparser.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
|
PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
|
||||||
PIStringList arg_vals;
|
PIStringList arg_vals;
|
||||||
while (!args_.isEmpty()) {
|
while (!args_.isEmpty()) {
|
||||||
@@ -31,20 +32,17 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
|
|||||||
PIString ca;
|
PIString ca;
|
||||||
if (bi >= 0 && bi < ci) {
|
if (bi >= 0 && bi < ci) {
|
||||||
ca = args_.left(args_.takeLeft(bi).toInt());
|
ca = args_.left(args_.takeLeft(bi).toInt());
|
||||||
ci -= ca.size_s();
|
ci -= ca.size_s(); bi -= ca.size_s();
|
||||||
bi -= ca.size_s();
|
|
||||||
ca += '(' + args_.takeRange('(', ')') + ')';
|
ca += '(' + args_.takeRange('(', ')') + ')';
|
||||||
} else {
|
} else {
|
||||||
ca = args_.takeLeft(ci);
|
ca = args_.takeLeft(ci);
|
||||||
}
|
}
|
||||||
arg_vals << ca;
|
arg_vals << ca;
|
||||||
args_.trim();
|
args_.trim(); args_.takeLeft(1); args_.trim();
|
||||||
args_.takeLeft(1);
|
|
||||||
args_.trim();
|
|
||||||
}
|
}
|
||||||
if (args.size() != arg_vals.size()) {
|
if (args.size() != arg_vals.size()) {
|
||||||
piCout << ("Error: in expansion of macro \"" + name + '(' + args.join(", ") + ")\": expect") << args.size() << "arguments but takes"
|
piCout << ("Error: in expansion of macro \"" + name + '(' + args.join(", ") + ")\": expect")
|
||||||
<< arg_vals.size() << "!";
|
<< args.size() << "arguments but takes" << arg_vals.size() << "!";
|
||||||
if (ok != 0) *ok = false;
|
if (ok != 0) *ok = false;
|
||||||
return PIString();
|
return PIString();
|
||||||
}
|
}
|
||||||
@@ -74,6 +72,7 @@ PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PICodeParser::PICodeParser() {
|
PICodeParser::PICodeParser() {
|
||||||
macros_iter = 32;
|
macros_iter = 32;
|
||||||
with_includes = true;
|
with_includes = true;
|
||||||
@@ -139,14 +138,10 @@ void PICodeParser::parseFiles(const PIStringList & files, bool follow_includes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PICodeParser::parseFileContent(PIString fc) {
|
|
||||||
parseFileContent(fc, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PICodeParser::isEnum(const PIString & name) {
|
bool PICodeParser::isEnum(const PIString & name) {
|
||||||
piForeachC (Enum & e, enums)
|
piForeachC (Enum & e, enums)
|
||||||
if (e.name == name) return true;
|
if (e.name == name)
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +174,7 @@ bool PICodeParser::parseFileInternal(const PIString & file, bool follow_includes
|
|||||||
|
|
||||||
|
|
||||||
void PICodeParser::clear() {
|
void PICodeParser::clear() {
|
||||||
piForeach(Entity * i, entities)
|
piForeach (Entity * i, entities) delete i;
|
||||||
delete i;
|
|
||||||
defines.clear();
|
defines.clear();
|
||||||
macros.clear();
|
macros.clear();
|
||||||
enums.clear();
|
enums.clear();
|
||||||
@@ -198,137 +192,32 @@ void PICodeParser::clear() {
|
|||||||
defines << Define(PIStringAscii("PICODE"), "") << custom_defines;
|
defines << Define(PIStringAscii("PICODE"), "") << custom_defines;
|
||||||
macros << Macro(PIStringAscii("PIOBJECT"), "", PIStringList() << "name")
|
macros << Macro(PIStringAscii("PIOBJECT"), "", PIStringList() << "name")
|
||||||
<< Macro(PIStringAscii("PIOBJECT_PARENT"), "", PIStringList() << "parent")
|
<< Macro(PIStringAscii("PIOBJECT_PARENT"), "", PIStringList() << "parent")
|
||||||
<< Macro(PIStringAscii("PIOBJECT_SUBCLASS"),
|
<< Macro(PIStringAscii("PIOBJECT_SUBCLASS"), "", PIStringList() << "name" << "parent")
|
||||||
"",
|
|
||||||
PIStringList() << "name"
|
|
||||||
<< "parent")
|
|
||||||
<< Macro(PIStringAscii("PIIODEVICE"), "", PIStringList() << "name")
|
<< Macro(PIStringAscii("PIIODEVICE"), "", PIStringList() << "name")
|
||||||
<< Macro(PIStringAscii("NO_COPY_CLASS"), "", PIStringList() << "name") << Macro(PIStringAscii("PRIVATE_DECLARATION"))
|
<< Macro(PIStringAscii("NO_COPY_CLASS"), "", PIStringList() << "name")
|
||||||
|
<< Macro(PIStringAscii("PRIVATE_DECLARATION"))
|
||||||
|
|
||||||
<< Macro(PIStringAscii("EVENT" ), "void name();", PIStringList() << "name")
|
<< Macro(PIStringAscii("EVENT" ), "void name();", PIStringList() << "name")
|
||||||
<< Macro(PIStringAscii("EVENT0"), "void name();", PIStringList() << "name")
|
<< Macro(PIStringAscii("EVENT0"), "void name();", PIStringList() << "name")
|
||||||
<< Macro(PIStringAscii("EVENT1"),
|
<< Macro(PIStringAscii("EVENT1"), "void name(a0 n0);", PIStringList() << "name" << "a0" << "n0")
|
||||||
"void name(a0 n0);",
|
<< Macro(PIStringAscii("EVENT2"), "void name(a0 n0, a1 n1);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1")
|
||||||
PIStringList() << "name"
|
<< Macro(PIStringAscii("EVENT3"), "void name(a0 n0, a1 n1, a2 n2);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
|
||||||
<< "a0"
|
<< Macro(PIStringAscii("EVENT4"), "void name(a0 n0, a1 n1, a2 n2, a3 n3);", PIStringList() << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2" << "a3" << "n3")
|
||||||
<< "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"),
|
<< Macro(PIStringAscii("EVENT_HANDLER" ), "ret name()", PIStringList() << "ret" << "name")
|
||||||
"ret name()",
|
<< Macro(PIStringAscii("EVENT_HANDLER0"), "ret name()", PIStringList() << "ret" << "name")
|
||||||
PIStringList() << "ret"
|
<< Macro(PIStringAscii("EVENT_HANDLER1"), "ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
|
||||||
<< "name")
|
<< Macro(PIStringAscii("EVENT_HANDLER2"), "ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
|
||||||
<< Macro(PIStringAscii("EVENT_HANDLER0"),
|
<< Macro(PIStringAscii("EVENT_HANDLER3"), "ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
|
||||||
"ret name()",
|
<< 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")
|
||||||
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"),
|
<< Macro(PIStringAscii("EVENT_VHANDLER" ), "virtual ret name()", PIStringList() << "ret" << "name")
|
||||||
"virtual ret name()",
|
<< Macro(PIStringAscii("EVENT_VHANDLER0"), "virtual ret name()", PIStringList() << "ret" << "name")
|
||||||
PIStringList() << "ret"
|
<< Macro(PIStringAscii("EVENT_VHANDLER1"), "virtual ret name(a0 n0)", PIStringList() << "ret" << "name" << "a0" << "n0")
|
||||||
<< "name")
|
<< Macro(PIStringAscii("EVENT_VHANDLER2"), "virtual ret name(a0 n0, a1 n1)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1")
|
||||||
<< Macro(PIStringAscii("EVENT_VHANDLER0"),
|
<< Macro(PIStringAscii("EVENT_VHANDLER3"), "virtual ret name(a0 n0, a1 n1, a2 n2)", PIStringList() << "ret" << "name" << "a0" << "n0" << "a1" << "n1" << "a2" << "n2")
|
||||||
"virtual ret name()",
|
<< 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")
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -358,8 +247,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
if (i > 0) pc = c;
|
if (i > 0) pc = c;
|
||||||
c = fc[i].toAscii();
|
c = fc[i].toAscii();
|
||||||
if (c == '"' && !mlc && pc != '\'') {
|
if (c == '"' && !mlc && pc != '\'') {
|
||||||
if (i > 0)
|
if (i > 0) if (fc[i - 1] == '\\') continue;
|
||||||
if (fc[i - 1] == '\\') continue;
|
|
||||||
cc = !cc;
|
cc = !cc;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -370,24 +258,9 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cc) continue;
|
if (cc) continue;
|
||||||
if (fc.mid(i, 2) == "/*") {
|
if (fc.mid(i, 2) == "/*") {mlc = true; mls = i; ++i; continue;}
|
||||||
mlc = true;
|
if (fc.mid(i, 2) == "*/" && mlc) {mlc = false; fc.cutMid(mls, i - mls + 2); i = mls - 1; continue;}
|
||||||
mls = i;
|
if (fc.mid(i, 2) == "//" && !mlc) {ole = fc.find('\n', i); fc.cutMid(i, ole < 0 ? -1 : ole - i); --i; continue;}
|
||||||
++i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (fc.mid(i, 2) == "*/" && mlc) {
|
|
||||||
mlc = false;
|
|
||||||
fc.cutMid(mls, i - mls + 2);
|
|
||||||
i = mls - 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (fc.mid(i, 2) == "//" && !mlc) {
|
|
||||||
ole = fc.find('\n', i);
|
|
||||||
fc.cutMid(i, ole < 0 ? -1 : ole - i);
|
|
||||||
--i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pfc = procMacros(fc);
|
pfc = procMacros(fc);
|
||||||
|
|
||||||
@@ -422,8 +295,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
if (ind > 0) pc = pfc[ind - 1];
|
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 (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;
|
if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue;
|
||||||
PIString ret, range;
|
PIString ret, range; bool ok(false);
|
||||||
bool ok(false);
|
|
||||||
range = pfc.mid(ind + m.name.size_s()).takeRange('(', ')');
|
range = pfc.mid(ind + m.name.size_s()).takeRange('(', ')');
|
||||||
ret = m.expand(range, &ok);
|
ret = m.expand(range, &ok);
|
||||||
if (!ok) return false;
|
if (!ok) return false;
|
||||||
@@ -439,7 +311,6 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
|
|
||||||
//piCout << PICoutManipulators::NewLine << "file" << cur_file << pfc;
|
//piCout << PICoutManipulators::NewLine << "file" << cur_file << pfc;
|
||||||
int pl = -1;
|
int pl = -1;
|
||||||
cur_def_vis = Global;
|
|
||||||
while (!pfc.isEmpty()) {
|
while (!pfc.isEmpty()) {
|
||||||
pfc.trim();
|
pfc.trim();
|
||||||
int nl = pfc.size_s();
|
int nl = pfc.size_s();
|
||||||
@@ -450,7 +321,6 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
PIString prev_namespace = cur_namespace, ccmn;
|
PIString prev_namespace = cur_namespace, ccmn;
|
||||||
cur_namespace += pfc.takeCWord() + s_ns;
|
cur_namespace += pfc.takeCWord() + s_ns;
|
||||||
ccmn = pfc.takeRange('{', '}');
|
ccmn = pfc.takeRange('{', '}');
|
||||||
// piCout << "namespace" << cur_namespace;
|
|
||||||
parseClass(0, ccmn, true);
|
parseClass(0, ccmn, true);
|
||||||
cur_namespace = prev_namespace;
|
cur_namespace = prev_namespace;
|
||||||
continue;
|
continue;
|
||||||
@@ -460,25 +330,14 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
pfc.takeRange('<', '>');
|
pfc.takeRange('<', '>');
|
||||||
bool def = !isDeclaration(pfc, 0, &end);
|
bool def = !isDeclaration(pfc, 0, &end);
|
||||||
pfc.cutLeft(end);
|
pfc.cutLeft(end);
|
||||||
if (def)
|
if (def) pfc.takeRange('{', '}');
|
||||||
pfc.takeRange('{', '}');
|
else pfc.takeSymbol();
|
||||||
else
|
|
||||||
pfc.takeSymbol();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pfc.left(5) == s_class || pfc.left(6) == s_struct || pfc.left(5) == s_union) {
|
if (pfc.left(5) == s_class || pfc.left(6) == s_struct || pfc.left(5) == s_union) {
|
||||||
int dind = pfc.find('{', 0), find = pfc.find(';', 0);
|
int dind = pfc.find('{', 0), find = pfc.find(';', 0);
|
||||||
// piCout << pfc.left(6) << dind << find;
|
if (dind < 0 && find < 0) {pfc.cutLeft(6); continue;}
|
||||||
if (dind < 0 && find < 0) {
|
if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;}
|
||||||
pfc.cutLeft(6);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (dind < 0 || find < dind) {
|
|
||||||
// piCout << "skip FC" << (find + 1) << pfc.left(find + 1);
|
|
||||||
pfc.cutLeft(find + 1);
|
|
||||||
// pfc.cutLeft(6);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
|
ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
|
||||||
pfc.remove(0, ccmn.size());
|
pfc.remove(0, ccmn.size());
|
||||||
parseClass(0, ccmn, false);
|
parseClass(0, ccmn, false);
|
||||||
@@ -489,12 +348,6 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
tmp = pfc.takeCWord();
|
tmp = pfc.takeCWord();
|
||||||
pfc.trim();
|
pfc.trim();
|
||||||
MetaMap meta = maybeMeta(pfc);
|
MetaMap meta = maybeMeta(pfc);
|
||||||
if (tmp == s_class || tmp == s_struct) {
|
|
||||||
tmp = pfc.takeCWord();
|
|
||||||
pfc.trim();
|
|
||||||
MetaMap smeta = maybeMeta(pfc);
|
|
||||||
meta << smeta;
|
|
||||||
}
|
|
||||||
parseEnum(0, cur_namespace + tmp, pfc.takeRange('{', '}'), meta);
|
parseEnum(0, cur_namespace + tmp, pfc.takeRange('{', '}'), meta);
|
||||||
pfc.takeSymbol();
|
pfc.takeSymbol();
|
||||||
continue;
|
continue;
|
||||||
@@ -502,10 +355,8 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
|
|||||||
if (pfc.left(7) == s_typedef) {
|
if (pfc.left(7) == s_typedef) {
|
||||||
pfc.cutLeft(7);
|
pfc.cutLeft(7);
|
||||||
typedefs << parseTypedef(pfc.takeLeft(pfc.find(';')));
|
typedefs << parseTypedef(pfc.takeLeft(pfc.find(';')));
|
||||||
if (typedefs.back().first.isEmpty())
|
if (typedefs.back().first.isEmpty()) typedefs.pop_back();
|
||||||
typedefs.pop_back();
|
else root_.typedefs << typedefs.back();
|
||||||
else
|
|
||||||
root_.typedefs << typedefs.back();
|
|
||||||
pfc.takeSymbol();
|
pfc.takeSymbol();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -547,33 +398,27 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
|
|||||||
cd.cutRight(1);
|
cd.cutRight(1);
|
||||||
Entity * pe = 0;
|
Entity * pe = 0;
|
||||||
piForeachC (PIString & p, pl) {
|
piForeachC (PIString & p, pl) {
|
||||||
if (p.contains(' '))
|
if (p.contains(' ')) pn = p.mid(p.find(' ') + 1);
|
||||||
pn = p.mid(p.find(' ') + 1);
|
else pn = p;
|
||||||
else
|
|
||||||
pn = p;
|
|
||||||
pe = findEntityByName(pn);
|
pe = findEntityByName(pn);
|
||||||
if (pe == 0)
|
if (pe == 0) ;//{piCout << "Error: can`t find" << pn;}
|
||||||
; //{piCout << "Error: can`t find" << pn;}
|
else parents << pe;
|
||||||
else
|
|
||||||
parents << pe;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PIString typename_ = cd.left(6).trim();
|
PIString typename_ = cd.left(6).trim();
|
||||||
bool is_class = typename_ == s_class;
|
bool is_class = typename_ == s_class;
|
||||||
Visibility vis = cur_def_vis;
|
|
||||||
cur_def_vis = (is_class ? Private : Public);
|
cur_def_vis = (is_class ? Private : Public);
|
||||||
PIString cn = cd.mid(6).trim();
|
PIString cn = cd.mid(6).trim();
|
||||||
bool has_name = !cn.isEmpty();
|
bool has_name = !cn.isEmpty();
|
||||||
if (cn.isEmpty()) cn = PIStringAscii("<unnamed_") + PIString::fromNumber(anon_num++) + '>';
|
if (cn.isEmpty()) cn = PIStringAscii("<unnamed_") + PIString::fromNumber(anon_num++) + '>';
|
||||||
//piCout << "found " << typename_ << cn;
|
//piCout << "found " << typename_ << cn;
|
||||||
if (cn.isEmpty()) return nullptr;
|
if (cn.isEmpty()) return 0;
|
||||||
Entity * e = new Entity();
|
Entity * e = new Entity();
|
||||||
e->meta = meta;
|
e->meta = meta;
|
||||||
e->name = cur_namespace + cn;
|
e->name = cur_namespace + cn;
|
||||||
e->type = typename_;
|
e->type = typename_;
|
||||||
e->has_name = has_name;
|
e->has_name = has_name;
|
||||||
e->parents = parents;
|
e->parents = parents;
|
||||||
e->visibility = vis;
|
|
||||||
e->file = cur_file;
|
e->file = cur_file;
|
||||||
entities << e;
|
entities << e;
|
||||||
return e;
|
return e;
|
||||||
@@ -596,6 +441,10 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
|
|||||||
Visibility prev_vis = cur_def_vis;
|
Visibility prev_vis = cur_def_vis;
|
||||||
int dind = fc.find('{'), find = fc.find(';'), end = 0;
|
int dind = fc.find('{'), find = fc.find(';'), end = 0;
|
||||||
if (dind < 0 && find < 0) return;
|
if (dind < 0 && find < 0) return;
|
||||||
|
if (dind < 0 || find < dind) {
|
||||||
|
fc.left(find);
|
||||||
|
return;
|
||||||
|
}
|
||||||
//piCout << "parse class <****\n" << fc << "\n****>";
|
//piCout << "parse class <****\n" << fc << "\n****>";
|
||||||
Entity * ce = parent;
|
Entity * ce = parent;
|
||||||
if (!is_namespace) {
|
if (!is_namespace) {
|
||||||
@@ -603,6 +452,7 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
|
|||||||
fc.trim().cutLeft(1).cutRight(1).trim();
|
fc.trim().cutLeft(1).cutRight(1).trim();
|
||||||
}
|
}
|
||||||
//piCout << "found class <****\n" << fc << "\n****>";
|
//piCout << "found class <****\n" << fc << "\n****>";
|
||||||
|
///if (!ce) return PIString();
|
||||||
if (ce) {
|
if (ce) {
|
||||||
if (parent) parent->children << ce;
|
if (parent) parent->children << ce;
|
||||||
ce->parent_scope = parent;
|
ce->parent_scope = parent;
|
||||||
@@ -616,21 +466,9 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
|
|||||||
while (!fc.isEmpty()) {
|
while (!fc.isEmpty()) {
|
||||||
PIString cw = fc.takeCWord(), tmp;
|
PIString cw = fc.takeCWord(), tmp;
|
||||||
//piCout << "\ntaked word" << cw;
|
//piCout << "\ntaked word" << cw;
|
||||||
if (cw == s_public) {
|
if (cw == s_public ) {cur_def_vis = Public; fc.cutLeft(1); continue;}
|
||||||
cur_def_vis = Public;
|
if (cw == s_protected) {cur_def_vis = Protected; fc.cutLeft(1); continue;}
|
||||||
fc.cutLeft(1);
|
if (cw == s_private ) {cur_def_vis = Private; fc.cutLeft(1); continue;}
|
||||||
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) {
|
if (cw == s_namespace) {
|
||||||
PIString prev_namespace = cur_namespace, ccmn;
|
PIString prev_namespace = cur_namespace, ccmn;
|
||||||
cur_namespace += fc.takeCWord() + s_ns;
|
cur_namespace += fc.takeCWord() + s_ns;
|
||||||
@@ -640,7 +478,6 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cw == s_class || cw == s_struct || cw == s_union) {
|
if (cw == s_class || cw == s_struct || cw == s_union) {
|
||||||
// piCout << cw << isDeclaration(fc, 0, &end);
|
|
||||||
if (isDeclaration(fc, 0, &end)) {
|
if (isDeclaration(fc, 0, &end)) {
|
||||||
fc.cutLeft(end);
|
fc.cutLeft(end);
|
||||||
fc.takeSymbol();
|
fc.takeSymbol();
|
||||||
@@ -657,26 +494,18 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
|
|||||||
tmp = fc.takeCWord();
|
tmp = fc.takeCWord();
|
||||||
fc.trim();
|
fc.trim();
|
||||||
MetaMap meta = maybeMeta(fc);
|
MetaMap meta = maybeMeta(fc);
|
||||||
if (tmp == s_class || tmp == s_struct) {
|
|
||||||
tmp = fc.takeCWord();
|
|
||||||
fc.trim();
|
|
||||||
MetaMap smeta = maybeMeta(fc);
|
|
||||||
meta << smeta;
|
|
||||||
}
|
|
||||||
parseEnum(ce, cur_namespace + tmp, fc.takeRange('{', '}'), meta);
|
parseEnum(ce, cur_namespace + tmp, fc.takeRange('{', '}'), meta);
|
||||||
fc.takeSymbol();
|
fc.takeSymbol();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (cw == s_friend) {
|
if (cw == s_friend) {fc.cutLeft(fc.find(';') + 1); continue;}
|
||||||
fc.cutLeft(fc.find(';') + 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cw == s_typedef) {
|
if (cw == s_typedef) {
|
||||||
if (ce) {
|
if (ce) {
|
||||||
ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';')));
|
ce->typedefs << parseTypedef(fc.takeLeft(fc.find(';')));
|
||||||
typedefs << ce->typedefs.back();
|
typedefs << ce->typedefs.back();
|
||||||
typedefs.back().first.insert(0, cur_namespace);
|
typedefs.back().first.insert(0, cur_namespace);
|
||||||
if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back();
|
if (ce->typedefs.back().first.isEmpty())
|
||||||
|
ce->typedefs.pop_back();
|
||||||
}
|
}
|
||||||
fc.takeSymbol();
|
fc.takeSymbol();
|
||||||
continue;
|
continue;
|
||||||
@@ -685,22 +514,17 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
|
|||||||
fc.takeRange('<', '>');
|
fc.takeRange('<', '>');
|
||||||
def = !isDeclaration(fc, 0, &end);
|
def = !isDeclaration(fc, 0, &end);
|
||||||
fc.cutLeft(end);
|
fc.cutLeft(end);
|
||||||
if (def)
|
if (def) fc.takeRange('{', '}');
|
||||||
fc.takeRange('{', '}');
|
else fc.takeSymbol();
|
||||||
else
|
|
||||||
fc.takeSymbol();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
def = !isDeclaration(fc, 0, &end);
|
def = !isDeclaration(fc, 0, &end);
|
||||||
tmp = (cw + fc.takeLeft(end)).trim();
|
tmp = (cw + fc.takeLeft(end)).trim();
|
||||||
if (!tmp.isEmpty() && ce) parseMember(ce, tmp);
|
if (!tmp.isEmpty() && ce)
|
||||||
if (def)
|
parseMember(ce, tmp);
|
||||||
fc.takeRange('{', '}');
|
if (def) fc.takeRange('{', '}');
|
||||||
else
|
else fc.takeSymbol();
|
||||||
fc.takeSymbol();
|
if (ps == fc.size_s()) {fc.cutLeft(1);}
|
||||||
if (ps == fc.size_s()) {
|
|
||||||
fc.cutLeft(1);
|
|
||||||
}
|
|
||||||
ps = fc.size_s();
|
ps = fc.size_s();
|
||||||
}
|
}
|
||||||
cur_def_vis = prev_vis;
|
cur_def_vis = prev_vis;
|
||||||
@@ -744,17 +568,14 @@ bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc
|
|||||||
meta = tmp_meta.value(v.takeMid(mi, 5));
|
meta = tmp_meta.value(v.takeMid(mi, 5));
|
||||||
v.replaceAll(s_ss, ' ');
|
v.replaceAll(s_ss, ' ');
|
||||||
}
|
}
|
||||||
vn = v;
|
vn = v; ind = v.find('=');
|
||||||
ind = v.find('=');
|
if (ind > 0) {cv = v.right(v.size_s() - ind - 1).toInt(); vn = v.left(ind);}
|
||||||
if (ind > 0) {
|
|
||||||
cv = v.right(v.size_s() - ind - 1).toInt();
|
|
||||||
vn = v.left(ind);
|
|
||||||
}
|
|
||||||
if (ind < 0) ++cv;
|
if (ind < 0) ++cv;
|
||||||
e.members << EnumeratorInfo(vn.trim(), cv, meta);
|
e.members << EnumeratorInfo(vn.trim(), cv, meta);
|
||||||
}
|
}
|
||||||
if (!e.members.isEmpty())
|
if (!e.members.isEmpty())
|
||||||
if (e.members.back().name.isEmpty()) e.members.pop_back();
|
if (e.members.back().name.isEmpty())
|
||||||
|
e.members.pop_back();
|
||||||
enums << e;
|
enums << e;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -768,10 +589,7 @@ PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) {
|
|||||||
if (fc.contains('(')) {
|
if (fc.contains('(')) {
|
||||||
int start = fc.find('('), end = fc.find(')');
|
int start = fc.find('('), end = fc.find(')');
|
||||||
td.first = fc.takeMid(start + 1, end - start - 1).trim();
|
td.first = fc.takeMid(start + 1, end - start - 1).trim();
|
||||||
if (td.first.left(1) == PIChar('*')) {
|
if (td.first.left(1) == PIChar('*')) {td.first.cutLeft(1).trim(); fc.insert(start + 1, '*');}
|
||||||
td.first.cutLeft(1).trim();
|
|
||||||
fc.insert(start + 1, '*');
|
|
||||||
}
|
|
||||||
td.second = fc.trim();
|
td.second = fc.trim();
|
||||||
} else {
|
} else {
|
||||||
td.first = fc.takeMid(fc.findLast(' ')).trim();
|
td.first = fc.takeMid(fc.findLast(' ')).trim();
|
||||||
@@ -818,11 +636,7 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
|
|||||||
PIString ctemp, crepl;
|
PIString ctemp, crepl;
|
||||||
while (ts >= 0) {
|
while (ts >= 0) {
|
||||||
ctemp = fc.mid(ts).takeRange('<', '>');
|
ctemp = fc.mid(ts).takeRange('<', '>');
|
||||||
if (ctemp.isEmpty()) {
|
if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find('<', te); continue;}
|
||||||
te = ts + 1;
|
|
||||||
ts = fc.find('<', te);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
crepl = s_T + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, '0');
|
crepl = s_T + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, '0');
|
||||||
fc.replace(ts, ctemp.size_s() + 2, crepl);
|
fc.replace(ts, ctemp.size_s() + 2, crepl);
|
||||||
tmp_temp[crepl] = '<' + ctemp + '>';
|
tmp_temp[crepl] = '<' + ctemp + '>';
|
||||||
@@ -868,7 +682,8 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
//piCout << me.arguments_full;
|
//piCout << me.arguments_full;
|
||||||
piForeach (PIString & a, me.arguments_full)
|
piForeach (PIString & a, me.arguments_full)
|
||||||
if ((i = a.find('=')) > 0) a.cutRight(a.size_s() - i).trim();
|
if ((i = a.find('=')) > 0)
|
||||||
|
a.cutRight(a.size_s() - i).trim();
|
||||||
for (int j = 0; j < me.arguments_full.size_s(); ++j)
|
for (int j = 0; j < me.arguments_full.size_s(); ++j)
|
||||||
if (me.arguments_full[j] == s_void) {
|
if (me.arguments_full[j] == s_void) {
|
||||||
me.arguments_full.remove(j);
|
me.arguments_full.remove(j);
|
||||||
@@ -877,7 +692,8 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
|
|||||||
me.arguments_type = me.arguments_full;
|
me.arguments_type = me.arguments_full;
|
||||||
piForeach (PIString & a, me.arguments_type) {
|
piForeach (PIString & a, me.arguments_type) {
|
||||||
crepl.clear();
|
crepl.clear();
|
||||||
if (a.contains('[')) crepl = a.takeMid(a.find('['), a.findLast(']') - a.find('[') + 1);
|
if (a.contains('['))
|
||||||
|
crepl = a.takeMid(a.find('['), a.findLast(']') - a.find('[') + 1);
|
||||||
for (ts = a.size_s() - 1; ts >= 0; --ts)
|
for (ts = a.size_s() - 1; ts >= 0; --ts)
|
||||||
if (!_isCChar(a[ts]) && !(a[ts].isDigit())) break;
|
if (!_isCChar(a[ts]) && !(a[ts].isDigit())) break;
|
||||||
a.cutRight(a.size_s() - ts - 1);
|
a.cutRight(a.size_s() - ts - 1);
|
||||||
@@ -907,11 +723,8 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
|
|||||||
ctemp.trim();
|
ctemp.trim();
|
||||||
}
|
}
|
||||||
for (ts = ctemp.size_s() - 1; ts > 0; --ts) {
|
for (ts = ctemp.size_s() - 1; ts > 0; --ts) {
|
||||||
if (vn) {
|
if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;}
|
||||||
if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;
|
else {if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;}
|
||||||
} else {
|
|
||||||
if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
me.type = ctemp.takeLeft(ts + 1);
|
me.type = ctemp.takeLeft(ts + 1);
|
||||||
me.visibility = cur_def_vis;
|
me.visibility = cur_def_vis;
|
||||||
@@ -949,13 +762,13 @@ bool PICodeParser::parseMember(Entity * parent, PIString & fc) {
|
|||||||
me.type = type;
|
me.type = type;
|
||||||
restoreTmpMeta(&me);
|
restoreTmpMeta(&me);
|
||||||
if (me.name.isEmpty()) continue;
|
if (me.name.isEmpty()) continue;
|
||||||
if (me.name.contains('[')) crepl = me.name.takeMid(me.name.find('['), me.name.findLast(']') - me.name.find('[') + 1);
|
if (me.name.contains('['))
|
||||||
|
crepl = me.name.takeMid(me.name.find('['), me.name.findLast(']') - me.name.find('[') + 1);
|
||||||
while (!me.name.isEmpty()) {
|
while (!me.name.isEmpty()) {
|
||||||
if (me.name.front() == PIChar('*') || me.name.front() == PIChar('&')) {
|
if (me.name.front() == PIChar('*') || me.name.front() == PIChar('&')) {
|
||||||
me.type += me.name.takeLeft(1);
|
me.type += me.name.takeLeft(1);
|
||||||
me.name.trim();
|
me.name.trim();
|
||||||
} else
|
} else break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
me.is_type_ptr = (me.type.right(1) == PIChar(']') || me.type.right(1) == PIChar('*'));
|
me.is_type_ptr = (me.type.right(1) == PIChar(']') || me.type.right(1) == PIChar('*'));
|
||||||
me.type += crepl;
|
me.type += crepl;
|
||||||
@@ -1002,22 +815,10 @@ void PICodeParser::normalizeEntityNamespace(PIString & n) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n.push_front(' ');
|
n.push_front(' ');
|
||||||
if (n.find(s_s_const_s) >= 0) {
|
if (n.find(s_s_const_s) >= 0) {n.replaceAll(s_s_const_s, ""); pref += s_const_s;}
|
||||||
n.replaceAll(s_s_const_s, "");
|
if (n.find(s_s_static_s) >= 0) {n.replaceAll(s_s_static_s, ""); pref += s_static_s;}
|
||||||
pref += s_const_s;
|
if (n.find(s_s_mutable_s) >= 0) {n.replaceAll(s_s_mutable_s, ""); pref += s_mutable_s;}
|
||||||
}
|
if (n.find(s_s_volatile_s) >= 0) {n.replaceAll(s_s_volatile_s, ""); pref += s_volatile_s;}
|
||||||
if (n.find(s_s_static_s) >= 0) {
|
|
||||||
n.replaceAll(s_s_static_s, "");
|
|
||||||
pref += s_static_s;
|
|
||||||
}
|
|
||||||
if (n.find(s_s_mutable_s) >= 0) {
|
|
||||||
n.replaceAll(s_s_mutable_s, "");
|
|
||||||
pref += s_mutable_s;
|
|
||||||
}
|
|
||||||
if (n.find(s_s_volatile_s) >= 0) {
|
|
||||||
n.replaceAll(s_s_volatile_s, "");
|
|
||||||
pref += s_volatile_s;
|
|
||||||
}
|
|
||||||
n.trim();
|
n.trim();
|
||||||
int f = 0;
|
int f = 0;
|
||||||
piForeachC (Entity * e, entities) {
|
piForeachC (Entity * e, entities) {
|
||||||
@@ -1117,25 +918,10 @@ double PICodeParser::procMacrosCond(PIString fc) {
|
|||||||
while (!fc.isEmpty()) {
|
while (!fc.isEmpty()) {
|
||||||
cc = fc[0].toAscii();
|
cc = fc[0].toAscii();
|
||||||
nc = (fc.size() > 1 ? fc[1].toAscii() : 0);
|
nc = (fc.size() > 1 ? fc[1].toAscii() : 0);
|
||||||
if (cc == '!') {
|
if (cc == '!') {neg = true; fc.pop_front(); continue;}
|
||||||
neg = true;
|
if (cc == '(') {br = true; brv = procMacrosCond(fc.takeRange('(', ')'));}
|
||||||
fc.pop_front();
|
if (cc == '&' && nc == '&') {fc.remove(0, 2); oper = 1; continue;}
|
||||||
continue;
|
if (cc == '|' && nc == '|') {fc.remove(0, 2); oper = 2; continue;}
|
||||||
}
|
|
||||||
if (cc == '(') {
|
|
||||||
br = true;
|
|
||||||
brv = procMacrosCond(fc.takeRange('(', ')'));
|
|
||||||
}
|
|
||||||
if (cc == '&' && nc == '&') {
|
|
||||||
fc.remove(0, 2);
|
|
||||||
oper = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cc == '|' && nc == '|') {
|
|
||||||
fc.remove(0, 2);
|
|
||||||
oper = 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!br) {
|
if (!br) {
|
||||||
ce = fc.takeCWord();
|
ce = fc.takeCWord();
|
||||||
if (ce.isEmpty()) ce = fc.takeNumber();
|
if (ce.isEmpty()) ce = fc.takeNumber();
|
||||||
@@ -1163,7 +949,8 @@ double PICodeParser::procMacrosCond(PIString fc) {
|
|||||||
|
|
||||||
bool PICodeParser::isDefineExists(const PIString & dn) {
|
bool PICodeParser::isDefineExists(const PIString & dn) {
|
||||||
piForeachC (Define & d, defines) {
|
piForeachC (Define & d, defines) {
|
||||||
if (d.first == dn) return true;
|
if (d.first == dn)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1171,7 +958,8 @@ bool PICodeParser::isDefineExists(const PIString & dn) {
|
|||||||
|
|
||||||
double PICodeParser::defineValue(const PIString & dn) {
|
double PICodeParser::defineValue(const PIString & dn) {
|
||||||
piForeachC (Define & d, defines) {
|
piForeachC (Define & d, defines) {
|
||||||
if (d.first == dn) return d.second.isEmpty() ? 1. : d.second.toDouble();
|
if (d.first == dn)
|
||||||
|
return d.second.isEmpty() ? 1. : d.second.toDouble();
|
||||||
}
|
}
|
||||||
return dn.toDouble();
|
return dn.toDouble();
|
||||||
}
|
}
|
||||||
@@ -1199,7 +987,8 @@ void PICodeParser::replaceMeta(PIString & dn) {
|
|||||||
|
|
||||||
PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
|
PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
|
||||||
piForeach (Entity * e, entities)
|
piForeach (Entity * e, entities)
|
||||||
if (e->name == en) return e;
|
if (e->name == en)
|
||||||
|
return e;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1207,14 +996,8 @@ PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
|
|||||||
bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) {
|
bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) {
|
||||||
int dind = fc.find('{', start), find = fc.find(';', start);
|
int dind = fc.find('{', start), find = fc.find(';', start);
|
||||||
//piCout << "isDeclaration" << dind << find << fc.left(10);
|
//piCout << "isDeclaration" << dind << find << fc.left(10);
|
||||||
if (dind < 0 && find < 0) {
|
if (dind < 0 && find < 0) {if (end) *end = -1; return true;}
|
||||||
if (end) *end = -1;
|
if (dind < 0 || find < dind) {if (end) *end = find; return true;}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (dind < 0 || find < dind) {
|
|
||||||
if (end) *end = find;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (end) *end = dind;
|
if (end) *end = dind;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1264,11 +1047,10 @@ PIString PICodeParser::procMacros(PIString fc) {
|
|||||||
if (skip || grab) {
|
if (skip || grab) {
|
||||||
if (mif.left(2) == s_if) ifcnt++;
|
if (mif.left(2) == s_if) ifcnt++;
|
||||||
if (mif.left(5) == s_endif) {
|
if (mif.left(5) == s_endif) {
|
||||||
if (ifcnt > 0)
|
if (ifcnt > 0) ifcnt--;
|
||||||
ifcnt--;
|
|
||||||
else {
|
else {
|
||||||
//piCout << "main endif" << skip << grab;
|
//piCout << "main endif" << skip << grab;
|
||||||
if (grab) pfc += procMacros(nfc);
|
if (grab) pfc << procMacros(nfc);
|
||||||
skip = grab = false;
|
skip = grab = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1277,9 +1059,8 @@ PIString PICodeParser::procMacros(PIString fc) {
|
|||||||
//piCout << "main elif" << skip << grab << cond_ok;
|
//piCout << "main elif" << skip << grab << cond_ok;
|
||||||
if (cond_ok) {
|
if (cond_ok) {
|
||||||
if (grab) {
|
if (grab) {
|
||||||
pfc += procMacros(nfc);
|
pfc << procMacros(nfc);
|
||||||
skip = true;
|
skip = true; grab = false;
|
||||||
grab = false;
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1287,34 +1068,26 @@ PIString PICodeParser::procMacros(PIString fc) {
|
|||||||
//piCout << "check elif" << skip << grab << cond_ok;
|
//piCout << "check elif" << skip << grab << cond_ok;
|
||||||
if (!macroCondition(mif, mifcond.trimmed())) continue;
|
if (!macroCondition(mif, mifcond.trimmed())) continue;
|
||||||
//piCout << "check elif ok";
|
//piCout << "check elif ok";
|
||||||
skip = false;
|
skip = false; grab = cond_ok = true;
|
||||||
grab = cond_ok = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mif.left(4) == s_else && ifcnt == 0) {
|
if (mif.left(4) == s_else && ifcnt == 0) {
|
||||||
//piCout << "main else" << skip << grab;
|
//piCout << "main else" << skip << grab;
|
||||||
if (grab) pfc += procMacros(nfc);
|
if (grab) pfc << procMacros(nfc);
|
||||||
if (skip && !cond_ok) {
|
if (skip && !cond_ok) {skip = false; grab = true;}
|
||||||
skip = false;
|
else {skip = true; grab = false;}
|
||||||
grab = true;
|
|
||||||
} else {
|
|
||||||
skip = true;
|
|
||||||
grab = false;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (grab) nfc += line + '\n';
|
if (grab) nfc << line << '\n';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mif.left(2) == s_if) {
|
if (mif.left(2) == s_if) {
|
||||||
//piCout << "main if";
|
//piCout << "main if";
|
||||||
skip = grab = cond_ok = false;
|
skip = grab = cond_ok = false;
|
||||||
if (macroCondition(mif, mifcond.trimmed()))
|
if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true;
|
||||||
grab = cond_ok = true;
|
else skip = true;
|
||||||
else
|
|
||||||
skip = true;
|
|
||||||
ifcnt = 0;
|
ifcnt = 0;
|
||||||
nfc.clear();
|
nfc.clear();
|
||||||
} else {
|
} else {
|
||||||
@@ -1322,10 +1095,8 @@ PIString PICodeParser::procMacros(PIString fc) {
|
|||||||
//return false; /// WARNING: now skip errors
|
//return false; /// WARNING: now skip errors
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (grab)
|
if (grab) nfc << line << '\n';
|
||||||
nfc += line + '\n';
|
else if (!skip) pfc << line << '\n';
|
||||||
else if (!skip)
|
|
||||||
pfc += line + '\n';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pfc;
|
return pfc;
|
||||||
@@ -1376,10 +1147,7 @@ bool PICodeParser::parseDirective(PIString d) {
|
|||||||
if (dname == s_undef) {
|
if (dname == s_undef) {
|
||||||
PIString mname = d.takeCWord();
|
PIString mname = d.takeCWord();
|
||||||
for (int i = 0; i < defines.size_s(); ++i)
|
for (int i = 0; i < defines.size_s(); ++i)
|
||||||
if (defines[i].first == mname) {
|
if (defines[i].first == mname) {defines.remove(i); --i;}
|
||||||
defines.remove(i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -26,27 +26,17 @@
|
|||||||
#ifndef PICODEPARSER_H
|
#ifndef PICODEPARSER_H
|
||||||
#define PICODEPARSER_H
|
#define PICODEPARSER_H
|
||||||
|
|
||||||
#include "pievaluator.h"
|
|
||||||
#include "pifile.h"
|
#include "pifile.h"
|
||||||
|
#include "pievaluator.h"
|
||||||
|
|
||||||
inline bool _isCChar(const PIChar & c) {
|
inline bool _isCChar(const PIChar & c) {return (c.isAlpha() || (c.toAscii() == '_'));}
|
||||||
return (c.isAlpha() || (c.toAscii() == '_'));
|
inline bool _isCChar(const PIString & c) {if (c.isEmpty()) return false; return _isCChar(c[0]);}
|
||||||
}
|
|
||||||
inline bool _isCChar(const PIString & c) {
|
|
||||||
if (c.isEmpty()) return false;
|
|
||||||
return _isCChar(c[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
class PIP_EXPORT PICodeParser {
|
class PIP_EXPORT PICodeParser {
|
||||||
public:
|
public:
|
||||||
PICodeParser();
|
PICodeParser();
|
||||||
|
|
||||||
enum Visibility {
|
enum Visibility {Global, Public, Protected, Private};
|
||||||
Global,
|
|
||||||
Public,
|
|
||||||
Protected,
|
|
||||||
Private
|
|
||||||
};
|
|
||||||
enum Attribute {
|
enum Attribute {
|
||||||
NoAttributes = 0x0,
|
NoAttributes = 0x0,
|
||||||
Const = 0x01,
|
Const = 0x01,
|
||||||
@@ -120,18 +110,16 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PIP_EXPORT EnumeratorInfo {
|
struct PIP_EXPORT EnumeratorInfo {
|
||||||
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {
|
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {name = n; value = v; meta = m;}
|
||||||
name = n;
|
|
||||||
value = v;
|
|
||||||
meta = m;
|
|
||||||
}
|
|
||||||
MetaMap meta;
|
MetaMap meta;
|
||||||
PIString name;
|
PIString name;
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PIP_EXPORT Enum {
|
struct PIP_EXPORT Enum {
|
||||||
Enum(const PIString & n = PIString()) { name = n; }
|
Enum(const PIString & n = PIString()) {
|
||||||
|
name = n;
|
||||||
|
}
|
||||||
MetaMap meta;
|
MetaMap meta;
|
||||||
PIString name;
|
PIString name;
|
||||||
PIVector<EnumeratorInfo> members;
|
PIVector<EnumeratorInfo> members;
|
||||||
@@ -139,7 +127,6 @@ public:
|
|||||||
|
|
||||||
void parseFile(const PIString & file, bool follow_includes = true);
|
void parseFile(const PIString & file, bool follow_includes = true);
|
||||||
void parseFiles(const PIStringList & files, bool follow_includes = true);
|
void parseFiles(const PIStringList & files, bool follow_includes = true);
|
||||||
void parseFileContent(PIString fc);
|
|
||||||
|
|
||||||
void includeDirectory(const PIString & dir) {includes << dir;}
|
void includeDirectory(const PIString & dir) {includes << dir;}
|
||||||
void addDefine(const PIString & def_name, const PIString & def_value) {custom_defines << Define(def_name, def_value);}
|
void addDefine(const PIString & def_name, const PIString & def_value) {custom_defines << Define(def_name, def_value);}
|
||||||
@@ -194,6 +181,7 @@ private:
|
|||||||
PIString cur_namespace;
|
PIString cur_namespace;
|
||||||
PIMap<PIString, PIString> tmp_temp;
|
PIMap<PIString, PIString> tmp_temp;
|
||||||
PIMap<PIString, MetaMap> tmp_meta;
|
PIMap<PIString, MetaMap> tmp_meta;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PICODEPARSER_H
|
#endif // PICODEPARSER_H
|
||||||
|
|||||||
@@ -58,8 +58,8 @@
|
|||||||
#ifndef PICOMPRESS_H
|
#ifndef PICOMPRESS_H
|
||||||
#define PICOMPRESS_H
|
#define PICOMPRESS_H
|
||||||
|
|
||||||
#include "pibytearray.h"
|
|
||||||
#include "pip_compress_export.h"
|
#include "pip_compress_export.h"
|
||||||
|
#include "pibytearray.h"
|
||||||
|
|
||||||
//! \~english Compress "ba" with compression level "level", return empty %PIByteArray if no compression supports
|
//! \~english Compress "ba" with compression level "level", return empty %PIByteArray if no compression supports
|
||||||
//! \~russian Сжимает "ba" с уровнем сжатия "level", возвращает пустой %PIByteArray если нет поддержки
|
//! \~russian Сжимает "ba" с уровнем сжатия "level", возвращает пустой %PIByteArray если нет поддержки
|
||||||
|
|||||||
@@ -16,15 +16,13 @@
|
|||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "pikbdlistener.h"
|
|
||||||
|
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#include "piliterals.h"
|
#include "pikbdlistener.h"
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
# include <termios.h>
|
# include <termios.h>
|
||||||
#else
|
#else
|
||||||
# include <wincon.h>
|
|
||||||
# include <wingdi.h>
|
# include <wingdi.h>
|
||||||
|
# include <wincon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** \class PIKbdListener
|
/** \class PIKbdListener
|
||||||
@@ -121,10 +119,8 @@ const PIKbdListener::EscSeq PIKbdListener::esc_seq[] = {
|
|||||||
{0, 0, 0, 0, 0},
|
{0, 0, 0, 0, 0},
|
||||||
};
|
};
|
||||||
void setupTerminal(bool on) {
|
void setupTerminal(bool on) {
|
||||||
printf("\e[?1000");
|
printf("\e[?1000"); printf(on ? "h" : "l");
|
||||||
printf(on ? "h" : "l");
|
printf("\e[?1002"); printf(on ? "h" : "l");
|
||||||
printf("\e[?1002");
|
|
||||||
printf(on ? "h" : "l");
|
|
||||||
fflush(0);
|
fflush(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -148,7 +144,7 @@ PRIVATE_DEFINITION_END(PIKbdListener)
|
|||||||
|
|
||||||
|
|
||||||
PIKbdListener::PIKbdListener(KBFunc slot, void * _d, bool startNow): PIThread() {
|
PIKbdListener::PIKbdListener(KBFunc slot, void * _d, bool startNow): PIThread() {
|
||||||
setName("keyboard_listener"_a);
|
setName("keyboard_listener");
|
||||||
_object = this;
|
_object = this;
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
PRIVATE->hIn = GetStdHandle(STD_INPUT_HANDLE);
|
PRIVATE->hIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
@@ -228,111 +224,33 @@ void PIKbdListener::readKeyboard() {
|
|||||||
ke.modifiers = getModifiers(ker.dwControlKeyState, &shift);
|
ke.modifiers = getModifiers(ker.dwControlKeyState, &shift);
|
||||||
//piCout << "key" << int(ker.wVirtualKeyCode) << int(ker.uChar.AsciiChar);
|
//piCout << "key" << int(ker.wVirtualKeyCode) << int(ker.uChar.AsciiChar);
|
||||||
switch (ker.wVirtualKeyCode) {
|
switch (ker.wVirtualKeyCode) {
|
||||||
case 8:
|
case 8: PRIVATE->ret = 1; ke.key = Backspace; break;
|
||||||
PRIVATE->ret = 1;
|
case 33: PRIVATE->ret = 1; ke.key = PageUp; break;
|
||||||
ke.key = Backspace;
|
case 34: PRIVATE->ret = 1; ke.key = PageDown; break;
|
||||||
break;
|
case 35: PRIVATE->ret = 1; ke.key = End; break;
|
||||||
case 33:
|
case 36: PRIVATE->ret = 1; ke.key = Home; break;
|
||||||
PRIVATE->ret = 1;
|
case 37: PRIVATE->ret = 1; ke.key = LeftArrow; break;
|
||||||
ke.key = PageUp;
|
case 38: PRIVATE->ret = 1; ke.key = UpArrow; break;
|
||||||
break;
|
case 39: PRIVATE->ret = 1; ke.key = RightArrow; break;
|
||||||
case 34:
|
case 40: PRIVATE->ret = 1; ke.key = DownArrow; break;
|
||||||
PRIVATE->ret = 1;
|
case 45: PRIVATE->ret = 1; ke.key = Insert; break;
|
||||||
ke.key = PageDown;
|
case 46: PRIVATE->ret = 1; ke.key = Delete; break;
|
||||||
break;
|
|
||||||
case 35:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = End;
|
|
||||||
break;
|
|
||||||
case 36:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = Home;
|
|
||||||
break;
|
|
||||||
case 37:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = LeftArrow;
|
|
||||||
break;
|
|
||||||
case 38:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = UpArrow;
|
|
||||||
break;
|
|
||||||
case 39:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = RightArrow;
|
|
||||||
break;
|
|
||||||
case 40:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = DownArrow;
|
|
||||||
break;
|
|
||||||
case 45:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = Insert;
|
|
||||||
break;
|
|
||||||
case 46:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = Delete;
|
|
||||||
break;
|
|
||||||
case '\r':
|
case '\r':
|
||||||
case '\n':
|
case '\n': PRIVATE->ret = 1; ke.key = Return; break;
|
||||||
PRIVATE->ret = 1;
|
case ' ': PRIVATE->ret = 1; ke.key = Space; break;
|
||||||
ke.key = Return;
|
case '\t': PRIVATE->ret = 1; ke.key = Tab; break;
|
||||||
break;
|
case 112: PRIVATE->ret = 1; ke.key = F1; break;
|
||||||
case ' ':
|
case 113: PRIVATE->ret = 1; ke.key = F2; break;
|
||||||
PRIVATE->ret = 1;
|
case 114: PRIVATE->ret = 1; ke.key = F3; break;
|
||||||
ke.key = Space;
|
case 115: PRIVATE->ret = 1; ke.key = F4; break;
|
||||||
break;
|
case 116: PRIVATE->ret = 1; ke.key = F5; break;
|
||||||
case '\t':
|
case 117: PRIVATE->ret = 1; ke.key = F6; break;
|
||||||
PRIVATE->ret = 1;
|
case 118: PRIVATE->ret = 1; ke.key = F7; break;
|
||||||
ke.key = Tab;
|
case 119: PRIVATE->ret = 1; ke.key = F8; break;
|
||||||
break;
|
case 120: PRIVATE->ret = 1; ke.key = F9; break;
|
||||||
case 112:
|
case 121: PRIVATE->ret = 1; ke.key = F10; break;
|
||||||
PRIVATE->ret = 1;
|
case 122: PRIVATE->ret = 1; ke.key = F11; break;
|
||||||
ke.key = F1;
|
case 123: PRIVATE->ret = 1; ke.key = F12; break;
|
||||||
break;
|
|
||||||
case 113:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F2;
|
|
||||||
break;
|
|
||||||
case 114:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F3;
|
|
||||||
break;
|
|
||||||
case 115:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F4;
|
|
||||||
break;
|
|
||||||
case 116:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F5;
|
|
||||||
break;
|
|
||||||
case 117:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F6;
|
|
||||||
break;
|
|
||||||
case 118:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F7;
|
|
||||||
break;
|
|
||||||
case 119:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F8;
|
|
||||||
break;
|
|
||||||
case 120:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F9;
|
|
||||||
break;
|
|
||||||
case 121:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F10;
|
|
||||||
break;
|
|
||||||
case 122:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F11;
|
|
||||||
break;
|
|
||||||
case 123:
|
|
||||||
PRIVATE->ret = 1;
|
|
||||||
ke.key = F12;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
PRIVATE->ret = 1;
|
PRIVATE->ret = 1;
|
||||||
rc[0] = 1;
|
rc[0] = 1;
|
||||||
@@ -343,15 +261,10 @@ void PIKbdListener::readKeyboard() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ke.key == 0) {
|
if (ke.key == 0) {piMSleep(10); return;}
|
||||||
piMSleep(10);
|
} else {piMSleep(10); return;}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
piMSleep(10);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case MOUSE_EVENT: {
|
case MOUSE_EVENT: {
|
||||||
MOUSE_EVENT_RECORD mer = ir.Event.MouseEvent;
|
MOUSE_EVENT_RECORD mer = ir.Event.MouseEvent;
|
||||||
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
GetConsoleScreenBufferInfo(PRIVATE->hOut, &PRIVATE->sbi);
|
||||||
@@ -384,23 +297,24 @@ void PIKbdListener::readKeyboard() {
|
|||||||
prev_p_me = me;
|
prev_p_me = me;
|
||||||
}
|
}
|
||||||
tm_dbl.reset();
|
tm_dbl.reset();
|
||||||
} else if (mb < me.buttons)
|
|
||||||
me.action = MouseButtonRelease;
|
|
||||||
else {
|
|
||||||
if (mb != 0) piCoutObj << "WTF";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if (mb < me.buttons) me.action = MouseButtonRelease;
|
||||||
|
else {if (mb != 0) piCoutObj << "WTF"; break;}
|
||||||
}
|
}
|
||||||
me.buttons = mb;
|
me.buttons = mb;
|
||||||
if (piCompareBinary(&prev_me, &me, sizeof(me))) break;
|
if (piCompareBinary(&prev_me, &me, sizeof(me)))
|
||||||
|
break;
|
||||||
memcpy((void*)(&prev_me), (const void*)(&me), sizeof(me));
|
memcpy((void*)(&prev_me), (const void*)(&me), sizeof(me));
|
||||||
//PIString _s[] = {"press", "release", "dbl click", "move"};
|
//PIString _s[] = {"press", "release", "dbl click", "move"};
|
||||||
//piCoutObj << _s[me.action] << me.buttons << ":" << me.x << me.y;
|
//piCoutObj << _s[me.action] << me.buttons << ":" << me.x << me.y;
|
||||||
mouseEvent(me, kbddata_);
|
mouseEvent(me, kbddata_);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
default: piMSleep(10); return;
|
break;
|
||||||
|
default:
|
||||||
|
piMSleep(10);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
tcsetattr(0, TCSANOW, &PRIVATE->tterm);
|
tcsetattr(0, TCSANOW, &PRIVATE->tterm);
|
||||||
@@ -413,14 +327,8 @@ void PIKbdListener::readKeyboard() {
|
|||||||
for (int i = 0; i < PRIVATE->ret; ++i)
|
for (int i = 0; i < PRIVATE->ret; ++i)
|
||||||
std::cout << "'" << (char)(rc[i]) << "' " << (int)(uchar)(rc[i]);
|
std::cout << "'" << (char)(rc[i]) << "' " << (int)(uchar)(rc[i]);
|
||||||
std::cout << std::endl;*/
|
std::cout << std::endl;*/
|
||||||
if (rc[0] == 0) {
|
if (rc[0] == 0) {piMSleep(10); return;}
|
||||||
piMSleep(10);
|
if (PRIVATE->ret < 0 || PRIVATE->ret > 7) {piMSleep(10); return;}
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (PRIVATE->ret < 0 || PRIVATE->ret > 7) {
|
|
||||||
piMSleep(10);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (PRIVATE->ret == 1) {
|
if (PRIVATE->ret == 1) {
|
||||||
if (rc[0] == 8)
|
if (rc[0] == 8)
|
||||||
ke.key = Backspace;
|
ke.key = Backspace;
|
||||||
@@ -439,8 +347,7 @@ void PIKbdListener::readKeyboard() {
|
|||||||
ke.key = PIChar::fromConsole(rc[1]).unicode16Code();
|
ke.key = PIChar::fromConsole(rc[1]).unicode16Code();
|
||||||
} else {// escape-seq
|
} else {// escape-seq
|
||||||
if (rc[1] == '\e') { // search for Alt
|
if (rc[1] == '\e') { // search for Alt
|
||||||
for (int i = 1; i < 7; ++i)
|
for (int i = 1; i < 7; ++i) rc[i] = rc[i + 1];
|
||||||
rc[i] = rc[i + 1];
|
|
||||||
mod = 2;
|
mod = 2;
|
||||||
PRIVATE->ret--;
|
PRIVATE->ret--;
|
||||||
}
|
}
|
||||||
@@ -489,8 +396,7 @@ void PIKbdListener::readKeyboard() {
|
|||||||
for (int i = 2; i < 7; ++i) // search for modifier
|
for (int i = 2; i < 7; ++i) // search for modifier
|
||||||
if (rc[i] == ';') {
|
if (rc[i] == ';') {
|
||||||
mod |= rc[i + 1] - '0' - 1;
|
mod |= rc[i + 1] - '0' - 1;
|
||||||
for (int j = i; j < 6; ++j)
|
for (int j = i; j < 6; ++j) rc[j] = rc[j + 2];
|
||||||
rc[j] = rc[j + 2];
|
|
||||||
rc[6] = rc[7] = 0;
|
rc[6] = rc[7] = 0;
|
||||||
PRIVATE->ret -= 2;
|
PRIVATE->ret -= 2;
|
||||||
break;
|
break;
|
||||||
@@ -500,8 +406,7 @@ void PIKbdListener::readKeyboard() {
|
|||||||
if (PRIVATE->ret >= 3 && rc[1] == 'O') { // search for modifier (F1-F4)
|
if (PRIVATE->ret >= 3 && rc[1] == 'O') { // search for modifier (F1-F4)
|
||||||
if (rc[2] >= '1' && rc[2] <= '8') {
|
if (rc[2] >= '1' && rc[2] <= '8') {
|
||||||
mod |= rc[2] - '0' - 1;
|
mod |= rc[2] - '0' - 1;
|
||||||
for (int j = 2; j < 6; ++j)
|
for (int j = 2; j < 6; ++j) rc[j] = rc[j + 1];
|
||||||
rc[j] = rc[j + 1];
|
|
||||||
rc[7] = 0;
|
rc[7] = 0;
|
||||||
PRIVATE->ret--;
|
PRIVATE->ret--;
|
||||||
}
|
}
|
||||||
@@ -527,9 +432,11 @@ void PIKbdListener::readKeyboard() {
|
|||||||
cout << "'" << (char)(rc[i]) << "' ";
|
cout << "'" << (char)(rc[i]) << "' ";
|
||||||
cout << endl;*/
|
cout << endl;*/
|
||||||
}
|
}
|
||||||
if (ke.key == 0 && PRIVATE->ret > 1) ke.key = PIChar::fromSystem(rc).unicode16Code();
|
if (ke.key == 0 && PRIVATE->ret > 1)
|
||||||
|
ke.key = PIChar(rc).unicode16Code();
|
||||||
#endif
|
#endif
|
||||||
if ((rc[0] == '\n' || rc[0] == '\r') && PRIVATE->ret == 1) ke.key = Return;
|
if ((rc[0] == '\n' || rc[0] == '\r') && PRIVATE->ret == 1)
|
||||||
|
ke.key = Return;
|
||||||
if (exit_enabled && ke.key == exit_key) {
|
if (exit_enabled && ke.key == exit_key) {
|
||||||
PIKbdListener::exiting = true;
|
PIKbdListener::exiting = true;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -27,19 +27,17 @@
|
|||||||
#define PIKBDLISTENER_H
|
#define PIKBDLISTENER_H
|
||||||
|
|
||||||
#include "pithread.h"
|
#include "pithread.h"
|
||||||
#include "pitime.h"
|
|
||||||
|
|
||||||
#define WAIT_FOR_EXIT \
|
#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) piMSleep(PIP_MIN_MSLEEP*5); // TODO: rewrite with condvar
|
||||||
while (!PIKbdListener::exiting) \
|
|
||||||
piMSleep(PIP_MIN_MSLEEP * 5); // TODO: rewrite with condvar
|
|
||||||
|
|
||||||
|
|
||||||
class PIP_EXPORT PIKbdListener: public PIThread {
|
class PIP_EXPORT PIKbdListener: public PIThread
|
||||||
PIOBJECT_SUBCLASS(PIKbdListener, PIThread);
|
{
|
||||||
|
PIOBJECT_SUBCLASS(PIKbdListener, PIThread)
|
||||||
friend class PIConsole;
|
friend class PIConsole;
|
||||||
friend class PITerminal;
|
friend class PITerminal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Special keyboard keys
|
//! Special keyboard keys
|
||||||
enum SpecialKey {
|
enum SpecialKey {
|
||||||
Tab /** Tab key */ = 0x09,
|
Tab /** Tab key */ = 0x09,
|
||||||
@@ -83,10 +81,7 @@ public:
|
|||||||
|
|
||||||
//! This struct contains information about pressed keyboard key
|
//! This struct contains information about pressed keyboard key
|
||||||
struct PIP_EXPORT KeyEvent {
|
struct PIP_EXPORT KeyEvent {
|
||||||
KeyEvent(int k = 0, KeyModifiers m = 0) {
|
KeyEvent(int k = 0, KeyModifiers m = 0) {key = k; modifiers = m;}
|
||||||
key = k;
|
|
||||||
modifiers = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Pressed key. It can be simple \b char or special key (see PIKbdListener::SpecialKey)
|
//! Pressed key. It can be simple \b char or special key (see PIKbdListener::SpecialKey)
|
||||||
int key;
|
int key;
|
||||||
@@ -115,12 +110,7 @@ public:
|
|||||||
|
|
||||||
//! This struct contains information about mouse action
|
//! This struct contains information about mouse action
|
||||||
struct PIP_EXPORT MouseEvent {
|
struct PIP_EXPORT MouseEvent {
|
||||||
MouseEvent(MouseAction a = MouseButtonPress, MouseButtons b = 0, KeyModifiers m = 0) {
|
MouseEvent(MouseAction a = MouseButtonPress, MouseButtons b = 0, KeyModifiers m = 0) {x = y = 0; action = a; buttons = b; modifiers = m;}
|
||||||
x = y = 0;
|
|
||||||
action = a;
|
|
||||||
buttons = b;
|
|
||||||
modifiers = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Event X coordinate in view-space, from 0
|
//! Event X coordinate in view-space, from 0
|
||||||
int x;
|
int x;
|
||||||
@@ -164,9 +154,7 @@ public:
|
|||||||
void setSlot(KBFunc slot) {ret_func = slot;}
|
void setSlot(KBFunc slot) {ret_func = slot;}
|
||||||
|
|
||||||
//! Set external function to "slot"
|
//! Set external function to "slot"
|
||||||
void setSlot(std::function<void(KeyEvent)> slot) {
|
void setSlot(std::function<void(KeyEvent)> slot) {ret_func = [slot](KeyEvent e, void *){slot(e);};}
|
||||||
ret_func = [slot](KeyEvent e, void *) { slot(e); };
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns if exit key if awaiting
|
//! Returns if exit key if awaiting
|
||||||
bool exitCaptured() const {return exit_enabled;}
|
bool exitCaptured() const {return exit_enabled;}
|
||||||
@@ -183,17 +171,14 @@ public:
|
|||||||
bool isActive() {return is_active;}
|
bool isActive() {return is_active;}
|
||||||
|
|
||||||
EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');}
|
EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');}
|
||||||
EVENT_HANDLER1(void, enableExitCapture, int, key) {
|
EVENT_HANDLER1(void, enableExitCapture, int, key) {exit_enabled = true; exit_key = key;}
|
||||||
exit_enabled = true;
|
|
||||||
exit_key = key;
|
|
||||||
}
|
|
||||||
EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;}
|
EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;}
|
||||||
EVENT_HANDLER(void, setActive) {setActive(true);}
|
EVENT_HANDLER(void, setActive) {setActive(true);}
|
||||||
EVENT_HANDLER1(void, setActive, bool, yes);
|
EVENT_HANDLER1(void, setActive, bool, yes);
|
||||||
|
|
||||||
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
|
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
|
||||||
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void *, data);
|
EVENT2(mouseEvent, PIKbdListener::MouseEvent, mouse, void * , data)
|
||||||
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void *, data);
|
EVENT2(wheelEvent, PIKbdListener::WheelEvent, wheel, void * , data)
|
||||||
|
|
||||||
//! \handlers
|
//! \handlers
|
||||||
//! \{
|
//! \{
|
||||||
@@ -220,9 +205,9 @@ public:
|
|||||||
static PIKbdListener * instance() {return _object;}
|
static PIKbdListener * instance() {return _object;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void begin() override;
|
void begin();
|
||||||
void run() override { readKeyboard(); }
|
void run() {readKeyboard();}
|
||||||
void end() override;
|
void end();
|
||||||
|
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
struct PIP_EXPORT EscSeq {
|
struct PIP_EXPORT EscSeq {
|
||||||
@@ -258,42 +243,17 @@ private:
|
|||||||
MouseEvent me, prev_me, prev_p_me;
|
MouseEvent me, prev_me, prev_p_me;
|
||||||
WheelEvent we;
|
WheelEvent we;
|
||||||
static PIKbdListener * _object;
|
static PIKbdListener * _object;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::KeyEvent & v) {s << v.key << v.modifiers; return s;}
|
||||||
//! \~english Store operator
|
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::MouseEvent & v) {s << v.x << v.y << (int)v.action << v.buttons << v.modifiers; return s;}
|
||||||
//! \~russian Оператор сохранения
|
inline PIByteArray & operator <<(PIByteArray & s, const PIKbdListener::WheelEvent & v) {s << (*(PIKbdListener::MouseEvent*)&v) << (uchar)v.direction; return s;}
|
||||||
BINARY_STREAM_WRITE(PIKbdListener::MouseEvent) {
|
|
||||||
s << v.x << v.y << v.action << v.buttons << v.modifiers;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
|
||||||
//! \~english Restore operator
|
|
||||||
//! \~russian Оператор извлечения
|
|
||||||
BINARY_STREAM_READ(PIKbdListener::MouseEvent) {
|
|
||||||
s >> v.x >> v.y >> v.action >> v.buttons >> v.modifiers;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
|
||||||
//! \~english Store operator
|
|
||||||
//! \~russian Оператор сохранения
|
|
||||||
BINARY_STREAM_WRITE(PIKbdListener::WheelEvent) {
|
|
||||||
s << (*(PIKbdListener::MouseEvent *)&v) << v.direction;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
|
||||||
//! \~english Restore operator
|
|
||||||
//! \~russian Оператор извлечения
|
|
||||||
BINARY_STREAM_READ(PIKbdListener::WheelEvent) {
|
|
||||||
s >> (*(PIKbdListener::MouseEvent *)&v) >> v.direction;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::KeyEvent & v) {s >> v.key >> v.modifiers; return s;}
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::MouseEvent & v) {int a(0); s >> v.x >> v.y >> a >> v.buttons >> v.modifiers; v.action = (PIKbdListener::MouseAction)a; return s;}
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIKbdListener::WheelEvent & v) {uchar d(0); s >> (*(PIKbdListener::MouseEvent*)&v) >> d; v.direction = d; return s;}
|
||||||
|
|
||||||
REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent)
|
REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent)
|
||||||
REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent)
|
REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent)
|
||||||
|
|||||||
@@ -27,17 +27,16 @@
|
|||||||
#define PISCREEN_H
|
#define PISCREEN_H
|
||||||
|
|
||||||
#include "pip_console_export.h"
|
#include "pip_console_export.h"
|
||||||
#include "piscreendrawer.h"
|
|
||||||
#include "piscreentile.h"
|
#include "piscreentile.h"
|
||||||
|
#include "piscreendrawer.h"
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT PIScreen
|
class PIP_CONSOLE_EXPORT PIScreen: public PIThread, public PIScreenTypes::PIScreenBase
|
||||||
: public PIThread
|
{
|
||||||
, public PIScreenTypes::PIScreenBase {
|
PIOBJECT_SUBCLASS(PIScreen, PIThread)
|
||||||
PIOBJECT_SUBCLASS(PIScreen, PIThread);
|
|
||||||
class SystemConsole;
|
class SystemConsole;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it
|
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it
|
||||||
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
|
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
|
||||||
|
|
||||||
@@ -73,15 +72,12 @@ public:
|
|||||||
|
|
||||||
EVENT_HANDLER0(void, waitForFinish);
|
EVENT_HANDLER0(void, waitForFinish);
|
||||||
EVENT_HANDLER0(void, start) {start(false);}
|
EVENT_HANDLER0(void, start) {start(false);}
|
||||||
EVENT_HANDLER1(void, start, bool, wait) {
|
EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
|
||||||
PIThread::start(40);
|
|
||||||
if (wait) waitForFinish();
|
|
||||||
}
|
|
||||||
EVENT_HANDLER0(void, stop) {stop(false);}
|
EVENT_HANDLER0(void, stop) {stop(false);}
|
||||||
EVENT_HANDLER1(void, stop, bool, clear);
|
EVENT_HANDLER1(void, stop, bool, clear);
|
||||||
|
|
||||||
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
|
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void * , data)
|
||||||
EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e);
|
EVENT2(tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e)
|
||||||
|
|
||||||
//! \handlers
|
//! \handlers
|
||||||
//! \{
|
//! \{
|
||||||
@@ -138,9 +134,9 @@ private:
|
|||||||
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
|
PIVector<PIVector<PIScreenTypes::Cell> > cells, pcells;
|
||||||
};
|
};
|
||||||
|
|
||||||
void begin() override;
|
void begin();
|
||||||
void run() override;
|
void run();
|
||||||
void end() override;
|
void end();
|
||||||
void key_event(PIKbdListener::KeyEvent key);
|
void key_event(PIKbdListener::KeyEvent key);
|
||||||
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
|
EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me);
|
||||||
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
|
EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we);
|
||||||
@@ -149,9 +145,9 @@ private:
|
|||||||
PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e);
|
PIVector<PIScreenTile*> prepareMouse(PIKbdListener::MouseEvent * e);
|
||||||
PIVector<PIScreenTile*> tilesUnderMouse(int x, int y);
|
PIVector<PIScreenTile*> tilesUnderMouse(int x, int y);
|
||||||
bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent());
|
bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent());
|
||||||
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e) override;
|
void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e);
|
||||||
void tileRemovedInternal(PIScreenTile * t) override;
|
void tileRemovedInternal(PIScreenTile * t);
|
||||||
void tileSetFocusInternal(PIScreenTile * t) override;
|
void tileSetFocusInternal(PIScreenTile * t);
|
||||||
|
|
||||||
bool mouse_;
|
bool mouse_;
|
||||||
SystemConsole console;
|
SystemConsole console;
|
||||||
@@ -160,6 +156,7 @@ private:
|
|||||||
PIKbdListener::KBFunc ret_func;
|
PIKbdListener::KBFunc ret_func;
|
||||||
PIScreenTile root;
|
PIScreenTile root;
|
||||||
PIScreenTile * tile_focus, * tile_dialog;
|
PIScreenTile * tile_focus, * tile_dialog;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,14 +35,9 @@
|
|||||||
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
|
||||||
public:
|
public:
|
||||||
TileVars(const PIString & n = PIString());
|
TileVars(const PIString & n = PIString());
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct PIP_CONSOLE_EXPORT Variable {
|
struct PIP_CONSOLE_EXPORT Variable {
|
||||||
Variable() {
|
Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = PIScreenTypes::CellFormat(); ptr = 0;}
|
||||||
nx = ny = type = offset = bitFrom = bitCount = size = 0;
|
|
||||||
format = PIScreenTypes::CellFormat();
|
|
||||||
ptr = 0;
|
|
||||||
}
|
|
||||||
bool isEmpty() const {return (ptr == 0);}
|
bool isEmpty() const {return (ptr == 0);}
|
||||||
PIString name;
|
PIString name;
|
||||||
PIScreenTypes::CellFormat format;
|
PIScreenTypes::CellFormat format;
|
||||||
@@ -69,12 +64,14 @@ protected:
|
|||||||
};
|
};
|
||||||
PIVector<Variable> variables;
|
PIVector<Variable> variables;
|
||||||
PIScreenTypes::Alignment alignment;
|
PIScreenTypes::Alignment alignment;
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT PIScreenConsoleTile: public PIScreenTile {
|
|
||||||
|
class PIP_CONSOLE_EXPORT PIScreenConsoleTile : public PIScreenTile
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
PIScreenConsoleTile();
|
PIScreenConsoleTile();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,10 +30,10 @@
|
|||||||
#include "piscreentypes.h"
|
#include "piscreentypes.h"
|
||||||
#include "pistring.h"
|
#include "pistring.h"
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT PIScreenDrawer {
|
class PIP_CONSOLE_EXPORT PIScreenDrawer
|
||||||
|
{
|
||||||
friend class PIScreen;
|
friend class PIScreen;
|
||||||
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c);
|
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell> > & c);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ArtChar {
|
enum ArtChar {
|
||||||
LineVertical = 1,
|
LineVertical = 1,
|
||||||
@@ -49,49 +49,12 @@ public:
|
|||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');}
|
void clearRect(int x0, int y0, int x1, int y1) {fillRect(x0, y0, x1, y1, ' ');}
|
||||||
void drawPixel(int x,
|
void drawPixel(int x, int y, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
|
||||||
int y,
|
void drawLine(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
|
||||||
const PIChar & c,
|
void drawRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
|
||||||
PIScreenTypes::Color col_char = PIScreenTypes::Default,
|
void drawFrame(int x0, int y0, int x1, int y1, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
|
||||||
PIScreenTypes::Color col_back = PIScreenTypes::Default,
|
void drawText(int x, int y, const PIString & s, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Transparent, PIScreenTypes::CharFlags flags_char = 0);
|
||||||
PIScreenTypes::CharFlags flags_char = 0);
|
void fillRect(int x0, int y0, int x1, int y1, const PIChar & c, PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::CharFlags flags_char = 0);
|
||||||
void drawLine(int x0,
|
|
||||||
int y0,
|
|
||||||
int x1,
|
|
||||||
int y1,
|
|
||||||
const PIChar & c,
|
|
||||||
PIScreenTypes::Color col_char = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::Color col_back = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::CharFlags flags_char = 0);
|
|
||||||
void drawRect(int x0,
|
|
||||||
int y0,
|
|
||||||
int x1,
|
|
||||||
int y1,
|
|
||||||
const PIChar & c,
|
|
||||||
PIScreenTypes::Color col_char = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::Color col_back = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::CharFlags flags_char = 0);
|
|
||||||
void drawFrame(int x0,
|
|
||||||
int y0,
|
|
||||||
int x1,
|
|
||||||
int y1,
|
|
||||||
PIScreenTypes::Color col_char = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::Color col_back = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::CharFlags flags_char = 0);
|
|
||||||
void drawText(int x,
|
|
||||||
int y,
|
|
||||||
const PIString & s,
|
|
||||||
PIScreenTypes::Color col_char = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::Color col_back = PIScreenTypes::Transparent,
|
|
||||||
PIScreenTypes::CharFlags flags_char = 0);
|
|
||||||
void fillRect(int x0,
|
|
||||||
int y0,
|
|
||||||
int x1,
|
|
||||||
int y1,
|
|
||||||
const PIChar & c,
|
|
||||||
PIScreenTypes::Color col_char = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::Color col_back = PIScreenTypes::Default,
|
|
||||||
PIScreenTypes::CharFlags flags_char = 0);
|
|
||||||
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell> > & content);
|
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell> > & content);
|
||||||
|
|
||||||
PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));}
|
PIChar artChar(const ArtChar type) const {return arts_.value(type, PIChar(' '));}
|
||||||
@@ -102,6 +65,7 @@ private:
|
|||||||
PIVector<PIVector<PIScreenTypes::Cell> > & cells;
|
PIVector<PIVector<PIScreenTypes::Cell> > & cells;
|
||||||
int width, height;
|
int width, height;
|
||||||
PIMap<ArtChar, PIChar> arts_;
|
PIMap<ArtChar, PIChar> arts_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,20 +26,17 @@
|
|||||||
#ifndef PISCREENTILE_H
|
#ifndef PISCREENTILE_H
|
||||||
#define PISCREENTILE_H
|
#define PISCREENTILE_H
|
||||||
|
|
||||||
#include "pikbdlistener.h"
|
|
||||||
#include "pip_console_export.h"
|
#include "pip_console_export.h"
|
||||||
#include "piscreentypes.h"
|
#include "piscreentypes.h"
|
||||||
|
#include "pikbdlistener.h"
|
||||||
|
|
||||||
class PIScreenDrawer;
|
class PIScreenDrawer;
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
|
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
|
||||||
friend class PIScreen;
|
friend class PIScreen;
|
||||||
PIOBJECT_SUBCLASS(PIScreenTile, PIObject);
|
PIOBJECT_SUBCLASS(PIScreenTile, PIObject)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PIScreenTile(const PIString & n = PIString(),
|
PIScreenTile(const PIString & n = PIString(), PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
|
||||||
PIScreenTypes::Direction d = PIScreenTypes::Vertical,
|
|
||||||
PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
|
|
||||||
virtual ~PIScreenTile();
|
virtual ~PIScreenTile();
|
||||||
|
|
||||||
void addTile(PIScreenTile * t);
|
void addTile(PIScreenTile * t);
|
||||||
@@ -53,12 +50,7 @@ public:
|
|||||||
void setFocus();
|
void setFocus();
|
||||||
bool hasFocus() const {return has_focus;}
|
bool hasFocus() const {return has_focus;}
|
||||||
void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;}
|
void setMargins(int m) {marginLeft = marginRight = marginTop = marginBottom = m;}
|
||||||
void setMargins(int l, int r, int t, int b) {
|
void setMargins(int l, int r, int t, int b) {marginLeft = l; marginRight = r; marginTop = t; marginBottom = b;}
|
||||||
marginLeft = l;
|
|
||||||
marginRight = r;
|
|
||||||
marginTop = t;
|
|
||||||
marginBottom = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int x() const {return x_;}
|
int x() const {return x_;}
|
||||||
int y() const {return y_;}
|
int y() const {return y_;}
|
||||||
@@ -77,6 +69,7 @@ public:
|
|||||||
bool visible;
|
bool visible;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
//! Returns desired tile size in "w" and "h"
|
//! Returns desired tile size in "w" and "h"
|
||||||
virtual void sizeHint(int & w, int & h) const;
|
virtual void sizeHint(int & w, int & h) const;
|
||||||
|
|
||||||
@@ -110,6 +103,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int pw, ph;
|
int pw, ph;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,7 @@
|
|||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
|
||||||
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile);
|
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
|
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
|
||||||
TileSimple(const PIString & n = PIString());
|
TileSimple(const PIString & n = PIString());
|
||||||
@@ -40,19 +39,17 @@ public:
|
|||||||
virtual ~TileSimple() {}
|
virtual ~TileSimple() {}
|
||||||
PIVector<Row> content;
|
PIVector<Row> content;
|
||||||
PIScreenTypes::Alignment alignment;
|
PIScreenTypes::Alignment alignment;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TileList;
|
class TileList;
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
|
||||||
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile);
|
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile)
|
||||||
friend class TileList;
|
friend class TileList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileScrollBar(const PIString & n = PIString());
|
TileScrollBar(const PIString & n = PIString());
|
||||||
virtual ~TileScrollBar() {}
|
virtual ~TileScrollBar() {}
|
||||||
@@ -63,20 +60,18 @@ public:
|
|||||||
int maximum() const {return maximum_;}
|
int maximum() const {return maximum_;}
|
||||||
int value() const {return value_;}
|
int value() const {return value_;}
|
||||||
int thickness;
|
int thickness;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _check();
|
void _check();
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
bool mouseEvent(PIKbdListener::MouseEvent me) override;
|
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||||
int minimum_, maximum_, value_;
|
int minimum_, maximum_, value_;
|
||||||
PIChar line_char;
|
PIChar line_char;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
|
||||||
PIOBJECT_SUBCLASS(TileList, PIScreenTile);
|
PIOBJECT_SUBCLASS(TileList, PIScreenTile)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum SelectionMode {
|
enum SelectionMode {
|
||||||
NoSelection,
|
NoSelection,
|
||||||
@@ -97,22 +92,20 @@ public:
|
|||||||
SelectionMode selection_mode;
|
SelectionMode selection_mode;
|
||||||
PISet<int> selected;
|
PISet<int> selected;
|
||||||
int lhei, cur, offset;
|
int lhei, cur, offset;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void resizeEvent(int w, int h) override;
|
void resizeEvent(int w, int h);
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||||
bool mouseEvent(PIKbdListener::MouseEvent me) override;
|
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||||
bool wheelEvent(PIKbdListener::WheelEvent we) override;
|
bool wheelEvent(PIKbdListener::WheelEvent we);
|
||||||
TileScrollBar * scroll;
|
TileScrollBar * scroll;
|
||||||
bool mouse_sel;
|
bool mouse_sel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
|
||||||
PIOBJECT_SUBCLASS(TileButton, PIScreenTile);
|
PIOBJECT_SUBCLASS(TileButton, PIScreenTile)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileButton(const PIString & n = PIString());
|
TileButton(const PIString & n = PIString());
|
||||||
virtual ~TileButton() {}
|
virtual ~TileButton() {}
|
||||||
@@ -121,18 +114,18 @@ public:
|
|||||||
};
|
};
|
||||||
PIScreenTypes::CellFormat format;
|
PIScreenTypes::CellFormat format;
|
||||||
PIString text;
|
PIString text;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||||
bool mouseEvent(PIKbdListener::MouseEvent me) override;
|
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
|
|
||||||
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile);
|
|
||||||
|
|
||||||
|
|
||||||
|
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
|
||||||
|
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile)
|
||||||
public:
|
public:
|
||||||
TileButtons(const PIString & n = PIString());
|
TileButtons(const PIString & n = PIString());
|
||||||
virtual ~TileButtons() {}
|
virtual ~TileButtons() {}
|
||||||
@@ -143,12 +136,11 @@ public:
|
|||||||
PIScreenTypes::Alignment alignment;
|
PIScreenTypes::Alignment alignment;
|
||||||
PIVector<Button> content;
|
PIVector<Button> content;
|
||||||
int cur;
|
int cur;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||||
bool mouseEvent(PIKbdListener::MouseEvent me) override;
|
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||||
struct Rect {
|
struct Rect {
|
||||||
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {}
|
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0),y0(_y0),x1(_x1),y1(_y1) {}
|
||||||
int x0,y0,x1,y1;
|
int x0,y0,x1,y1;
|
||||||
@@ -158,8 +150,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
|
||||||
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile);
|
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileCheck(const PIString & n = PIString());
|
TileCheck(const PIString & n = PIString());
|
||||||
virtual ~TileCheck() {}
|
virtual ~TileCheck() {}
|
||||||
@@ -169,18 +160,16 @@ public:
|
|||||||
PIScreenTypes::CellFormat format;
|
PIScreenTypes::CellFormat format;
|
||||||
PIString text;
|
PIString text;
|
||||||
bool toggled;
|
bool toggled;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||||
bool mouseEvent(PIKbdListener::MouseEvent me) override;
|
bool mouseEvent(PIKbdListener::MouseEvent me);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
|
||||||
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile);
|
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileProgress(const PIString & n = PIString());
|
TileProgress(const PIString & n = PIString());
|
||||||
virtual ~TileProgress() {}
|
virtual ~TileProgress() {}
|
||||||
@@ -189,42 +178,37 @@ public:
|
|||||||
PIString suffix;
|
PIString suffix;
|
||||||
double maximum;
|
double maximum;
|
||||||
double value;
|
double value;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
|
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
|
||||||
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);
|
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TilePICout(const PIString & n = PIString());
|
TilePICout(const PIString & n = PIString());
|
||||||
virtual ~TilePICout() {}
|
virtual ~TilePICout() {}
|
||||||
PIScreenTypes::CellFormat format;
|
PIScreenTypes::CellFormat format;
|
||||||
int max_lines;
|
int max_lines;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
|
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
|
||||||
PIOBJECT_SUBCLASS(TileInput, PIScreenTile);
|
PIOBJECT_SUBCLASS(TileInput, PIScreenTile)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileInput(const PIString & n = PIString());
|
TileInput(const PIString & n = PIString());
|
||||||
virtual ~TileInput() {}
|
virtual ~TileInput() {}
|
||||||
PIScreenTypes::CellFormat format;
|
PIScreenTypes::CellFormat format;
|
||||||
PIString text;
|
PIString text;
|
||||||
int max_length;
|
int max_length;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void sizeHint(int & w, int & h) const override;
|
void sizeHint(int & w, int & h) const;
|
||||||
void drawEvent(PIScreenDrawer * d) override;
|
void drawEvent(PIScreenDrawer * d);
|
||||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
bool keyEvent(PIKbdListener::KeyEvent key);
|
||||||
void reserCursor();
|
void reserCursor();
|
||||||
int cur, offset;
|
int cur, offset;
|
||||||
bool inv;
|
bool inv;
|
||||||
|
|||||||
@@ -110,10 +110,7 @@ union PIP_CONSOLE_EXPORT CellFormat {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PIP_CONSOLE_EXPORT Cell {
|
struct PIP_CONSOLE_EXPORT Cell {
|
||||||
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {
|
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {symbol = c; format = f;}
|
||||||
symbol = c;
|
|
||||||
format = f;
|
|
||||||
}
|
|
||||||
CellFormat format;
|
CellFormat format;
|
||||||
PIChar symbol;
|
PIChar symbol;
|
||||||
bool operator ==(const Cell & c) const {return format == c.format && symbol == c.symbol;}
|
bool operator ==(const Cell & c) const {return format == c.format && symbol == c.symbol;}
|
||||||
@@ -123,8 +120,7 @@ struct PIP_CONSOLE_EXPORT Cell {
|
|||||||
if (c.format.color_back == Transparent) {
|
if (c.format.color_back == Transparent) {
|
||||||
format.color_char = c.format.color_char;
|
format.color_char = c.format.color_char;
|
||||||
format.flags = c.format.flags;
|
format.flags = c.format.flags;
|
||||||
} else
|
} else format = c.format;
|
||||||
format = c.format;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -144,45 +140,14 @@ public:
|
|||||||
virtual void tileSetFocusInternal(PIScreenTile * ) {}
|
virtual void tileSetFocusInternal(PIScreenTile * ) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace PIScreenTypes
|
|
||||||
|
|
||||||
|
|
||||||
// inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
|
|
||||||
// inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
|
||||||
//! \~english Store operator
|
|
||||||
//! \~russian Оператор сохранения
|
|
||||||
BINARY_STREAM_WRITE(PIScreenTypes::Cell) {
|
|
||||||
s << v.format.raw_format << v.symbol;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
|
||||||
//! \~english Restore operator
|
|
||||||
//! \~russian Оператор извлечения
|
|
||||||
BINARY_STREAM_READ(PIScreenTypes::Cell) {
|
|
||||||
s >> v.format.raw_format >> v.symbol;
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::Cell & v) {s << v.format.raw_format << v.symbol; return s;}
|
||||||
//! \~english Store operator
|
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::Cell & v) {s >> v.format.raw_format >> v.symbol; return s;}
|
||||||
//! \~russian Оператор сохранения
|
|
||||||
BINARY_STREAM_WRITE(PIScreenTypes::TileEvent) {
|
|
||||||
s << v.type << v.data;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIBinaryStream
|
|
||||||
//! \~english Restore operator
|
|
||||||
//! \~russian Оператор извлечения
|
|
||||||
BINARY_STREAM_READ(PIScreenTypes::TileEvent) {
|
|
||||||
s >> v.type >> v.data;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIScreenTypes::TileEvent & v) {s << v.type << v.data; return s;}
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIScreenTypes::TileEvent & v) {s >> v.type >> v.data; return s;}
|
||||||
|
|
||||||
REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent)
|
REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent)
|
||||||
|
|
||||||
|
|||||||
@@ -26,15 +26,16 @@
|
|||||||
#ifndef PITERMINAL_H
|
#ifndef PITERMINAL_H
|
||||||
#define PITERMINAL_H
|
#define PITERMINAL_H
|
||||||
|
|
||||||
#include "pikbdlistener.h"
|
|
||||||
#include "pip_console_export.h"
|
#include "pip_console_export.h"
|
||||||
|
#include "pikbdlistener.h"
|
||||||
#include "piscreentypes.h"
|
#include "piscreentypes.h"
|
||||||
|
|
||||||
|
|
||||||
class PIP_CONSOLE_EXPORT PITerminal: public PIThread {
|
class PIP_CONSOLE_EXPORT PITerminal: public PIThread
|
||||||
PIOBJECT_SUBCLASS(PITerminal, PIThread);
|
{
|
||||||
|
PIOBJECT_SUBCLASS(PITerminal, PIThread)
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Constructs %PITerminal
|
//! Constructs %PITerminal
|
||||||
PITerminal();
|
PITerminal();
|
||||||
|
|
||||||
@@ -52,13 +53,12 @@ public:
|
|||||||
|
|
||||||
bool initialize();
|
bool initialize();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initPrivate();
|
void initPrivate();
|
||||||
void readConsole();
|
void readConsole();
|
||||||
void getCursor(int & x, int & y);
|
void getCursor(int & x, int & y);
|
||||||
uchar invertColor(uchar c);
|
uchar invertColor(uchar c);
|
||||||
void run() override;
|
void run();
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
void parseInput(const PIString & s);
|
void parseInput(const PIString & s);
|
||||||
bool isCompleteEscSeq(const PIString & es);
|
bool isCompleteEscSeq(const PIString & es);
|
||||||
@@ -73,6 +73,7 @@ private:
|
|||||||
bool cursor_blink, cursor_visible;
|
bool cursor_blink, cursor_visible;
|
||||||
PITimeMeasurer cursor_tm;
|
PITimeMeasurer cursor_tm;
|
||||||
PIVector<PIVector<PIScreenTypes::Cell> > cells;
|
PIVector<PIVector<PIScreenTypes::Cell> > cells;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,12 +20,11 @@
|
|||||||
#include "picontainers.h"
|
#include "picontainers.h"
|
||||||
|
|
||||||
|
|
||||||
const size_t minAlloc = 64;
|
const ssize_t minAlloc = 64;
|
||||||
|
|
||||||
|
|
||||||
size_t _PIContainerConstantsBase::calcMinCountPoT(size_t szof) {
|
ssize_t _PIContainerConstantsBase::calcMinCountPoT(ssize_t szof) {
|
||||||
size_t ret = 0;
|
ssize_t ret = 0, elc = 1;
|
||||||
size_t elc = 1;
|
|
||||||
while (elc * szof < minAlloc) {
|
while (elc * szof < minAlloc) {
|
||||||
elc *= 2;
|
elc *= 2;
|
||||||
++ret;
|
++ret;
|
||||||
|
|||||||
@@ -41,12 +41,12 @@
|
|||||||
#else
|
#else
|
||||||
# include <malloc.h>
|
# include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <string.h>
|
||||||
|
#include <new>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <initializer_list>
|
|
||||||
#include <new>
|
|
||||||
#include <string.h>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
@@ -58,7 +58,6 @@ public:
|
|||||||
typename C::reverse_iterator end() {return c_.rend(); }
|
typename C::reverse_iterator end() {return c_.rend(); }
|
||||||
typename C::const_reverse_iterator begin() const {return c_.rbegin();}
|
typename C::const_reverse_iterator begin() const {return c_.rbegin();}
|
||||||
typename C::const_reverse_iterator end() const {return c_.rend(); }
|
typename C::const_reverse_iterator end() const {return c_.rend(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
C & c_;
|
C & c_;
|
||||||
};
|
};
|
||||||
@@ -66,30 +65,21 @@ private:
|
|||||||
|
|
||||||
class PIP_EXPORT _PIContainerConstantsBase {
|
class PIP_EXPORT _PIContainerConstantsBase {
|
||||||
public:
|
public:
|
||||||
static size_t calcMinCountPoT(size_t szof);
|
static ssize_t calcMinCountPoT(ssize_t szof);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class _PIContainerConstants {
|
class _PIContainerConstants {
|
||||||
public:
|
public:
|
||||||
static size_t minCountPoT() {
|
static ssize_t minCountPoT() {static ssize_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); return ret;}
|
||||||
static const size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \brief
|
//! \brief
|
||||||
//! \~english Template reverse wrapper over any container
|
//! \~english Template reverse wrapper over any container
|
||||||
//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
|
//! \~russian Шаблонная функция обертки любого контейнера для обратного доступа через итераторы
|
||||||
template<typename C>
|
template <typename C> _PIReverseWrapper<C> PIReverseWrap(C & c) {return _PIReverseWrapper<C>(c);}
|
||||||
_PIReverseWrapper<C> PIReverseWrap(C & c) {
|
template <typename C> _PIReverseWrapper<C> PIReverseWrap(const C & c) {return _PIReverseWrapper<C>(c);}
|
||||||
return _PIReverseWrapper<C>(c);
|
|
||||||
}
|
|
||||||
template<typename C>
|
|
||||||
_PIReverseWrapper<C> PIReverseWrap(const C & c) {
|
|
||||||
return _PIReverseWrapper<C>(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \brief
|
//! \brief
|
||||||
@@ -187,9 +177,7 @@ _PIReverseWrapper<C> PIReverseWrap(const C & c) {
|
|||||||
//! \~russian Порядок обхода для функции изменения размерности reshape().
|
//! \~russian Порядок обхода для функции изменения размерности reshape().
|
||||||
//! \~ \sa \a PIVector::reshape(), \a PIDeque::reshape()
|
//! \~ \sa \a PIVector::reshape(), \a PIDeque::reshape()
|
||||||
enum ReshapeOrder {
|
enum ReshapeOrder {
|
||||||
ReshapeByRow /*! \~english Traversing elements by line, just as they stay in memory \~russian Обход элементов построчно, так же как они
|
ReshapeByRow /*! \~english Traversing elements by line, just as they stay in memory \~russian Обход элементов построчно, так же как они находятся в памяти */,
|
||||||
находятся в памяти */
|
|
||||||
,
|
|
||||||
ReshapeByColumn /*! \~english Traversing elements by column \~russian Обход элементов по столбцам */,
|
ReshapeByColumn /*! \~english Traversing elements by column \~russian Обход элементов по столбцам */,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -180,12 +180,12 @@
|
|||||||
#ifndef PICONTAINERSMODULE_H
|
#ifndef PICONTAINERSMODULE_H
|
||||||
#define PICONTAINERSMODULE_H
|
#define PICONTAINERSMODULE_H
|
||||||
|
|
||||||
|
#include "pivector.h"
|
||||||
#include "pideque.h"
|
#include "pideque.h"
|
||||||
#include "pimap.h"
|
#include "pimap.h"
|
||||||
#include "piqueue.h"
|
#include "piqueue.h"
|
||||||
#include "piset.h"
|
#include "piset.h"
|
||||||
#include "pistack.h"
|
#include "pistack.h"
|
||||||
#include "pivector.h"
|
|
||||||
#include "pivector2d.h"
|
#include "pivector2d.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -75,9 +75,9 @@
|
|||||||
//! if the number of elements is known beforehand.
|
//! if the number of elements is known beforehand.
|
||||||
//!
|
//!
|
||||||
//! The complexity (efficiency) of common operations on PIDeque is as follows:
|
//! The complexity (efficiency) of common operations on PIDeque is as follows:
|
||||||
//! - Random access - constant O(1)
|
//! - Random access - constant 𝓞(1)
|
||||||
//! - Insertion or removal of elements at the end or begin - amortized constant O(1)
|
//! - Insertion or removal of elements at the end or begin - amortized constant 𝓞(1)
|
||||||
//! - Insertion or removal of elements - linear in the distance to the end of the array O(n)
|
//! - Insertion or removal of elements - linear in the distance to the end of the array 𝓞(n)
|
||||||
//!
|
//!
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! Элементы хранятся непрерывно, а значит доступны не только через итераторы,
|
//! Элементы хранятся непрерывно, а значит доступны не только через итераторы,
|
||||||
@@ -109,9 +109,9 @@
|
|||||||
//! если количество элементов известно заранее.
|
//! если количество элементов известно заранее.
|
||||||
//!
|
//!
|
||||||
//! Сложность (эффективность) обычных операций над PIDeque следующая:
|
//! Сложность (эффективность) обычных операций над PIDeque следующая:
|
||||||
//! - Произвольный доступ — постоянная O(1)
|
//! - Произвольный доступ — постоянная 𝓞(1)
|
||||||
//! - Вставка и удаление элементов в конце или начале — амортизированная постоянная O(1)
|
//! - Вставка и удаление элементов в конце или начале — амортизированная постоянная 𝓞(1)
|
||||||
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива O(n)
|
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива 𝓞(n)
|
||||||
//!
|
//!
|
||||||
//! \~\sa \a PIVector, \a PIMap
|
//! \~\sa \a PIVector, \a PIMap
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -127,11 +127,13 @@ public:
|
|||||||
|
|
||||||
//! \~english Constructs an empty array.
|
//! \~english Constructs an empty array.
|
||||||
//! \~russian Создает пустой массив.
|
//! \~russian Создает пустой массив.
|
||||||
inline PIDeque() { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) }
|
inline PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||||
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Copy constructor.
|
//! \~english Copy constructor.
|
||||||
//! \~russian Копирующий конструктор.
|
//! \~russian Копирующий конструктор.
|
||||||
inline PIDeque(const PIDeque<T> & other) {
|
inline PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
alloc_forward(other.pid_size);
|
alloc_forward(other.pid_size);
|
||||||
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
|
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
|
||||||
@@ -146,7 +148,7 @@ public:
|
|||||||
//! PIDeque <int> v{1,2,3};
|
//! PIDeque <int> v{1,2,3};
|
||||||
//! piCout << v; // {1, 2, 3}
|
//! piCout << v; // {1, 2, 3}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
inline PIDeque(std::initializer_list<T> init_list) {
|
inline PIDeque(std::initializer_list<T> init_list): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
alloc_forward(init_list.size());
|
alloc_forward(init_list.size());
|
||||||
newT(pid_data, init_list.begin(), init_list.size());
|
newT(pid_data, init_list.begin(), init_list.size());
|
||||||
@@ -156,7 +158,7 @@ public:
|
|||||||
//! This constructor reserve `size` and copy from `data` pointer.
|
//! This constructor reserve `size` and copy from `data` pointer.
|
||||||
//! \~russian Создает массив из указателя на данные `data` и размер `size`.
|
//! \~russian Создает массив из указателя на данные `data` и размер `size`.
|
||||||
//! То есть выделяет память для `size` элементов и копирует данные из указателя `data`.
|
//! То есть выделяет память для `size` элементов и копирует данные из указателя `data`.
|
||||||
inline PIDeque(const T * data, size_t size) {
|
inline PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
alloc_forward(size);
|
alloc_forward(size);
|
||||||
newT(pid_data + pid_start, data, pid_size);
|
newT(pid_data + pid_start, data, pid_size);
|
||||||
@@ -164,9 +166,9 @@ public:
|
|||||||
|
|
||||||
//! \~english Contructs array with size `size` filled elements `e`.
|
//! \~english Contructs array with size `size` filled elements `e`.
|
||||||
//! \~russian Создает массив из `size` элементов заполненных `e`.
|
//! \~russian Создает массив из `size` элементов заполненных `e`.
|
||||||
inline explicit PIDeque(size_t pid_size, const T & e = T()) {
|
inline PIDeque(size_t pid_size, const T & e = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
expand(pid_size, e);
|
resize(pid_size, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
|
//! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
|
||||||
@@ -182,34 +184,31 @@ public:
|
|||||||
//! PIDeque <int> v(5, [](size_t i){return i*2;});
|
//! PIDeque <int> v(5, [](size_t i){return i*2;});
|
||||||
//! piCout << v; // {0, 2, 4, 6, 8}
|
//! piCout << v; // {0, 2, 4, 6, 8}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
inline PIDeque(size_t piv_size, std::function<T(size_t i)> f) {
|
inline PIDeque(size_t piv_size, std::function<T(size_t i)> f): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
expand(piv_size, f);
|
resize(piv_size, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Move constructor.
|
//! \~english Move constructor.
|
||||||
//! \~russian Перемещающий конструктор.
|
//! \~russian Перемещающий конструктор.
|
||||||
inline PIDeque(PIDeque<T> && other) {
|
inline PIDeque(PIDeque<T> && other): pid_data(other.pid_data), pid_size(other.pid_size), pid_rsize(other.pid_rsize), pid_start(other.pid_start) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
pid_data = other.pid_data;
|
|
||||||
pid_size = other.pid_size;
|
|
||||||
pid_rsize = other.pid_rsize;
|
|
||||||
pid_start = other.pid_start;
|
|
||||||
other._reset();
|
other._reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~PIDeque() {
|
inline virtual ~PIDeque() {
|
||||||
PIINTROSPECTION_CONTAINER_DELETE(T)
|
PIINTROSPECTION_CONTAINER_DELETE(T)
|
||||||
PIINTROSPECTION_CONTAINER_FREE(T, (pid_rsize))
|
PIINTROSPECTION_CONTAINER_FREE(T, (pid_rsize))
|
||||||
deleteT(pid_data + pid_start, pid_size);
|
deleteT(pid_data + pid_start, pid_size);
|
||||||
dealloc();
|
dealloc();
|
||||||
|
_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Assign operator.
|
//! \~english Assign operator.
|
||||||
//! \~russian Оператор присваивания.
|
//! \~russian Оператор присваивания.
|
||||||
inline PIDeque<T> & operator =(const PIDeque<T> & other) {
|
inline PIDeque<T> & operator =(const PIDeque<T> & other) {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
clear();
|
deleteT(pid_data + pid_start, pid_size);
|
||||||
alloc_forward(other.pid_size);
|
alloc_forward(other.pid_size);
|
||||||
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
|
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -224,12 +223,10 @@ public:
|
|||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
friend class PIDeque<T>;
|
friend class PIDeque<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
PIDeque<T> * parent;
|
PIDeque<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -249,7 +246,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline iterator operator ++(int) {
|
inline iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -258,7 +255,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline iterator operator --(int) {
|
inline iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -286,7 +283,9 @@ public:
|
|||||||
tmp -= p;
|
tmp -= p;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
friend inline std::ptrdiff_t operator-(const iterator & it1, const iterator & it2) { return it1.pos - it2.pos; }
|
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos - it2.pos;
|
||||||
|
}
|
||||||
|
|
||||||
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
|
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
|
||||||
friend inline iterator operator +(const iterator & it, size_t p) {
|
friend inline iterator operator +(const iterator & it, size_t p) {
|
||||||
@@ -297,20 +296,26 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const iterator & it1, const iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const iterator & it1, const iterator & it2) {
|
||||||
friend inline bool operator<=(const iterator & it1, const iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const iterator & it1, const iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const iterator & it1, const iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class const_iterator {
|
class const_iterator {
|
||||||
friend class PIDeque<T>;
|
friend class PIDeque<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline const_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline const_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIDeque<T> * parent;
|
const PIDeque<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -328,7 +333,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_iterator operator ++(int) {
|
inline const_iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -337,7 +342,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_iterator operator --(int) {
|
inline const_iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -365,7 +370,9 @@ public:
|
|||||||
tmp -= p;
|
tmp -= p;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; }
|
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos - it2.pos;
|
||||||
|
}
|
||||||
|
|
||||||
friend inline const_iterator operator +(size_t p, const const_iterator & it) {return it + p;}
|
friend inline const_iterator operator +(size_t p, const const_iterator & it) {return it + p;}
|
||||||
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
|
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
|
||||||
@@ -376,20 +383,26 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {
|
||||||
friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class reverse_iterator {
|
class reverse_iterator {
|
||||||
friend class PIDeque<T>;
|
friend class PIDeque<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline reverse_iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline reverse_iterator(PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
PIDeque<T> * parent;
|
PIDeque<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -409,7 +422,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline reverse_iterator operator ++(int) {
|
inline reverse_iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -418,7 +431,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline reverse_iterator operator --(int) {
|
inline reverse_iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -446,7 +459,9 @@ public:
|
|||||||
tmp -= p;
|
tmp -= p;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
friend inline std::ptrdiff_t operator-(const reverse_iterator & it1, const reverse_iterator & it2) { return it2.pos - it1.pos; }
|
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it2.pos - it1.pos;
|
||||||
|
}
|
||||||
|
|
||||||
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
|
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
|
||||||
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
|
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
|
||||||
@@ -457,20 +472,26 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
friend inline bool operator<=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class const_reverse_iterator {
|
class const_reverse_iterator {
|
||||||
friend class PIDeque<T>;
|
friend class PIDeque<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline const_reverse_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline const_reverse_iterator(const PIDeque<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIDeque<T> * parent;
|
const PIDeque<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -487,7 +508,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_reverse_iterator operator ++(int) {
|
inline const_reverse_iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -496,7 +517,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_reverse_iterator operator --(int) {
|
inline const_reverse_iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -537,10 +558,18 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
friend inline bool operator<=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -584,8 +613,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Returns a reverse iterator to the element.
|
//! \~english Returns a reverse iterator to the element.
|
||||||
//! following the last element of the reversed array.
|
//! following the last element of the reversed array.
|
||||||
//! \~russian Обратный итератор на элемент,
|
//! \~russian Обратный итератор на элемент, следующий за последним элементом.
|
||||||
//! следующий за последним элементом.
|
|
||||||
//! \~\details 
|
//! \~\details 
|
||||||
//!
|
//!
|
||||||
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
|
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
|
||||||
@@ -617,7 +645,7 @@ public:
|
|||||||
inline size_t length() const {return pid_size;}
|
inline size_t length() const {return pid_size;}
|
||||||
|
|
||||||
//! \~english Number of elements that the container has currently allocated space for.
|
//! \~english Number of elements that the container has currently allocated space for.
|
||||||
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
|
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english To find out the actual number of items, use the function \a size().
|
//! \~english To find out the actual number of items, use the function \a size().
|
||||||
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
|
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
|
||||||
@@ -627,18 +655,18 @@ public:
|
|||||||
inline size_t _start() const {return pid_start;}
|
inline size_t _start() const {return pid_start;}
|
||||||
|
|
||||||
//! \~english Checks if the container has no elements.
|
//! \~english Checks if the container has no elements.
|
||||||
//! \~russian Проверяет пуст ли массив.
|
//! \~russian Проверяет пуст ли контейнер.
|
||||||
//! \~\return
|
//! \~\return
|
||||||
//! \~english **true** if the container is empty, **false** otherwise
|
//! \~english **true** if the container is empty, **false** otherwise
|
||||||
//! \~russian **true** если массив пуст, **false** иначе.
|
//! \~russian **true** если контейнер пуст, **false** иначе.
|
||||||
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
||||||
inline bool isEmpty() const {return (pid_size == 0);}
|
inline bool isEmpty() const {return (pid_size == 0);}
|
||||||
|
|
||||||
//! \~english Checks if the container has elements.
|
//! \~english Checks if the container has elements.
|
||||||
//! \~russian Проверяет не пуст ли массив.
|
//! \~russian Проверяет не пуст ли контейнер.
|
||||||
//! \~\return
|
//! \~\return
|
||||||
//! \~english **true** if the container is not empty, **false** otherwise
|
//! \~english **true** if the container is not empty, **false** otherwise
|
||||||
//! \~russian **true** если массив не пуст, **false** иначе.
|
//! \~russian **true** если контейнер не пуст, **false** иначе.
|
||||||
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
||||||
inline bool isNotEmpty() const {return (pid_size > 0);}
|
inline bool isNotEmpty() const {return (pid_size > 0);}
|
||||||
|
|
||||||
@@ -661,7 +689,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
|
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
|
||||||
inline bool any(std::function<bool(const T & e)> test) const {
|
inline bool any(std::function<bool(const T & e)> test) const {
|
||||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||||
if (test(pid_data[i])) return true;
|
if (test(pid_data[i])) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -686,7 +714,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
|
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
|
||||||
inline bool every(std::function<bool(const T & e)> test) const {
|
inline bool every(std::function<bool(const T & e)> test) const {
|
||||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
for (ssize_t i = pid_start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||||
if (!test(pid_data[i])) return false;
|
if (!test(pid_data[i])) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -722,34 +750,6 @@ public:
|
|||||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||||
inline const T & at(size_t index) const {return pid_data[pid_start + index];}
|
inline const T & at(size_t index) const {return pid_data[pid_start + index];}
|
||||||
|
|
||||||
//! \~english Returns the first element of the array that
|
|
||||||
//! passes the test implemented by the provided function `test`
|
|
||||||
//! or `def` if there is no such element.
|
|
||||||
//! \~russian Возвращает первый элемент массива, проходящего по условию,
|
|
||||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
|
||||||
//! \~\sa \a indexWhere()
|
|
||||||
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
|
|
||||||
const ssize_t i = indexWhere(test, start);
|
|
||||||
if (i < 0)
|
|
||||||
return def;
|
|
||||||
else
|
|
||||||
return at(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns the last element of the array that
|
|
||||||
//! passes the test implemented by the provided function `test`
|
|
||||||
//! or `def` if there is no such element.
|
|
||||||
//! \~russian Возвращает последний элемент массива, проходящего по условию,
|
|
||||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
|
||||||
//! \~\sa \a lastIndexWhere()
|
|
||||||
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
|
|
||||||
const ssize_t i = lastIndexWhere(test, start);
|
|
||||||
if (i < 0)
|
|
||||||
return def;
|
|
||||||
else
|
|
||||||
return at(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Last element.
|
//! \~english Last element.
|
||||||
//! \~russian Последний элемент массива.
|
//! \~russian Последний элемент массива.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -804,7 +804,7 @@ public:
|
|||||||
//! возвращается **false**, что означает, что массив даже не просматривается.
|
//! возвращается **false**, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIDeque<int> v{1, 2, 3, 4};
|
//! PIDeque<int> v{1, 2, 3, 4};
|
||||||
@@ -825,39 +825,12 @@ public:
|
|||||||
start = pid_size + start;
|
start = pid_size + start;
|
||||||
if (start < 0) start = 0;
|
if (start < 0) start = 0;
|
||||||
}
|
}
|
||||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||||
if (e == pid_data[i]) return true;
|
if (e == pid_data[i]) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Tests if all elements of `v` exists in the array.
|
|
||||||
//! \~russian Проверяет наличие всех элементов `v` в массиве.
|
|
||||||
//! \~\details
|
|
||||||
//! \~\code
|
|
||||||
//! PIDeque<int> v{1, 2, 3, 4};
|
|
||||||
//! piCout << v.contains({1,4}); // true
|
|
||||||
//! piCout << v.contains({1,5}); // false
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a every(), \a any(), \a entries(), \a forEach()
|
|
||||||
inline bool contains(const PIDeque<T> & v, ssize_t start = 0) const {
|
|
||||||
if (start < 0) {
|
|
||||||
start = pid_size + start;
|
|
||||||
if (start < 0) start = 0;
|
|
||||||
}
|
|
||||||
for (const T & e: v) {
|
|
||||||
bool c = false;
|
|
||||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
|
||||||
if (e == pid_data[i]) {
|
|
||||||
c = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!c) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Count elements equal `e` in the array.
|
//! \~english Count elements equal `e` in the array.
|
||||||
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
|
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -874,7 +847,7 @@ public:
|
|||||||
//! возвращается 0, что означает, что массив даже не просматривается.
|
//! возвращается 0, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIDeque<int> v{2, 2, 4, 2, 6};
|
//! PIDeque<int> v{2, 2, 4, 2, 6};
|
||||||
@@ -883,13 +856,13 @@ public:
|
|||||||
//! piCout << v.entries(2, -4); // 2
|
//! piCout << v.entries(2, -4); // 2
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexOf()
|
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexOf()
|
||||||
inline int entries(const T & e, ssize_t start = 0) const {
|
inline int entries(const T & e, size_t start = 0) const {
|
||||||
int ec = 0;
|
int ec = 0;
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
start = pid_size + start;
|
start = pid_size + start;
|
||||||
if (start < 0) start = 0;
|
if (start < 0) start = 0;
|
||||||
}
|
}
|
||||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||||
if (e == pid_data[i]) ++ec;
|
if (e == pid_data[i]) ++ec;
|
||||||
}
|
}
|
||||||
return ec;
|
return ec;
|
||||||
@@ -914,16 +887,16 @@ public:
|
|||||||
//! возвращается 0, что означает, что массив даже не просматривается.
|
//! возвращается 0, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere()
|
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere()
|
||||||
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
|
inline int entries(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||||
int ec = 0;
|
int ec = 0;
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
start = pid_size + start;
|
start = pid_size + start;
|
||||||
if (start < 0) start = 0;
|
if (start < 0) start = 0;
|
||||||
}
|
}
|
||||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||||
if (test(pid_data[i])) ++ec;
|
if (test(pid_data[i])) ++ec;
|
||||||
}
|
}
|
||||||
return ec;
|
return ec;
|
||||||
@@ -947,7 +920,7 @@ public:
|
|||||||
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIDeque<int> v{2, 5, 9};
|
//! PIDeque<int> v{2, 5, 9};
|
||||||
@@ -958,14 +931,14 @@ public:
|
|||||||
//! piCout << v.indexOf(2, -3); // 0
|
//! piCout << v.indexOf(2, -3); // 0
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a indexWhere(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
//! \~\sa \a indexWhere(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
||||||
inline ssize_t indexOf(const T & e, ssize_t start = 0) const {
|
inline ssize_t indexOf(const T & e, size_t start = 0) const {
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
start = pid_size + start;
|
start = pid_size + start;
|
||||||
if (start < 0) start = 0;
|
if (start < 0) start = 0;
|
||||||
}
|
}
|
||||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||||
if (e == pid_data[i]) {
|
if (e == pid_data[i]) {
|
||||||
return ssize_t(i) - pid_start;
|
return i - pid_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -990,7 +963,7 @@ public:
|
|||||||
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIDeque<PIString> v{"do", "re", "mi", "re"};
|
//! PIDeque<PIString> v{"do", "re", "mi", "re"};
|
||||||
@@ -999,14 +972,14 @@ public:
|
|||||||
//! piCout << v.indexWhere([](const PIString & s){return s.startsWith('k');}); // -1
|
//! piCout << v.indexWhere([](const PIString & s){return s.startsWith('k');}); // -1
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
|
||||||
inline ssize_t indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
|
inline ssize_t indexWhere(std::function<bool(const T & e)> test, size_t start = 0) const {
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
start = pid_size + start;
|
start = pid_size + start;
|
||||||
if (start < 0) start = 0;
|
if (start < 0) start = 0;
|
||||||
}
|
}
|
||||||
for (size_t i = pid_start + size_t(start); i < pid_start + pid_size; ++i) {
|
for (ssize_t i = pid_start + start; i < pid_start + (ssize_t)pid_size; ++i) {
|
||||||
if (test(pid_data[i])) {
|
if (test(pid_data[i])) {
|
||||||
return ssize_t(i) - pid_start;
|
return i - pid_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1032,7 +1005,7 @@ public:
|
|||||||
//! c которого начинать поиск в обратном направлении.
|
//! c которого начинать поиск в обратном направлении.
|
||||||
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
|
||||||
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
||||||
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
||||||
//! и означает, что просматривается весь массив.
|
//! и означает, что просматривается весь массив.
|
||||||
@@ -1049,9 +1022,9 @@ public:
|
|||||||
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
|
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
|
||||||
if (start >= size_s()) start = pid_size - 1;
|
if (start >= size_s()) start = pid_size - 1;
|
||||||
if (start < 0) start = pid_size + start;
|
if (start < 0) start = pid_size + start;
|
||||||
for (ssize_t i = ssize_t(pid_start) + start; i >= ssize_t(pid_start); --i) {
|
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
|
||||||
if (e == pid_data[i]) {
|
if (e == pid_data[i]) {
|
||||||
return i - ssize_t(pid_start);
|
return i - pid_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1077,7 +1050,7 @@ public:
|
|||||||
//! c которого начинать поиск в обратном направлении.
|
//! c которого начинать поиск в обратном направлении.
|
||||||
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
|
||||||
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
||||||
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
||||||
//! и означает, что просматривается весь массив.
|
//! и означает, что просматривается весь массив.
|
||||||
@@ -1085,9 +1058,9 @@ public:
|
|||||||
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
|
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
|
||||||
if (start >= size_s()) start = pid_size - 1;
|
if (start >= size_s()) start = pid_size - 1;
|
||||||
if (start < 0) start = pid_size + start;
|
if (start < 0) start = pid_size + start;
|
||||||
for (ssize_t i = ssize_t(pid_start) + start; i >= ssize_t(pid_start); --i) {
|
for (ssize_t i = pid_start + start; i >= pid_start; --i) {
|
||||||
if (test(pid_data[i])) {
|
if (test(pid_data[i])) {
|
||||||
return i - ssize_t(pid_start);
|
return i - pid_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1146,7 +1119,7 @@ public:
|
|||||||
PIDeque<T> getRange(size_t index, size_t count) const {
|
PIDeque<T> getRange(size_t index, size_t count) const {
|
||||||
if (index >= pid_size || count == 0) return PIDeque<T>();
|
if (index >= pid_size || count == 0) return PIDeque<T>();
|
||||||
if (index + count > pid_size) count = pid_size - index;
|
if (index + count > pid_size) count = pid_size - index;
|
||||||
return PIDeque(pid_data + pid_start + index, count);
|
return PIDeque(&(pid_data[pid_start + index]), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Clear array, remove all elements.
|
//! \~english Clear array, remove all elements.
|
||||||
@@ -1156,14 +1129,16 @@ public:
|
|||||||
//! \~english Reserved memory will not be released.
|
//! \~english Reserved memory will not be released.
|
||||||
//! \~russian Зарезервированная память не освободится.
|
//! \~russian Зарезервированная память не освободится.
|
||||||
//! \~\sa \a resize()
|
//! \~\sa \a resize()
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIDeque<T> & clear() {
|
inline PIDeque<T> & clear() {
|
||||||
deleteT(pid_data + pid_start, pid_size);
|
resize(0);
|
||||||
pid_size = 0;
|
|
||||||
pid_start = (pid_rsize - pid_size) / 2;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIDeque<T> & clear() {
|
inline PIDeque<T> & clear() {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, pid_size)
|
PIINTROSPECTION_CONTAINER_UNUSED(T, pid_size)
|
||||||
pid_size = 0;
|
pid_size = 0;
|
||||||
@@ -1215,12 +1190,16 @@ public:
|
|||||||
//! \~english First does `resize(new_size)` then `fill(e)`.
|
//! \~english First does `resize(new_size)` then `fill(e)`.
|
||||||
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
|
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
|
||||||
//! \~\sa \a fill(), \a resize()
|
//! \~\sa \a fill(), \a resize()
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIDeque<T> & assign(size_t new_size, const T & e) {
|
inline PIDeque<T> & assign(size_t new_size, const T & e) {
|
||||||
resize(new_size);
|
resize(new_size);
|
||||||
return fill(e);
|
return fill(e);
|
||||||
}
|
}
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIDeque<T> & assign(size_t new_size, const T & e) {
|
inline PIDeque<T> & assign(size_t new_size, const T & e) {
|
||||||
_resizeRaw(new_size);
|
_resizeRaw(new_size);
|
||||||
return fill(e);
|
return fill(e);
|
||||||
@@ -1238,12 +1217,20 @@ public:
|
|||||||
//! лишние элементы удаляются с конца массива.
|
//! лишние элементы удаляются с конца массива.
|
||||||
//! \~\sa \a size(), \a clear()
|
//! \~\sa \a size(), \a clear()
|
||||||
inline PIDeque<T> & resize(size_t new_size, const T & e = T()) {
|
inline PIDeque<T> & resize(size_t new_size, const T & e = T()) {
|
||||||
if (new_size == 0) return clear();
|
|
||||||
if (new_size < pid_size) {
|
if (new_size < pid_size) {
|
||||||
deleteT(pid_data + pid_start + new_size, pid_size - new_size);
|
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
|
||||||
pid_size = new_size;
|
pid_size = new_size;
|
||||||
} else if (new_size > pid_size) {
|
if (new_size == 0) {
|
||||||
expand(new_size, e);
|
pid_start = (pid_rsize - pid_size) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (new_size > pid_size) {
|
||||||
|
size_t os = pid_size;
|
||||||
|
alloc_forward(new_size);
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||||
|
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
|
||||||
|
elementNew(pid_data + i, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1260,31 +1247,41 @@ public:
|
|||||||
//! лишние элементы удаляются с конца массива.
|
//! лишние элементы удаляются с конца массива.
|
||||||
//! \~\sa \a size(), \a clear()
|
//! \~\sa \a size(), \a clear()
|
||||||
inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
|
inline PIDeque<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
|
||||||
if (new_size == 0) return clear();
|
|
||||||
if (new_size < pid_size) {
|
if (new_size < pid_size) {
|
||||||
deleteT(pid_data + pid_start + new_size, pid_size - new_size);
|
deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size);
|
||||||
pid_size = new_size;
|
pid_size = new_size;
|
||||||
} else if (new_size > pid_size) {
|
if (new_size == 0) {
|
||||||
expand(new_size, f);
|
pid_start = (pid_rsize - pid_size) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (new_size > pid_size) {
|
||||||
|
size_t os = pid_size;
|
||||||
|
alloc_forward(new_size);
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||||
|
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
|
||||||
|
elementNew(pid_data + i, f(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIDeque<T> & _resizeRaw(size_t new_size) {
|
inline PIDeque<T> & _resizeRaw(size_t new_size) {
|
||||||
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
|
|
||||||
if (new_size > pid_size) {
|
if (new_size > pid_size) {
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-pid_size));
|
PIINTROSPECTION_CONTAINER_USED(T, (new_size-pid_size));
|
||||||
}
|
}
|
||||||
if (new_size < pid_size) {
|
if (new_size < pid_size) {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size));
|
PIINTROSPECTION_CONTAINER_UNUSED(T, (pid_size-new_size));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
alloc_forward(new_size);
|
alloc_forward(new_size);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void _copyRaw(T * dst, const T * src, size_t size) { newT(dst, src, size); }
|
inline void _copyRaw(T * dst, const T * src, size_t size) {
|
||||||
|
newT(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Attempts to allocate memory for at least `new_size` elements.
|
//! \~english Attempts to allocate memory for at least `new_size` elements.
|
||||||
//! \~russian Резервируется память под как минимум `new_size` элементов.
|
//! \~russian Резервируется память под как минимум `new_size` элементов.
|
||||||
@@ -1302,7 +1299,7 @@ public:
|
|||||||
//! \~\sa \a size(), \a capacity(), \a resize()
|
//! \~\sa \a size(), \a capacity(), \a resize()
|
||||||
inline PIDeque<T> & reserve(size_t new_size) {
|
inline PIDeque<T> & reserve(size_t new_size) {
|
||||||
if (new_size <= pid_rsize) return *this;
|
if (new_size <= pid_rsize) return *this;
|
||||||
const size_t os = pid_size;
|
size_t os = pid_size;
|
||||||
alloc_forward(new_size);
|
alloc_forward(new_size);
|
||||||
pid_size = os;
|
pid_size = os;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1322,21 +1319,17 @@ public:
|
|||||||
inline PIDeque<T> & insert(size_t index, const T & e = T()) {
|
inline PIDeque<T> & insert(size_t index, const T & e = T()) {
|
||||||
if (index == pid_size) return push_back(e);
|
if (index == pid_size) return push_back(e);
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||||
const bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
alloc_forward(pid_size + 1);
|
alloc_forward(pid_size + 1);
|
||||||
if (index < pid_size - 1) {
|
if (index < pid_size - 1) {
|
||||||
const size_t os = pid_size - index - 1;
|
size_t os = pid_size - index - 1;
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + 1),
|
memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
|
||||||
os * sizeof(T));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alloc_backward(pid_size + 1, -1);
|
alloc_backward(pid_size + 1, -1);
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + 1),
|
|
||||||
index * sizeof(T));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elementNew(pid_data + pid_start + index, e);
|
elementNew(pid_data + pid_start + index, e);
|
||||||
@@ -1352,21 +1345,17 @@ public:
|
|||||||
inline PIDeque<T> & insert(size_t index, T && e) {
|
inline PIDeque<T> & insert(size_t index, T && e) {
|
||||||
if (index == pid_size) return push_back(e);
|
if (index == pid_size) return push_back(e);
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||||
const bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
alloc_forward(pid_size + 1);
|
alloc_forward(pid_size + 1);
|
||||||
if (index < pid_size - 1) {
|
if (index < pid_size - 1) {
|
||||||
const size_t os = pid_size - index - 1;
|
size_t os = pid_size - index - 1;
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + 1),
|
memmove((void*)(&(pid_data[index + pid_start + 1])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
|
||||||
os * sizeof(T));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alloc_backward(pid_size + 1, -1);
|
alloc_backward(pid_size + 1, -1);
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + 1])), index * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + 1),
|
|
||||||
index * sizeof(T));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elementNew(pid_data + pid_start + index, std::move(e));
|
elementNew(pid_data + pid_start + index, std::move(e));
|
||||||
@@ -1387,21 +1376,17 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(&v != this);
|
assert(&v != this);
|
||||||
const bool dir = v.size() > pid_size ? true : (index >= pid_rsize / 2 ? true : false);
|
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
const ssize_t os = pid_size - index;
|
ssize_t os = pid_size - index;
|
||||||
alloc_forward(pid_size + v.pid_size);
|
alloc_forward(pid_size + v.pid_size);
|
||||||
if (os > 0) {
|
if (os > 0) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + v.pid_size),
|
memmove((void*)(&(pid_data[index + pid_start + v.pid_size])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
|
||||||
os * sizeof(T));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alloc_backward(pid_size + v.pid_size, -v.pid_size);
|
alloc_backward(pid_size + v.pid_size, -v.pid_size);
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + v.pid_size])), index * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + v.pid_size),
|
|
||||||
index * sizeof(T));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newT(pid_data + pid_start + index, v.pid_data + v.pid_start, v.pid_size);
|
newT(pid_data + pid_start + index, v.pid_data + v.pid_start, v.pid_size);
|
||||||
@@ -1419,22 +1404,17 @@ public:
|
|||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||||
//! \~\sa \a append(), \a prepend(), \a remove()
|
//! \~\sa \a append(), \a prepend(), \a remove()
|
||||||
inline PIDeque<T> & insert(size_t index, std::initializer_list<T> init_list) {
|
inline PIDeque<T> & insert(size_t index, std::initializer_list<T> init_list) {
|
||||||
if (init_list.size() == 0) return *this;
|
bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false);
|
||||||
const bool dir = init_list.size() > pid_size ? true : (index >= pid_rsize / 2 ? true : false);
|
|
||||||
if (dir) {
|
if (dir) {
|
||||||
const ssize_t os = ssize_t(pid_size) - index;
|
ssize_t os = pid_size - index;
|
||||||
alloc_forward(pid_size + init_list.size());
|
alloc_forward(pid_size + init_list.size());
|
||||||
if (os > 0) {
|
if (os > 0) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index + init_list.size()),
|
memmove((void*)(&(pid_data[index + pid_start + init_list.size()])), (const void*)(&(pid_data[index + pid_start])), os * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
|
||||||
os * sizeof(T));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alloc_backward(pid_size + init_list.size(), -init_list.size());
|
alloc_backward(pid_size + init_list.size(), -init_list.size());
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start),
|
memmove((void*)(&(pid_data[pid_start])), (const void*)(&(pid_data[pid_start + init_list.size()])), index * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + init_list.size()),
|
|
||||||
index * sizeof(T));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newT(pid_data + pid_start + index, init_list.begin(), init_list.size());
|
newT(pid_data + pid_start + index, init_list.begin(), init_list.size());
|
||||||
@@ -1453,27 +1433,22 @@ public:
|
|||||||
inline PIDeque<T> & remove(size_t index, size_t count = 1) {
|
inline PIDeque<T> & remove(size_t index, size_t count = 1) {
|
||||||
if (count == 0) return *this;
|
if (count == 0) return *this;
|
||||||
if (index + count >= pid_size) {
|
if (index + count >= pid_size) {
|
||||||
if (index < pid_size) {
|
resize(index);
|
||||||
deleteT(pid_data + pid_start + index, pid_size - index);
|
return *this;
|
||||||
pid_size = index;
|
}
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
const size_t os = pid_size - index - count;
|
|
||||||
deleteT(pid_data + pid_start + index, count);
|
|
||||||
if (os <= index) {
|
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index),
|
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + index + count),
|
|
||||||
os * sizeof(T));
|
|
||||||
} else {
|
} else {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + count),
|
memmove((void*)(&(pid_data[pid_start + count])), (const void*)(&(pid_data[pid_start])), index * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
|
||||||
index * sizeof(T));
|
|
||||||
}
|
}
|
||||||
pid_start += count;
|
pid_start += count;
|
||||||
}
|
}
|
||||||
pid_size -= count;
|
pid_size -= count;
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1486,7 +1461,7 @@ public:
|
|||||||
piSwap<T*>(pid_data, other.pid_data);
|
piSwap<T*>(pid_data, other.pid_data);
|
||||||
piSwap<size_t>(pid_size, other.pid_size);
|
piSwap<size_t>(pid_size, other.pid_size);
|
||||||
piSwap<size_t>(pid_rsize, other.pid_rsize);
|
piSwap<size_t>(pid_rsize, other.pid_rsize);
|
||||||
piSwap<size_t>(pid_start, other.pid_start);
|
piSwap<ssize_t>(pid_start, other.pid_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Sorts the elements in non-descending order.
|
//! \~english Sorts the elements in non-descending order.
|
||||||
@@ -1528,11 +1503,16 @@ public:
|
|||||||
//! Complexity `O(N·log(N))`.
|
//! Complexity `O(N·log(N))`.
|
||||||
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
|
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
|
||||||
//! Для сравнения элементов используется функция сравнения `comp`.
|
//! Для сравнения элементов используется функция сравнения `comp`.
|
||||||
//! Функция сравнения, возвращает `true` если первый аргумент меньше
|
//! Функция сравнения, возвращает `true` если первый аргумент меньше второго.
|
||||||
//! второго. Сигнатура функции сравнения должна быть эквивалентна следующей: \code bool comp(const T &a, const T &b); \endcode Сигнатура
|
//! Сигнатура функции сравнения должна быть эквивалентна следующей:
|
||||||
//! не обязана содержать const &, однако, функция не может изменять переданные объекты. Функция обязана возвращать `false` для
|
//! \code
|
||||||
//! одинаковых элементов, иначе это приведёт к неопределённому поведению программы и ошибкам памяти. Для сортировки используется функция
|
//! bool comp(const T &a, const T &b);
|
||||||
//! [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). Сложность сортировки `O(N·log(N))`.
|
//! \endcode
|
||||||
|
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
|
||||||
|
//! Функция обязана возвращать `false` для одинаковых элементов,
|
||||||
|
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||||
|
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
|
||||||
|
//! Сложность сортировки `O(N·log(N))`.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIDeque<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
|
//! PIDeque<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
|
||||||
//! v.sort([](const int & a, const int & b){return a > b;});
|
//! v.sort([](const int & a, const int & b){return a > b;});
|
||||||
@@ -1562,7 +1542,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a reversed()
|
//! \~\sa \a reversed()
|
||||||
inline PIDeque<T> & reverse() {
|
inline PIDeque<T> & reverse() {
|
||||||
const size_t s2 = pid_size / 2;
|
size_t s2 = pid_size/2;
|
||||||
for (size_t i = 0; i < s2; ++i) {
|
for (size_t i = 0; i < s2; ++i) {
|
||||||
piSwap<T>(pid_data[pid_start+i], pid_data[pid_start+pid_size-i-1]);
|
piSwap<T>(pid_data[pid_start+i], pid_data[pid_start+pid_size-i-1]);
|
||||||
}
|
}
|
||||||
@@ -1592,12 +1572,10 @@ public:
|
|||||||
//! Если `add_size < 0`, то с конца массива удаляются элементы.
|
//! Если `add_size < 0`, то с конца массива удаляются элементы.
|
||||||
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
|
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
|
||||||
//! \~\sa \a resize()
|
//! \~\sa \a resize()
|
||||||
inline PIDeque<T> & enlarge(ssize_t add_size, const T & e = T()) {
|
inline PIDeque<T> & enlarge(llong pid_size) {
|
||||||
const ssize_t ns = size_s() + add_size;
|
llong ns = size_s() + pid_size;
|
||||||
if (ns <= 0)
|
if (ns <= 0) clear();
|
||||||
clear();
|
else resize(size_t(ns));
|
||||||
else
|
|
||||||
resize(size_t(ns), e);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1630,7 +1608,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||||
inline PIDeque<T> & removeAll(const T & e) {
|
inline PIDeque<T> & removeAll(const T & e) {
|
||||||
for (size_t i = 0; i < pid_size; ++i) {
|
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
|
||||||
if (pid_data[i + pid_start] == e) {
|
if (pid_data[i + pid_start] == e) {
|
||||||
remove(i);
|
remove(i);
|
||||||
--i;
|
--i;
|
||||||
@@ -1651,7 +1629,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
|
||||||
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
|
inline PIDeque<T> & removeWhere(std::function<bool(const T & e)> test) {
|
||||||
for (size_t i = 0; i < pid_size; ++i) {
|
for (ssize_t i = 0; i < ssize_t(pid_size); ++i) {
|
||||||
if (test(pid_data[i + pid_start])) {
|
if (test(pid_data[i + pid_start])) {
|
||||||
remove(i);
|
remove(i);
|
||||||
--i;
|
--i;
|
||||||
@@ -1715,8 +1693,7 @@ public:
|
|||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||||
//! \~\sa \a push_back()
|
//! \~\sa \a push_back()
|
||||||
inline PIDeque<T> & push_back(std::initializer_list<T> init_list) {
|
inline PIDeque<T> & push_back(std::initializer_list<T> init_list) {
|
||||||
if (init_list.size() == 0) return *this;
|
size_t ps = pid_size;
|
||||||
const size_t ps = pid_size;
|
|
||||||
alloc_forward(pid_size + init_list.size());
|
alloc_forward(pid_size + init_list.size());
|
||||||
newT(pid_data + pid_start + ps, init_list.begin(), init_list.size());
|
newT(pid_data + pid_start + ps, init_list.begin(), init_list.size());
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1729,14 +1706,13 @@ public:
|
|||||||
//! \~russian Перегруженая функция.
|
//! \~russian Перегруженая функция.
|
||||||
//! \~\sa \a push_back()
|
//! \~\sa \a push_back()
|
||||||
inline PIDeque<T> & push_back(const PIDeque<T> & v) {
|
inline PIDeque<T> & push_back(const PIDeque<T> & v) {
|
||||||
if (v.isEmpty()) return *this;
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (&v == this) {
|
if (&v == this) {
|
||||||
printf("error with PIDeque<%s>::append\n", __PIP_TYPENAME__(T));
|
printf("error with PIDeque<%s>::append\n", __PIP_TYPENAME__(T));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(&v != this);
|
assert(&v != this);
|
||||||
const size_t ps = pid_size;
|
size_t ps = pid_size;
|
||||||
alloc_forward(pid_size + v.pid_size);
|
alloc_forward(pid_size + v.pid_size);
|
||||||
newT(pid_data + ps + pid_start, v.pid_data + v.pid_start, v.pid_size);
|
newT(pid_data + ps + pid_start, v.pid_data + v.pid_start, v.pid_size);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1859,9 +1835,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
|
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
|
||||||
inline PIDeque<T> & push_front(const T & e) {
|
inline PIDeque<T> & push_front(const T & e) {
|
||||||
if (isEmpty()) return push_back(e);
|
insert(0, e);
|
||||||
alloc_backward(pid_size + 1, -1);
|
|
||||||
elementNew(pid_data + pid_start, e);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1872,9 +1846,7 @@ public:
|
|||||||
//! \~russian Перегруженая функция.
|
//! \~russian Перегруженая функция.
|
||||||
//! \~\sa \a push_front()
|
//! \~\sa \a push_front()
|
||||||
inline PIDeque<T> & push_front(T && e) {
|
inline PIDeque<T> & push_front(T && e) {
|
||||||
if (isEmpty()) return push_back(std::move(e));
|
insert(0, std::move(e));
|
||||||
alloc_backward(pid_size + 1, -1);
|
|
||||||
elementNew(pid_data + pid_start, std::move(e));
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1889,7 +1861,10 @@ public:
|
|||||||
//! piCout << v; // {4, 5, 1, 2, 3}
|
//! piCout << v; // {4, 5, 1, 2, 3}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a push_front()
|
//! \~\sa \a push_front()
|
||||||
inline PIDeque<T> & push_front(const PIDeque<T> & v) { return insert(0, v); }
|
inline PIDeque<T> & push_front(const PIDeque<T> & v) {
|
||||||
|
insert(0, v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Appends the given elements to the begin of the array.
|
//! \~english Appends the given elements to the begin of the array.
|
||||||
//! \~russian Добавляет элементы в начало массива.
|
//! \~russian Добавляет элементы в начало массива.
|
||||||
@@ -1901,7 +1876,10 @@ public:
|
|||||||
//! Добавляет элементы из
|
//! Добавляет элементы из
|
||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||||
//! \~\sa \a append()
|
//! \~\sa \a append()
|
||||||
inline PIDeque<T> & push_front(std::initializer_list<T> init_list) { return insert(0, init_list); }
|
inline PIDeque<T> & push_front(std::initializer_list<T> init_list) {
|
||||||
|
insert(0, init_list);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Appends the given element `e` to the begin of the array.
|
//! \~english Appends the given element `e` to the begin of the array.
|
||||||
//! \~russian Добавляет элемент `e` в начало массива.
|
//! \~russian Добавляет элемент `e` в начало массива.
|
||||||
@@ -1960,7 +1938,7 @@ public:
|
|||||||
//! Добавляет элементы из
|
//! Добавляет элементы из
|
||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||||
//! \~\sa \a append()
|
//! \~\sa \a append()
|
||||||
inline PIDeque<T> & prepend(std::initializer_list<T> init_list) { return push_front(init_list); }
|
inline PIDeque<T> & prepend(std::initializer_list<T> init_list) {return prepend(init_list);}
|
||||||
|
|
||||||
//! \~english Remove one element from the end of the array.
|
//! \~english Remove one element from the end of the array.
|
||||||
//! \~russian Удаляет один элемент с конца массива.
|
//! \~russian Удаляет один элемент с конца массива.
|
||||||
@@ -1977,8 +1955,7 @@ public:
|
|||||||
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
|
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
|
||||||
inline PIDeque<T> & pop_back() {
|
inline PIDeque<T> & pop_back() {
|
||||||
if (pid_size == 0) return *this;
|
if (pid_size == 0) return *this;
|
||||||
elementDelete(pid_data[pid_size + pid_start - 1]);
|
resize(pid_size - 1);
|
||||||
pid_size = pid_size - 1;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1999,9 +1976,7 @@ public:
|
|||||||
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
|
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
|
||||||
inline PIDeque<T> & pop_front() {
|
inline PIDeque<T> & pop_front() {
|
||||||
if (pid_size == 0) return *this;
|
if (pid_size == 0) return *this;
|
||||||
elementDelete(pid_data[pid_start]);
|
remove(0);
|
||||||
pid_start += 1;
|
|
||||||
pid_size -= 1;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2015,7 +1990,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
||||||
inline T take_back() {
|
inline T take_back() {
|
||||||
const T e(back());
|
T e(back());
|
||||||
pop_back();
|
pop_back();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -2030,7 +2005,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
||||||
inline T take_front() {
|
inline T take_front() {
|
||||||
const T e(front());
|
T e(front());
|
||||||
pop_front();
|
pop_front();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -2047,7 +2022,6 @@ public:
|
|||||||
template <typename ST>
|
template <typename ST>
|
||||||
inline PIDeque<ST> toType() const {
|
inline PIDeque<ST> toType() const {
|
||||||
PIDeque<ST> ret(pid_size);
|
PIDeque<ST> ret(pid_size);
|
||||||
ret.reserve(pid_size);
|
|
||||||
for (size_t i = 0; i < pid_size; ++i) {
|
for (size_t i = 0; i < pid_size; ++i) {
|
||||||
ret[i] = ST(pid_data[i + pid_start]);
|
ret[i] = ST(pid_data[i + pid_start]);
|
||||||
}
|
}
|
||||||
@@ -2055,9 +2029,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Returns a new array with all elements
|
//! \~english Returns a new array with all elements
|
||||||
//! that pass the test implemented by the provided function `bool test(const T & e)`.
|
//! that pass the test implemented by the provided function `test`.
|
||||||
//! \~russian Возвращает новый массив со всеми элементами,
|
//! \~russian Возвращает новый массив со всеми элементами,
|
||||||
//! прошедшими проверку, задаваемую в передаваемой функции `bool test(const T & e)`.
|
//! прошедшими проверку, задаваемую в передаваемой функции `test`.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIDeque<int> v{3, 2, 5, 2, 7};
|
//! PIDeque<int> v{3, 2, 5, 2, 7};
|
||||||
@@ -2073,39 +2047,6 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a filter() but with `index` parameter in `test`.
|
|
||||||
//! \~russian Аналогично \a filter() но с параметром индекса `index` в функции `test`.
|
|
||||||
//! \~\sa \a filter()
|
|
||||||
inline PIDeque<T> filterIndexed(std::function<bool(size_t index, const T & e)> test) const {
|
|
||||||
PIDeque<T> ret;
|
|
||||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
|
||||||
if (test(i - pid_start, pid_data[i])) ret << pid_data[i];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a filter() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a filter() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a filter()
|
|
||||||
inline PIDeque<T> filterReverse(std::function<bool(const T & e)> test) const {
|
|
||||||
PIDeque<T> ret;
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
if (test(pid_data[i])) ret << pid_data[i];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a filterReverse() but with `index` parameter in `test`.
|
|
||||||
//! \~russian Аналогично \a filterReverse() но с параметром индекса `index` в функции `test`.
|
|
||||||
//! \~\sa \a filterReverse()
|
|
||||||
inline PIDeque<T> filterReverseIndexed(std::function<bool(size_t index, const T & e)> test) const {
|
|
||||||
PIDeque<T> ret;
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
if (test(i - pid_start, pid_data[i])) ret << pid_data[i];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Execute function `void f(const T & e)` for every element in array.
|
//! \~english Execute function `void f(const T & e)` for every element in array.
|
||||||
//! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива.
|
//! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -2146,63 +2087,6 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a forEach() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a forEach() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\sa \a forEach()
|
|
||||||
inline void forEachIndexed(std::function<void(size_t index, const T & e)> f) const {
|
|
||||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
|
||||||
f(i - pid_start, pid_data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachIndexed(), but allows you to change the elements of the array.
|
|
||||||
//! \~russian Аналогично \a forEachIndexed(), но позволяет изменять элементы массива.
|
|
||||||
//! \~\sa \a forEach(), \a forEachIndexed()
|
|
||||||
inline PIDeque<T> & forEachIndexed(std::function<void(size_t index, T & e)> f) {
|
|
||||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
|
||||||
f(i - pid_start, pid_data[i]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEach() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a forEach() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a forEach()
|
|
||||||
inline void forEachReverse(std::function<void(const T & e)> f) const {
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
f(pid_data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachReverse(), but allows you to change the elements of the array.
|
|
||||||
//! \~russian Аналогично \a forEachReverse(), но позволяет изменять элементы массива.
|
|
||||||
//! \~\sa \a forEach(), \a forEachReverse()
|
|
||||||
inline PIDeque<T> & forEachReverse(std::function<void(T & e)> f) {
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
f(pid_data[i]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachIndexed() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a forEachIndexed() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a forEachIndexed(), \a forEachReverse(), \a forEach()
|
|
||||||
inline void forEachReverseIndexed(std::function<void(size_t index, const T & e)> f) const {
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
f(i - pid_start, pid_data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachReverseIndexed(), but allows you to change the elements of the array.
|
|
||||||
//! \~russian Аналогично \a forEachReverseIndexed(), но позволяет изменять элементы массива.
|
|
||||||
//! \~\sa \a forEachReverseIndexed(), \a forEachIndexed(), \a forEachReverse(), \a forEach()
|
|
||||||
inline PIDeque<T> & forEachReverseIndexed(std::function<void(size_t index, T & e)> f) {
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
f(i - pid_start, pid_data[i]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Сreates a new array populated with the results
|
//! \~english Сreates a new array populated with the results
|
||||||
//! of calling a provided function `ST f(const T & e)` on every element in the calling array.
|
//! of calling a provided function `ST f(const T & e)` on every element in the calling array.
|
||||||
//! \~russian Создаёт новый массив с результатом вызова указанной функции
|
//! \~russian Создаёт новый массив с результатом вызова указанной функции
|
||||||
@@ -2212,78 +2096,23 @@ public:
|
|||||||
//! once for each element in an array, in order,
|
//! once for each element in an array, in order,
|
||||||
//! and constructs a new array from the results.
|
//! and constructs a new array from the results.
|
||||||
//! \~russian Метод `map` вызывает переданную функцию `ST f(const T & e)`
|
//! \~russian Метод `map` вызывает переданную функцию `ST f(const T & e)`
|
||||||
//! один раз для каждого элемента в порядке их появления от начала к концу (слева на право)
|
//! один раз для каждого элемента в порядке их появления
|
||||||
//! и конструирует новый массив из результатов её вызова.
|
//! и конструирует новый массив из результатов её вызова.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIDeque<int> v{1, 2, 3};
|
//! PIDeque<int> v{1, 2, 3};
|
||||||
//! PIStringList sl = v.map<PIString>([](const int & i){return PIString::fromNumber(i);});
|
//! PIStringList sl = v.map<PIString>([](const int & i){return PIString::fromNumber(i);});
|
||||||
//! piCout << sl; // {"1", "2", "3"}
|
//! piCout << sl; {"1", "2", "3"}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a forEach(), \a reduce()
|
//! \~\sa \a forEach(), \a reduce()
|
||||||
template <typename ST>
|
template <typename ST>
|
||||||
inline PIDeque<ST> map(std::function<ST(const T & e)> f) const {
|
inline PIDeque<ST> map(std::function<ST(const T & e)> f) const {
|
||||||
PIDeque<ST> ret;
|
PIDeque<ST> ret; ret.reserve(pid_size);
|
||||||
ret.reserve(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) {
|
||||||
ret << f(pid_data[i]);
|
ret << f(pid_data[i]);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a map() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a map() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\code
|
|
||||||
//! PIDeque<int> v{1, 2, 3};
|
|
||||||
//! PIStringList sl = v.mapIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
|
|
||||||
//! piCout << sl; // {"0", "1", "2"}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a map()
|
|
||||||
template<typename ST>
|
|
||||||
inline PIDeque<ST> mapIndexed(std::function<ST(size_t index, const T & e)> f) const {
|
|
||||||
PIDeque<ST> ret;
|
|
||||||
ret.reserve(pid_size);
|
|
||||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
|
||||||
ret << f(i - pid_start, pid_data[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a map() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a map() но от конца до начала (справа на лево).
|
|
||||||
//! \~\code
|
|
||||||
//! PIDeque<int> v{1, 2, 3};
|
|
||||||
//! PIStringList sl = v.mapReverse<PIString>([](const int & i){return PIString::fromNumber(i);});
|
|
||||||
//! piCout << sl; // {"3", "2", "1"}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a map()
|
|
||||||
template<typename ST>
|
|
||||||
inline PIDeque<ST> mapReverse(std::function<ST(const T & e)> f) const {
|
|
||||||
PIDeque<ST> ret;
|
|
||||||
ret.reserve(pid_size);
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
ret << f(pid_data[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a mapReverse() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a mapReverse() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\code
|
|
||||||
//! PIDeque<int> v{1, 2, 3};
|
|
||||||
//! PIStringList sl = v.mapReverseIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
|
|
||||||
//! piCout << sl; // {"2", "1", "0"}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a mapReverse()
|
|
||||||
template<typename ST>
|
|
||||||
inline PIDeque<ST> mapReverseIndexed(std::function<ST(size_t index, const T & e)> f) const {
|
|
||||||
PIDeque<ST> ret;
|
|
||||||
ret.reserve(pid_size);
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
ret << f(size_t(i) - pid_start, pid_data[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Applies the function `ST f(const T & e, const ST & acc)`
|
//! \~english Applies the function `ST f(const T & e, const ST & acc)`
|
||||||
//! to each element of the array (from left to right), returns one value.
|
//! to each element of the array (from left to right), returns one value.
|
||||||
//! \~russian Применяет функцию `ST f(const T & e, const ST & acc)`
|
//! \~russian Применяет функцию `ST f(const T & e, const ST & acc)`
|
||||||
@@ -2304,7 +2133,7 @@ public:
|
|||||||
//! \param initial _optional_ Object used as the second argument
|
//! \param initial _optional_ Object used as the second argument
|
||||||
//! when the `f` function is first called.
|
//! when the `f` function is first called.
|
||||||
//! \~russian Метод reduce() выполняет функцию `f`
|
//! \~russian Метод reduce() выполняет функцию `f`
|
||||||
//! один раз для каждого элемента, присутствующего в массиве от начала к концу (слева на право).
|
//! один раз для каждого элемента, присутствующего в массиве.
|
||||||
//! Если при вызове reduce() передан аргумент `initial`,
|
//! Если при вызове reduce() передан аргумент `initial`,
|
||||||
//! то при первом вызове функции `f` значение `acc`
|
//! то при первом вызове функции `f` значение `acc`
|
||||||
//! будет равным значению `initial`.
|
//! будет равным значению `initial`.
|
||||||
@@ -2324,7 +2153,7 @@ public:
|
|||||||
//! int s = v.reduce<int>([](const int & e, const int & acc){return e + acc;});
|
//! int s = v.reduce<int>([](const int & e, const int & acc){return e + acc;});
|
||||||
//! piCout << s; // 15
|
//! piCout << s; // 15
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a reduceIndexed(), \a reduceReverse(), \a reduceReverseIndexed(), \a forEach(), \a map()
|
//! \~\sa \a forEach(), \a map()
|
||||||
template <typename ST>
|
template <typename ST>
|
||||||
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
||||||
ST ret(initial);
|
ST ret(initial);
|
||||||
@@ -2334,42 +2163,6 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a reduce() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\sa \a reduce()
|
|
||||||
template<typename ST>
|
|
||||||
inline ST reduceIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
|
||||||
ST ret(initial);
|
|
||||||
for (size_t i = pid_start; i < pid_start + pid_size; ++i) {
|
|
||||||
ret = f(i - pid_start, pid_data[i], ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a reduce() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a reduce() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a reduce()
|
|
||||||
template<typename ST>
|
|
||||||
inline ST reduceReverse(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
|
||||||
ST ret(initial);
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
ret = f(pid_data[i], ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a reduceReverse() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\sa \a reduceReverse()
|
|
||||||
template<typename ST>
|
|
||||||
inline ST reduceReverseIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
|
||||||
ST ret(initial);
|
|
||||||
for (ssize_t i = ssize_t(pid_start + pid_size) - 1; i >= ssize_t(pid_start); --i) {
|
|
||||||
ret = f(size_t(i) - pid_start, pid_data[i], ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
|
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
|
||||||
//! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
|
//! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -2398,7 +2191,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(rows*cols == pid_size);
|
assert(rows*cols == pid_size);
|
||||||
ret.expand(rows);
|
ret.resize(rows);
|
||||||
if (order == ReshapeByRow) {
|
if (order == ReshapeByRow) {
|
||||||
for (size_t r = 0; r < rows; r++) {
|
for (size_t r = 0; r < rows; r++) {
|
||||||
ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols);
|
ret[r] = PIDeque<T>(&(pid_data[r*cols]), cols);
|
||||||
@@ -2406,7 +2199,7 @@ public:
|
|||||||
}
|
}
|
||||||
if (order == ReshapeByColumn) {
|
if (order == ReshapeByColumn) {
|
||||||
for (size_t r = 0; r < rows; r++) {
|
for (size_t r = 0; r < rows; r++) {
|
||||||
ret[r].expand(cols);
|
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];
|
ret[r][c] = pid_data[c*rows + r];
|
||||||
}
|
}
|
||||||
@@ -2429,12 +2222,14 @@ public:
|
|||||||
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
|
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a map(), \a reduce(), \a reshape()
|
//! \~\sa \a map(), \a reduce(), \a reshape()
|
||||||
template<typename C, typename std::enable_if<std::is_same<T, PIDeque<C>>::value, int>::type = 0>
|
template<typename C, typename std::enable_if<
|
||||||
|
std::is_same<T, PIDeque<C>>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIDeque<C> flatten(ReshapeOrder order = ReshapeByRow) const {
|
inline PIDeque<C> flatten(ReshapeOrder order = ReshapeByRow) const {
|
||||||
PIDeque<C> ret;
|
PIDeque<C> ret;
|
||||||
if (isEmpty()) return ret;
|
if (isEmpty()) return ret;
|
||||||
const size_t rows = size();
|
size_t rows = size();
|
||||||
const size_t cols = at(0).size();
|
size_t cols = at(0).size();
|
||||||
ret.reserve(rows * cols);
|
ret.reserve(rows * cols);
|
||||||
if (order == ReshapeByRow) {
|
if (order == ReshapeByRow) {
|
||||||
for (size_t r = 0; r < rows; r++) {
|
for (size_t r = 0; r < rows; r++) {
|
||||||
@@ -2470,217 +2265,116 @@ public:
|
|||||||
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
|
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a map(), \a reduce(), \a reshape()
|
//! \~\sa \a map(), \a reduce(), \a reshape()
|
||||||
template<typename C, typename std::enable_if<std::is_same<T, PIDeque<C>>::value, int>::type = 0>
|
template<typename C, typename std::enable_if<
|
||||||
|
std::is_same<T, PIDeque<C>>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIDeque<PIDeque<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
|
inline PIDeque<PIDeque<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
|
||||||
PIDeque<C> fl = flatten<C>();
|
PIDeque<C> fl = flatten<C>();
|
||||||
return fl.reshape(rows, cols, order);
|
return fl.reshape(rows, cols, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Divides an array into a two-dimensional array using the separator `separator`.
|
|
||||||
//! \~russian Разделяет массив на двумерный массив с помощью разделителя`separator`.
|
|
||||||
//! \~\code
|
|
||||||
//! PIDeque<int> v{1, 2, 3, 99, 4, 5, 99, 6};
|
|
||||||
//! piCout << v.split(99); // {{1, 2, 3}, {4, 5}, {6}}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a splitBySize()
|
|
||||||
inline PIDeque<PIDeque<T>> split(const T & separator) const {
|
|
||||||
PIDeque<PIDeque<T>> ret;
|
|
||||||
if (isEmpty()) return ret;
|
|
||||||
size_t start = 0;
|
|
||||||
ssize_t ci = indexOf(separator, start);
|
|
||||||
while (ci >= 0) {
|
|
||||||
ret << PIDeque<T>(pid_data + pid_start + start, ci - start);
|
|
||||||
start = ci + 1;
|
|
||||||
ci = indexOf(separator, start);
|
|
||||||
}
|
|
||||||
if (start < pid_size) {
|
|
||||||
ret << PIDeque<T>(pid_data + pid_start + start, pid_size - start);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Divides an array into a two-dimensional array in chunks of no more than `sz`.
|
|
||||||
//! \~russian Разделяет массив на двумерный массив по кускам не более чем `sz`.
|
|
||||||
//! \~\sa \a split()
|
|
||||||
inline PIDeque<PIDeque<T>> splitBySize(size_t sz) const {
|
|
||||||
PIDeque<PIDeque<T>> ret;
|
|
||||||
if (isEmpty() || sz == 0) return ret;
|
|
||||||
const size_t ch = pid_size / sz;
|
|
||||||
for (size_t i = 0; i < ch; ++i) {
|
|
||||||
ret << PIDeque<T>(pid_data + pid_start + sz * i, sz);
|
|
||||||
}
|
|
||||||
const size_t t = ch * sz;
|
|
||||||
if (t < pid_size) {
|
|
||||||
ret << PIDeque<T>(pid_data + pid_start + t, pid_size - t);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \~english Cut sub-array of this array.
|
|
||||||
//! \~russian Вырезает подмассив, то есть кусок из текущего массива.
|
|
||||||
//! \~english
|
|
||||||
//! \param index - index of this array where sub-array starts
|
|
||||||
//! \param count - sub-array size
|
|
||||||
//! \~russian
|
|
||||||
//! \param index - индекс в текущем массиве, откуда начинётся подмассив
|
|
||||||
//! \param count - размер подмассива
|
|
||||||
//! \~\details
|
|
||||||
//! \~english
|
|
||||||
//! Index must be in range from `0` to `size()-1`.
|
|
||||||
//! If sub-array size more than this array size, than ends early.
|
|
||||||
//! \~russian
|
|
||||||
//! Индекс начала должен лежать в диапазоне от `0` до `size()-1`.
|
|
||||||
//! Если заданный размер подмассива превышает размер текущего массива,
|
|
||||||
//! то вернется подмассив меньшего размера (`size()-index-1`).
|
|
||||||
inline PIDeque<T> takeRange(size_t index, size_t count) {
|
|
||||||
PIDeque<T> ret;
|
|
||||||
if (index >= pid_size || count == 0) return ret;
|
|
||||||
if (index + count > pid_size) count = pid_size - index;
|
|
||||||
ret.alloc_forward(count);
|
|
||||||
memcpy(reinterpret_cast<void *>(ret.pid_data + ret.pid_start),
|
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + index),
|
|
||||||
count * sizeof(T));
|
|
||||||
|
|
||||||
const size_t os = pid_size - index - count;
|
|
||||||
if (os <= index) {
|
|
||||||
if (os > 0) {
|
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + index),
|
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start + index + count),
|
|
||||||
os * sizeof(T));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (index > 0) {
|
|
||||||
memmove(reinterpret_cast<void *>(pid_data + pid_start + count),
|
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
|
||||||
index * sizeof(T));
|
|
||||||
}
|
|
||||||
pid_start += count;
|
|
||||||
}
|
|
||||||
pid_size -= count;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void _reset() {
|
inline void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;}
|
||||||
pid_size = 0;
|
|
||||||
pid_rsize = 0;
|
|
||||||
pid_start = 0;
|
|
||||||
pid_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t asize(ssize_t s) {
|
inline size_t asize(ssize_t s) {
|
||||||
if (s <= 0) return 0;
|
if (s <= 0) return 0;
|
||||||
if (pid_rsize * 2 >= size_t(s) && pid_rsize < size_t(s)) {
|
if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) {
|
||||||
return pid_rsize * 2;
|
return pid_rsize + pid_rsize;
|
||||||
}
|
}
|
||||||
size_t t = _PIContainerConstants<T>::minCountPoT();
|
ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
|
||||||
s -= 1;
|
while (s_ >> t)
|
||||||
while (s >> t) {
|
|
||||||
++t;
|
++t;
|
||||||
}
|
|
||||||
return (1 << t);
|
return (1 << t);
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline void newT(T * dst, const T * src, size_t s) {
|
inline void newT(T * dst, const T * src, size_t s) {
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||||
for (size_t i = 0; i < s; ++i) {
|
for (size_t i = 0; i < s; ++i)
|
||||||
elementNew(dst + i, src[i]);
|
elementNew(dst + i, src[i]);
|
||||||
}
|
}
|
||||||
}
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
, int>::type = 0>
|
||||||
inline void newT(T * dst, const T * src, size_t s) {
|
inline void newT(T * dst, const T * src, size_t s) {
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||||
memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<const void *>(src), s * sizeof(T));
|
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline void deleteT(T * d, size_t sz) {
|
inline void deleteT(T * d, size_t sz) {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||||
if (d != nullptr) {
|
if ((uchar*)d != 0) {
|
||||||
for (size_t i = 0; i < sz; ++i) {
|
for (size_t i = 0; i < sz; ++i) {
|
||||||
elementDelete(d[i]);
|
elementDelete(d[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline void deleteT(T * d, size_t sz) {
|
inline void deleteT(T * d, size_t sz) {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
!std::is_trivially_copyable<T1>::value
|
||||||
inline void elementNew(T * to, const T & from) {
|
, int>::type = 0>
|
||||||
new (to) T(from);
|
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
||||||
}
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
!std::is_trivially_copyable<T1>::value
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
, int>::type = 0>
|
||||||
inline void elementNew(T * to, T && from) {
|
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
|
||||||
new (to) T(std::move(from));
|
template<typename T1 = T, typename std::enable_if<
|
||||||
}
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
inline void elementNew(T1 * to, const T & from) {(*to) = from;}
|
||||||
inline void elementNew(T1 * to, const T & from) {
|
template<typename T1 = T, typename std::enable_if<
|
||||||
(*to) = from;
|
std::is_trivially_copyable<T1>::value
|
||||||
}
|
, int>::type = 0>
|
||||||
|
inline void elementNew(T * to, T && from) {(*to) = std::move(from);}
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
inline void elementNew(T * to, T && from) {
|
!std::is_trivially_copyable<T1>::value
|
||||||
(*to) = std::move(from);
|
, int>::type = 0>
|
||||||
}
|
inline void elementDelete(T & from) {from.~T();}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
std::is_trivially_copyable<T1>::value
|
||||||
inline void elementDelete(T & from) {
|
, int>::type = 0>
|
||||||
from.~T();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
|
||||||
inline void elementDelete(T & from) {}
|
inline void elementDelete(T & from) {}
|
||||||
|
|
||||||
inline void dealloc() {
|
inline void dealloc() {
|
||||||
if (pid_data != nullptr) {
|
if ((uchar*)pid_data != 0) free((uchar*)pid_data);
|
||||||
free(reinterpret_cast<void *>(pid_data));
|
pid_data = 0;
|
||||||
pid_data = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inline void checkMove() {
|
inline void checkMove() {
|
||||||
if (pid_size >= 4) {
|
if (pid_size >= 4) {
|
||||||
if (pid_size < pid_rsize / 6) {
|
if (pid_size < pid_rsize / 6) {
|
||||||
if (pid_start < (pid_size * 2) || ssize_t(pid_start) > (ssize_t(pid_rsize) - (ssize_t(pid_size) * 2))) {
|
if (pid_start < ssize_t(pid_size + pid_size) || pid_start > (ssize_t(pid_rsize) - ssize_t(pid_size) - ssize_t(pid_size))) {
|
||||||
size_t ns = (pid_rsize - pid_size) / 2;
|
ssize_t ns = (pid_rsize - pid_size) / 2;
|
||||||
if (pid_start != ns) {
|
if (pid_start != ns) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + ns),
|
memmove((void*)(pid_data + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
|
||||||
pid_size * sizeof(T));
|
|
||||||
pid_start = ns;
|
pid_start = ns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const size_t ns = (pid_rsize - pid_size) / 2;
|
ssize_t ns = (pid_rsize - pid_size) / 2;
|
||||||
if (pid_start != ns) {
|
if (pid_start != ns) {
|
||||||
memmove(reinterpret_cast<void *>(pid_data + ns),
|
memmove((void*)(pid_data + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
|
||||||
reinterpret_cast<const void *>(pid_data + pid_start),
|
|
||||||
pid_size * sizeof(T));
|
|
||||||
pid_start = ns;
|
pid_start = ns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline void alloc_forward(size_t new_size) { // direction == true -> alloc forward
|
||||||
inline void alloc_forward(size_t new_size) {
|
|
||||||
if (pid_start + new_size <= pid_rsize) {
|
if (pid_start + new_size <= pid_rsize) {
|
||||||
pid_size = new_size;
|
pid_size = new_size;
|
||||||
if (pid_start > 0) checkMove();
|
checkMove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pid_size = new_size;
|
pid_size = new_size;
|
||||||
const size_t as = asize(pid_start + new_size);
|
size_t as = asize(pid_start + new_size);
|
||||||
if (as != pid_rsize) {
|
if (as != pid_rsize) {
|
||||||
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
|
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
|
||||||
T * p_d = reinterpret_cast<T *>(realloc(reinterpret_cast<void *>(pid_data), as * sizeof(T)));
|
T * p_d = (T*)(realloc((void*)(pid_data), as*sizeof(T)));
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!p_d) {
|
if (!p_d) {
|
||||||
printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
|
printf("error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
|
||||||
@@ -2691,15 +2385,19 @@ private:
|
|||||||
pid_rsize = as;
|
pid_rsize = as;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) { //alloc backward
|
||||||
inline void alloc_backward(size_t new_size, ssize_t start_offset = 0) {
|
size_t as;
|
||||||
const size_t as = ssize_t(pid_start) + start_offset < 0 ? asize(pid_rsize - start_offset) : pid_rsize;
|
if (pid_start + start_offset < 0) {
|
||||||
|
as = asize(pid_rsize - start_offset);
|
||||||
|
} else {
|
||||||
|
as = pid_rsize;
|
||||||
|
}
|
||||||
if (as > pid_rsize) {
|
if (as > pid_rsize) {
|
||||||
T * td = reinterpret_cast<T *>(malloc(as * sizeof(T)));
|
T * td = (T*)(malloc(as * sizeof(T)));
|
||||||
const size_t ns = pid_start + as - pid_rsize;
|
ssize_t ns = pid_start + as - pid_rsize;
|
||||||
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
|
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-pid_rsize))
|
||||||
if (pid_rsize > 0 && pid_data != 0) {
|
if (pid_rsize > 0 && pid_data != 0) {
|
||||||
memcpy(reinterpret_cast<void *>(td + ns), reinterpret_cast<const void *>(pid_data + pid_start), pid_size * sizeof(T));
|
memcpy((void*)(td + ns), (const void*)(pid_data + pid_start), pid_size * sizeof(T));
|
||||||
dealloc();
|
dealloc();
|
||||||
}
|
}
|
||||||
pid_data = td;
|
pid_data = td;
|
||||||
@@ -2711,28 +2409,9 @@ private:
|
|||||||
checkMove();
|
checkMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void expand(size_t new_size, const T & e = T()) {
|
T * pid_data;
|
||||||
const size_t os = pid_size;
|
size_t pid_size, pid_rsize;
|
||||||
alloc_forward(new_size);
|
ssize_t pid_start;
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
|
|
||||||
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
|
|
||||||
elementNew(pid_data + i, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void expand(size_t new_size, std::function<T(size_t i)> f) {
|
|
||||||
const size_t os = pid_size;
|
|
||||||
alloc_forward(new_size);
|
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
|
|
||||||
for (size_t i = os + pid_start; i < new_size + pid_start; ++i) {
|
|
||||||
elementNew(pid_data + i, f(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T * pid_data = nullptr;
|
|
||||||
size_t pid_size = 0;
|
|
||||||
size_t pid_rsize = 0;
|
|
||||||
size_t pid_start = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -2758,21 +2437,19 @@ inline std::ostream & operator<<(std::ostream & s, const PIDeque<T> & v) {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline PICout operator <<(PICout s, const PIDeque<T> & v) {
|
inline PICout operator <<(PICout s, const PIDeque<T> & v) {
|
||||||
s.space();
|
s.space();
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "{";
|
s << "{";
|
||||||
for (size_t i = 0; i < v.size(); ++i) {
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
s << v[i];
|
s << v[i];
|
||||||
if (i < v.size() - 1) s << ", ";
|
if (i < v.size() - 1) s << ", ";
|
||||||
}
|
}
|
||||||
s << "}";
|
s << "}";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {
|
inline void piSwap(PIDeque<T> & f, PIDeque<T> & s) {f.swap(s);}
|
||||||
f.swap(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PIDEQUE_H
|
#endif // PIDEQUE_H
|
||||||
|
|||||||
187
libs/main/containers/pimap.cpp
Normal file
187
libs/main/containers/pimap.cpp
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/** \class PIMap
|
||||||
|
* \brief Associative array
|
||||||
|
* \details This class used to store Key = Value array of any
|
||||||
|
* type of data. \a value() returns value for key and leave map
|
||||||
|
* unchaged in any case. \a operator [] create entry in map if
|
||||||
|
* there is no entry for given key. You can retrieve all
|
||||||
|
* keys by method \a keys() and all values by methos \a values().
|
||||||
|
* To iterate all entries use class PIMapIterator, or methods
|
||||||
|
* \a makeIterator() and \a makeReverseIterator().
|
||||||
|
|
||||||
|
* \fn PIMap::PIMap();
|
||||||
|
* \brief Contructs an empty map
|
||||||
|
|
||||||
|
* \fn PIMap::PIMap(const PIMap & other);
|
||||||
|
* \brief Contructs a copy of "other"
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::operator =(const PIMap & other);
|
||||||
|
* \brief Copy operator
|
||||||
|
|
||||||
|
* \fn PIMap::PIMap(const PIMap & other);
|
||||||
|
* \brief Contructs a copy of "other"
|
||||||
|
|
||||||
|
* \fn PIMapIterator PIMap::makeIterator() const
|
||||||
|
* \brief Returns PIMapIterator for this map
|
||||||
|
|
||||||
|
* \fn PIMapIterator PIMap::makeReverseIterator() const
|
||||||
|
* \brief Returns reverse PIMapIterator for this map
|
||||||
|
|
||||||
|
|
||||||
|
* \fn size_t PIMap::size() const
|
||||||
|
* \brief Returns entries count
|
||||||
|
|
||||||
|
* \fn int PIMap::size_s() const
|
||||||
|
* \brief Returns entries count
|
||||||
|
|
||||||
|
* \fn size_t PIMap::length() const
|
||||||
|
* \brief Returns entries count
|
||||||
|
|
||||||
|
* \fn bool PIMap::isEmpty() const
|
||||||
|
* \brief Returns if map is empty
|
||||||
|
|
||||||
|
|
||||||
|
* \fn T & PIMap::operator [](const Key & key)
|
||||||
|
* \brief Returns value for key "key". If there is no key in map, create one.
|
||||||
|
|
||||||
|
* \fn const T PIMap::operator [](const Key & key) const
|
||||||
|
* \brief Returns value for key "key". If there is no key in map, returns default T().
|
||||||
|
|
||||||
|
* \fn T & PIMap::at(const Key & key)
|
||||||
|
* \brief Equivalent to operator []
|
||||||
|
|
||||||
|
* \fn const T PIMap::at(const Key & key) const
|
||||||
|
* \brief Equivalent to operator []
|
||||||
|
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::operator <<(const PIMap & other)
|
||||||
|
* \brief Insert all etries of "other" to this map. Override existing values.
|
||||||
|
|
||||||
|
* \fn bool PIMap::operator ==(const PIMap & t) const
|
||||||
|
* \brief Compare operator
|
||||||
|
|
||||||
|
* \fn bool PIMap::operator !=(const PIMap & t) const
|
||||||
|
* \brief Compare operator
|
||||||
|
|
||||||
|
* \fn bool PIMap::contains(const Key & key) const
|
||||||
|
* \brief Returns "true" if map contains entry with key "key"
|
||||||
|
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::reserve(size_t new_size)
|
||||||
|
* \brief Reserve space for "new_size" entries
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::removeOne(const Key & key)
|
||||||
|
* \brief Remove entry with key "key"
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::remove(const Key & key)
|
||||||
|
* \brief Equivalent \a removeOne(key)
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::erase(const Key & key)
|
||||||
|
* \brief Equivalent \a removeOne(key)
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::clear()
|
||||||
|
* \brief Clear map
|
||||||
|
|
||||||
|
|
||||||
|
* \fn void PIMap::swap(PIMap & other)
|
||||||
|
* \brief Swap map with "other"
|
||||||
|
|
||||||
|
|
||||||
|
* \fn PIMap & PIMap::insert(const Key & key, const T & value)
|
||||||
|
* \brief Insert or rewrite entry with key "key" and value "value"
|
||||||
|
|
||||||
|
* \fn const T PIMap::value(const Key & key, const T & default = T())
|
||||||
|
* \brief Returns value for key "key". If there is no key in map, returns "default".
|
||||||
|
|
||||||
|
* \fn PIVector<T> PIMap::values() const
|
||||||
|
* \brief Returns all values as PIVector
|
||||||
|
|
||||||
|
* \fn Key PIMap::key(const T & value, const Key & default = Key()) const
|
||||||
|
* \brief Returns key for first founded value "value". If there is no such value in map, returns "default".
|
||||||
|
|
||||||
|
* \fn PIVector<Key> PIMap::keys() const
|
||||||
|
* \brief Returns all keys as PIVector
|
||||||
|
|
||||||
|
* */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** \class PIMapIterator
|
||||||
|
* \brief Helper class to iterate over PIMap
|
||||||
|
* \details This class used to access keys and values in PIMap.
|
||||||
|
* You can use constructor to create iterator, or use \a PIMap::makeIterator()
|
||||||
|
* and \a PIMap::makeReverseIterator() methods.
|
||||||
|
*
|
||||||
|
* First usage variant:
|
||||||
|
* \code
|
||||||
|
* PIMap<int, PIString> m;
|
||||||
|
* m[1] = "one";
|
||||||
|
* m[2] = "two";
|
||||||
|
* m[4] = "four";
|
||||||
|
*
|
||||||
|
* auto it = m.makeIterator();
|
||||||
|
* while (it.next()) {
|
||||||
|
* piCout << it.key() << it.value();
|
||||||
|
* }
|
||||||
|
* // 1 one
|
||||||
|
* // 2 two
|
||||||
|
* // 4 four
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Using hasNext():
|
||||||
|
* \code
|
||||||
|
* while (it.hasNext()) {
|
||||||
|
* it.next();
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Using constructor:
|
||||||
|
* \code
|
||||||
|
* PIMapIterator<int, PIString> it(m);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Write access:
|
||||||
|
* \code
|
||||||
|
* while (it.next()) {
|
||||||
|
* it.valueRef().append("_!");
|
||||||
|
* piCout << it.key() << it.value();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // 1 one_!
|
||||||
|
* // 2 two_!
|
||||||
|
* // 4 four_!
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* Reverse iterator:
|
||||||
|
* \code
|
||||||
|
* auto it = m.makeReverseIterator();
|
||||||
|
* while (it.next()) {
|
||||||
|
* piCout << it.key() << it.value();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // 4 four
|
||||||
|
* // 2 two
|
||||||
|
* // 1 one
|
||||||
|
* \endcode
|
||||||
|
|
||||||
|
* \fn PIMapIterator(const PIMap & map, bool reverse = false)
|
||||||
|
* \brief Contructs iterator for "map". Current position is invalid.
|
||||||
|
|
||||||
|
* \fn const Key & PIMapIterator::key() const
|
||||||
|
* \brief Returns current entry key
|
||||||
|
|
||||||
|
* \fn const T & PIMapIterator::value() const
|
||||||
|
* \brief Returns current entry value
|
||||||
|
|
||||||
|
* \fn T & PIMapIterator::valueRef() const
|
||||||
|
* \brief Returns reference to current entry value
|
||||||
|
|
||||||
|
* \fn bool PIMapIterator::hasNext()
|
||||||
|
* \brief Returns if iterator can jump to next entry
|
||||||
|
|
||||||
|
* \fn bool PIMapIterator::next()
|
||||||
|
* \brief Jump to next entry and return if new position is valid.
|
||||||
|
|
||||||
|
* \fn void PIMapIterator::reset()
|
||||||
|
* \brief Reset iterator to initial position.
|
||||||
|
|
||||||
|
* */
|
||||||
@@ -1,17 +1,8 @@
|
|||||||
//! \addtogroup Containers
|
/*! \file pimap.h
|
||||||
//! \{
|
* \brief Associative array with custom types of key and value
|
||||||
//! \file pimap.h
|
*
|
||||||
//! \brief
|
* This file declares PIMap
|
||||||
//! \~english Declares \a PIMap
|
*/
|
||||||
//! \~russian Объявление \a PIMap
|
|
||||||
//! \~\authors
|
|
||||||
//! \~english
|
|
||||||
//! Ivan Pelipenko peri4ko@yandex.ru;
|
|
||||||
//! Andrey Bychkov work.a.b@yandex.ru;
|
|
||||||
//! \~russian
|
|
||||||
//! Иван Пелипенко peri4ko@yandex.ru;
|
|
||||||
//! Андрей Бычков work.a.b@yandex.ru;
|
|
||||||
//! \~\}
|
|
||||||
/*
|
/*
|
||||||
PIP - Platform Independent Primitives
|
PIP - Platform Independent Primitives
|
||||||
Associative array with custom types of key and value
|
Associative array with custom types of key and value
|
||||||
@@ -34,129 +25,57 @@
|
|||||||
#ifndef PIMAP_H
|
#ifndef PIMAP_H
|
||||||
#define PIMAP_H
|
#define PIMAP_H
|
||||||
|
|
||||||
|
#include "pivector.h"
|
||||||
#include "pideque.h"
|
#include "pideque.h"
|
||||||
#include "pipair.h"
|
#include "pipair.h"
|
||||||
#include "pivector.h"
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Key, typename T>
|
|
||||||
class PIMapIteratorConst;
|
|
||||||
template<typename Key, typename T>
|
|
||||||
class PIMapIteratorConstReverse;
|
|
||||||
template <typename Key, typename T>
|
template <typename Key, typename T>
|
||||||
class PIMapIterator;
|
class PIMapIterator;
|
||||||
template<typename Key, typename T>
|
|
||||||
class PIMapIteratorReverse;
|
|
||||||
|
|
||||||
|
|
||||||
//! \addtogroup Containers
|
|
||||||
//! \{
|
|
||||||
//! \class PIMap
|
|
||||||
//! \brief
|
|
||||||
//! \~english Associative array.
|
|
||||||
//! \~russian Словарь.
|
|
||||||
//! \~\}
|
|
||||||
//! \details
|
|
||||||
//! \~english
|
|
||||||
//! A collection of key/value pairs, from which you retrieve a value using its associated key.
|
|
||||||
//! There is a finite number of keys in the map, and each key has exactly one value associated with it.
|
|
||||||
//! \a value() returns value for key and leave map
|
|
||||||
//! unchaged in any case. \a operator [] create entry in map if
|
|
||||||
//! there is no entry for given key. You can retrieve all
|
|
||||||
//! keys by method \a keys() and all values by methos \a values().
|
|
||||||
//! To iterate all entries use class PIMapIterator, or methods
|
|
||||||
//! \a makeIterator() and \a makeReverseIterator().
|
|
||||||
//! A key in the Map may only occur once.
|
|
||||||
//! \~russian
|
|
||||||
//! Словари, в принципе, похожи на обычные, используемые в повседневной жизни.
|
|
||||||
//! Они хранят элементы одного и того же типа, индексируемые ключевыми значениями.
|
|
||||||
//! Достоинство словаря в том, что он позволяет быстро получать значение,
|
|
||||||
//! ассоциированное с заданным ключом.
|
|
||||||
//! Ключи должны быть уникальными.
|
|
||||||
//! Элемент
|
|
||||||
//! В контейнеры этого типа заносятся элементы вместе с ключами,
|
|
||||||
//! по которым их можно найти, которыми могут выступать значения любого типа.
|
|
||||||
//! \a operator [] позволяет получить доступ к элементу по ключу,
|
|
||||||
//! и если такого эелемента не было, то он будет создан.
|
|
||||||
template <typename Key, typename T>
|
template <typename Key, typename T>
|
||||||
class PIMap {
|
class PIMap {
|
||||||
template<typename Key1, typename T1>
|
template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIMap<Key1, T1> & v);
|
||||||
friend class PIMapIteratorConst;
|
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIMap<Key1, T1> & v);
|
||||||
template<typename Key1, typename T1>
|
template <typename Key1, typename T1> friend class PIMapIterator;
|
||||||
friend class PIMapIteratorConstReverse;
|
|
||||||
template<typename Key1, typename T1>
|
|
||||||
friend class PIMapIterator;
|
|
||||||
template<typename Key1, typename T1>
|
|
||||||
friend class PIMapIteratorReverse;
|
|
||||||
template<typename P, typename Key1, typename T1>
|
|
||||||
friend PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIMap<Key1, T1> & v);
|
|
||||||
template<typename P, typename Key1, typename T1>
|
|
||||||
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIMap<Key1, T1> & v);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T mapped_type;
|
PIMap() {}
|
||||||
typedef Key key_type;
|
PIMap(const PIMap<Key, T> & other) {*this = other;}
|
||||||
typedef PIPair<Key, T> value_type;
|
PIMap(PIMap<Key, T> && other) : pim_content(std::move(other.pim_content)) {}
|
||||||
|
PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
|
||||||
//! \~english Constructs an empty map.
|
for (auto i: init_list)
|
||||||
//! \~russian Создает пустой словарь.
|
|
||||||
inline PIMap() {}
|
|
||||||
|
|
||||||
//! \~english Copy constructor.
|
|
||||||
//! \~russian Копирующий конструктор.
|
|
||||||
inline PIMap(const PIMap<Key, T> & other): pim_content(other.pim_content), pim_index(other.pim_index) {}
|
|
||||||
|
|
||||||
//! \~english Move constructor.
|
|
||||||
//! \~russian Перемещающий конструктор.
|
|
||||||
inline PIMap(PIMap<Key, T> && other): pim_content(std::move(other.pim_content)), pim_index(std::move(other.pim_index)) {}
|
|
||||||
|
|
||||||
//! \~english Contructs map from
|
|
||||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
|
||||||
//! \~russian Создает словарь из
|
|
||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
|
||||||
//! \~\details
|
|
||||||
//! \~\code
|
|
||||||
//! PIMap <int, PIString> m{{1, "a"}, {2, "b"}};
|
|
||||||
//! piCout << m; // {1: a, 2: b}
|
|
||||||
//! \endcode
|
|
||||||
inline PIMap(std::initializer_list<std::pair<Key, T>> init_list) {
|
|
||||||
for (auto i: init_list) {
|
|
||||||
insert(std::get<0>(i), std::get<1>(i));
|
insert(std::get<0>(i), std::get<1>(i));
|
||||||
}
|
}
|
||||||
}
|
virtual ~PIMap() {;}
|
||||||
|
|
||||||
//! \~english Assign operator.
|
PIMap<Key, T> & operator =(const PIMap<Key, T> & other) {
|
||||||
//! \~russian Оператор присваивания.
|
|
||||||
inline PIMap<Key, T> & operator=(const PIMap<Key, T> & other) {
|
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
clear();
|
clear();
|
||||||
pim_content = other.pim_content;
|
pim_content = other.pim_content;
|
||||||
pim_index = other.pim_index;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Assign move operator.
|
PIMap<Key, T> & operator =(PIMap<Key, T> && other) {
|
||||||
//! \~russian Оператор перемещающего присваивания.
|
|
||||||
inline PIMap<Key, T> & operator=(PIMap<Key, T> && other) {
|
|
||||||
swap(other);
|
swap(other);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef T mapped_type;
|
||||||
|
typedef Key key_type;
|
||||||
|
typedef PIPair<Key, T> value_type;
|
||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
friend class PIMap<Key, T>;
|
friend class PIMap<Key, T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIMap<Key, T> * parent;
|
const PIMap<Key, T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
iterator(): parent(nullptr), pos(0) {}
|
iterator(): parent(0), pos(0) {}
|
||||||
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
|
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
|
||||||
T & value() {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
|
T & value() {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
|
||||||
inline PIPair<Key, T> operator*() const {
|
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));}
|
||||||
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 ++() {++pos;}
|
||||||
void operator ++(int) {++pos;}
|
void operator ++(int) {++pos;}
|
||||||
void operator --() {--pos;}
|
void operator --() {--pos;}
|
||||||
@@ -167,19 +86,15 @@ public:
|
|||||||
|
|
||||||
class reverse_iterator {
|
class reverse_iterator {
|
||||||
friend class PIMap<Key, T>;
|
friend class PIMap<Key, T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
reverse_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
reverse_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIMap<Key, T> * parent;
|
const PIMap<Key, T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
reverse_iterator(): parent(nullptr), pos(0) {}
|
reverse_iterator(): parent(0), pos(0) {}
|
||||||
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
|
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);}
|
T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
|
||||||
inline PIPair<Key, T> operator*() const {
|
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));}
|
||||||
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 ++() {--pos;}
|
||||||
void operator ++(int) {--pos;}
|
void operator ++(int) {--pos;}
|
||||||
void operator --() {++pos;}
|
void operator --() {++pos;}
|
||||||
@@ -190,15 +105,14 @@ public:
|
|||||||
|
|
||||||
class const_iterator {
|
class const_iterator {
|
||||||
friend class PIMap<Key, T>;
|
friend class PIMap<Key, T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
const_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIMap<Key, T> * parent;
|
const PIMap<Key, T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const_iterator(): parent(nullptr), pos(0) {}
|
const_iterator(): parent(0), pos(0) {}
|
||||||
const value_type operator *() const {return parent->_pair(pos);}
|
const value_type operator *() const {return parent->_pair(pos);}
|
||||||
|
const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;}
|
||||||
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
|
const Key & key() const {return const_cast<PIMap<Key, T> * >(parent)->_key(pos);}
|
||||||
const T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
|
const T & value() const {return const_cast<PIMap<Key, T> * >(parent)->_value(pos);}
|
||||||
void operator ++() {++pos;}
|
void operator ++() {++pos;}
|
||||||
@@ -207,152 +121,64 @@ public:
|
|||||||
void operator --(int) {--pos;}
|
void operator --(int) {--pos;}
|
||||||
bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
||||||
bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
||||||
|
mutable value_type cval;
|
||||||
};
|
};
|
||||||
|
|
||||||
class const_reverse_iterator {
|
class const_reverse_iterator {
|
||||||
friend class PIMap<Key, T>;
|
friend class PIMap<Key, T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const_reverse_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
const_reverse_iterator(const PIMap<Key, T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIMap<Key, T> * parent;
|
const PIMap<Key, T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const_reverse_iterator(): parent(nullptr), pos(0) {}
|
const_reverse_iterator(): parent(0), pos(0) {}
|
||||||
const value_type operator *() const {return parent->_pair(pos);}
|
const value_type operator *() const {return parent->_pair(pos);}
|
||||||
|
const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;}
|
||||||
void operator ++() {--pos;}
|
void operator ++() {--pos;}
|
||||||
void operator ++(int) {--pos;}
|
void operator ++(int) {--pos;}
|
||||||
void operator --() {++pos;}
|
void operator --() {++pos;}
|
||||||
void operator --(int) {++pos;}
|
void operator --(int) {++pos;}
|
||||||
bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
||||||
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
||||||
|
mutable value_type cval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
iterator begin() {return iterator(this, 0);}
|
||||||
|
iterator end() {return iterator(this, size());}
|
||||||
|
const_iterator begin() const {return const_iterator(this, 0);}
|
||||||
|
const_iterator end() const {return const_iterator(this, size());}
|
||||||
|
const_iterator constBegin() const {return const_iterator(this, 0);}
|
||||||
|
const_iterator constEnd() const {return const_iterator(this, size());}
|
||||||
|
reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);}
|
||||||
|
reverse_iterator rend() {return reverse_iterator(this, -1);}
|
||||||
|
const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);}
|
||||||
|
const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);}
|
||||||
|
const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);}
|
||||||
|
const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);}
|
||||||
|
|
||||||
//! \~english Iterator to the first element.
|
PIMapIterator<Key, T> makeIterator() const {return PIMapIterator<Key, T>(*this);}
|
||||||
//! \~russian Итератор на первый элемент.
|
PIMapIterator<Key, T> makeReverseIterator() const {return PIMapIterator<Key, T>(*this, true);}
|
||||||
inline iterator begin() { return iterator(this, 0); }
|
|
||||||
|
|
||||||
//! \~english Iterator to the element following the last element.
|
size_t size() const {return pim_content.size();}
|
||||||
//! \~russian Итератор на элемент, следующий за последним элементом.
|
int size_s() const {return pim_content.size_s();}
|
||||||
inline iterator end() { return iterator(this, size()); }
|
size_t length() const {return pim_content.size();}
|
||||||
|
bool isEmpty() const {return (pim_content.size() == 0);}
|
||||||
|
|
||||||
inline const_iterator begin() const { return const_iterator(this, 0); }
|
T & operator [](const Key & key) {
|
||||||
inline const_iterator end() const { return const_iterator(this, size()); }
|
|
||||||
|
|
||||||
//! \~english Returns a reverse iterator to the first element of the reversed array.
|
|
||||||
//! \~russian Обратный итератор на первый элемент.
|
|
||||||
inline reverse_iterator rbegin() { return reverse_iterator(this, size() - 1); }
|
|
||||||
|
|
||||||
//! \~english Returns a reverse iterator to the element.
|
|
||||||
//! following the last element of the reversed array.
|
|
||||||
//! \~russian Обратный итератор на элемент,
|
|
||||||
//! следующий за последним элементом.
|
|
||||||
inline reverse_iterator rend() { return reverse_iterator(this, -1); }
|
|
||||||
|
|
||||||
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(this, size() - 1); }
|
|
||||||
inline const_reverse_iterator rend() const { return const_reverse_iterator(this, -1); }
|
|
||||||
|
|
||||||
//! \relatesalso PIMapIteratorConst
|
|
||||||
inline PIMapIteratorConst<Key, T> makeIterator() const { return PIMapIteratorConst<Key, T>(*this); }
|
|
||||||
|
|
||||||
//! \relatesalso PIMapIterator
|
|
||||||
inline PIMapIterator<Key, T> makeIterator() { return PIMapIterator<Key, T>(*this); }
|
|
||||||
|
|
||||||
//! \relatesalso PIMapIteratorConstReverse
|
|
||||||
inline PIMapIteratorConstReverse<Key, T> makeReverseIterator() const { return PIMapIteratorConstReverse<Key, T>(*this); }
|
|
||||||
|
|
||||||
//! \relatesalso PIMapIteratorReverse
|
|
||||||
inline PIMapIteratorReverse<Key, T> makeReverseIterator() { return PIMapIteratorReverse<Key, T>(*this); }
|
|
||||||
|
|
||||||
//! \~english Number of elements in the container.
|
|
||||||
//! \~russian Количество элементов массива.
|
|
||||||
//! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
|
||||||
inline size_t size() const { return pim_content.size(); }
|
|
||||||
|
|
||||||
//! \~english Number of elements in the container as signed value.
|
|
||||||
//! \~russian Количество элементов массива в виде знакового числа.
|
|
||||||
//! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
|
||||||
inline int size_s() const { return pim_content.size_s(); }
|
|
||||||
|
|
||||||
//! \~english Same as \a size().
|
|
||||||
//! \~russian Синоним \a size().
|
|
||||||
//! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
|
||||||
inline size_t length() const { return pim_content.size(); }
|
|
||||||
|
|
||||||
//! \~english Checks if the container has no elements.
|
|
||||||
//! \~russian Проверяет пуст ли массив.
|
|
||||||
//! \~\return
|
|
||||||
//! \~english **true** if the container is empty, **false** otherwise
|
|
||||||
//! \~russian **true** если массив пуст, **false** иначе.
|
|
||||||
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
|
||||||
inline bool isEmpty() const { return (pim_content.size() == 0); }
|
|
||||||
|
|
||||||
//! \~english Checks if the container has elements.
|
|
||||||
//! \~russian Проверяет не пуст ли массив.
|
|
||||||
//! \~\return
|
|
||||||
//! \~english **true** if the container is not empty, **false** otherwise
|
|
||||||
//! \~russian **true** если массив не пуст, **false** иначе.
|
|
||||||
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
|
||||||
inline bool isNotEmpty() const { return (pim_content.size() > 0); }
|
|
||||||
|
|
||||||
|
|
||||||
//! \~english Full access to element key `key`.
|
|
||||||
//! \~russian Полный доступ к элементу по ключу `key`.
|
|
||||||
//! \~\details
|
|
||||||
//! \~english If the map contains no item with key `key`,
|
|
||||||
//! the function inserts a default-constructed value into the map with key `key`,
|
|
||||||
//! and returns a reference to it.
|
|
||||||
//! \~russian Если элемента с таким ключом `key` не существует,
|
|
||||||
//! то он будет создан конструктором по умолчанию и добавлен в массив
|
|
||||||
//! по ключу `key`, а затем возвращена ссылка на этот новый элемент.
|
|
||||||
//! \~\code
|
|
||||||
//! PIMap <PIString, int> m;
|
|
||||||
//! m["огурец"] = 500;
|
|
||||||
//! piCout << m; // {огурец: 500}
|
|
||||||
//! m["лук"] = 25;
|
|
||||||
//! piCout << m; // {огурец: 500, лук: 25}
|
|
||||||
//! m["огурец"] = 350;
|
|
||||||
//! piCout << m; // {огурец: 350, лук: 25}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a insert(), \a value(), \a key()
|
|
||||||
inline T & operator[](const Key & key) {
|
|
||||||
bool f(false);
|
bool f(false);
|
||||||
const ssize_t i = _find(key, f);
|
ssize_t i = _find(key, f);
|
||||||
if (f) return _value(i);
|
if (!f) pim_content.insert(i, PIPair<Key, T>(key, T()));
|
||||||
pim_content.push_back(T());
|
return pim_content[i].second;
|
||||||
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
|
||||||
return pim_content.back();
|
|
||||||
}
|
}
|
||||||
|
const T operator [](const Key & key) const {
|
||||||
//! \~english Read only access to element by `key`.
|
|
||||||
//! \~russian Доступ исключительно на чтение к элементу по ключу `key`.
|
|
||||||
//! \~\note
|
|
||||||
//! \~english Element with key `key` must exists,
|
|
||||||
//! otherwise it will lead to undefined program behavior and memory errors.
|
|
||||||
//! \~russian Элемент по ключу `key` должен существовать,
|
|
||||||
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
|
||||||
//! \~\sa \a operator[](), \a value(), \a key()
|
|
||||||
inline const T & at(const Key & key) const {
|
|
||||||
bool f(false);
|
bool f(false);
|
||||||
const ssize_t i = _find(key, f);
|
ssize_t i = _find(key, f);
|
||||||
return _value(i);
|
if (f) return pim_content[i].second;
|
||||||
|
return T();
|
||||||
}
|
}
|
||||||
|
const T at(const Key & key) const {return (*this)[key];}
|
||||||
|
|
||||||
//! \~english Remove element with key `key` from the array and return it.
|
PIMap<Key, T> & operator <<(const PIMap<Key, T> & other) {
|
||||||
//! \~russian Удаляет элемент с ключом `key` из массива и возвращает его.
|
|
||||||
inline T take(const Key & key, const T & default_ = T()) {
|
|
||||||
bool f(false);
|
|
||||||
const ssize_t i = _find(key, f);
|
|
||||||
if (!f) return default_;
|
|
||||||
const T ret = _value(i);
|
|
||||||
_remove(i);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Inserts all elements in array `other` to this array with overwrite.
|
|
||||||
//! \~russian Вставляет все элементы `other` этот массив с перезаписью.
|
|
||||||
inline PIMap<Key, T> & operator<<(const PIMap<Key, T> & other) {
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (&other == this) {
|
if (&other == this) {
|
||||||
printf("error with PIMap<%s, %s>::<<\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
|
printf("error with PIMap<%s, %s>::<<\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
|
||||||
@@ -360,651 +186,205 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
assert(&other != this);
|
assert(&other != this);
|
||||||
if (other.isEmpty()) return *this;
|
if (other.isEmpty()) return *this;
|
||||||
if (other.size() == 1) {
|
// if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;}
|
||||||
insert(other.pim_index[0].key, other.pim_content[0]);
|
// if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;}
|
||||||
return *this;
|
for (int i = 0; i < other.pim_content.size_s(); ++i)
|
||||||
}
|
insert(other.pim_content[i].first, other.pim_content[i].second);
|
||||||
if (other.size() == 2) {
|
|
||||||
insert(other.pim_index[0].key, other.pim_content[0]);
|
|
||||||
insert(other.pim_index[1].key, other.pim_content[1]);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < other.pim_index.size_s(); ++i) {
|
|
||||||
insert(other.pim_index[i].key, other.pim_content[other.pim_index[i].index]);
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Compare operator with array `m`.
|
bool operator ==(const PIMap<Key, T> & t) const {return (pim_content == t.pim_content);}
|
||||||
//! \~russian Оператор сравнения с массивом `m`.
|
bool operator !=(const PIMap<Key, T> & t) const {return (pim_content != t.pim_content);}
|
||||||
inline bool operator==(const PIMap<Key, T> & m) const { return (pim_content == m.pim_content && pim_index == m.pim_index); }
|
bool contains(const Key & key) const {bool f(false); _find(key, f); return f;}
|
||||||
|
|
||||||
//! \~english Compare operator with array `m`.
|
PIMap<Key, T> & reserve(size_t new_size) {pim_content.reserve(new_size);return *this;}
|
||||||
//! \~russian Оператор сравнения с массивом `m`.
|
|
||||||
inline bool operator!=(const PIMap<Key, T> & m) const { return (pim_content != m.pim_content || pim_index != m.pim_index); }
|
|
||||||
|
|
||||||
//! \~english Tests if element with key `key` exists in the array.
|
PIMap<Key, T> & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;}
|
||||||
//! \~russian Проверяет наличие элемента с ключом `key` в массиве.
|
PIMap<Key, T> & remove(const Key & key) {return removeOne(key);}
|
||||||
inline bool contains(const Key & key) const {
|
PIMap<Key, T> & erase(const Key & key) {return removeOne(key);}
|
||||||
bool f(false);
|
PIMap<Key, T> & clear() {pim_content.clear(); return *this;}
|
||||||
_find(key, f);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Tests if element with value `value` exists in the array.
|
void swap(PIMap<Key, T> & other) {
|
||||||
//! \~russian Проверяет наличие элемента со значением `value` в массиве.
|
|
||||||
inline bool containsValue(const T & value) const { return pim_content.contains(value); }
|
|
||||||
|
|
||||||
//! \~english Attempts to allocate memory for at least `new_size` elements.
|
|
||||||
//! \~russian Резервируется память под как минимум `new_size` элементов.
|
|
||||||
inline PIMap<Key, T> & reserve(size_t new_size) {
|
|
||||||
pim_content.reserve(new_size);
|
|
||||||
pim_index.reserve(new_size);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Remove element with key `key` from the array.
|
|
||||||
//! \~russian Удаляет элемент с ключом `key` из массива.
|
|
||||||
inline PIMap<Key, T> & remove(const Key & key) {
|
|
||||||
bool f(false);
|
|
||||||
const ssize_t i = _find(key, f);
|
|
||||||
if (f) _remove(i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \~english Remove all elements in the array
|
|
||||||
//! passes the test implemented by the provided function `test`.
|
|
||||||
//! \~russian Удаляет все элементы, удовлетворяющие условию,
|
|
||||||
//! заданному в передаваемой функции `test`.
|
|
||||||
inline PIMap<Key, T> & removeWhere(std::function<bool(const Key & key, const T & value)> test) {
|
|
||||||
for (int i = 0; i < pim_index.size_s(); ++i) {
|
|
||||||
const auto & mi(pim_index[i]);
|
|
||||||
if (test(mi.key, pim_content[mi.index])) {
|
|
||||||
_remove(i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a remove().
|
|
||||||
//! \~russian Синоним функции \a remove().
|
|
||||||
inline PIMap<Key, T> & erase(const Key & key) { return remove(key); }
|
|
||||||
|
|
||||||
|
|
||||||
//! \~english Clear array, remove all elements.
|
|
||||||
//! \~russian Очищает массив, удаляет все элементы.
|
|
||||||
//! \~\details
|
|
||||||
//! \~\note
|
|
||||||
//! \~english Reserved memory will not be released.
|
|
||||||
//! \~russian Зарезервированная память не освободится.
|
|
||||||
//! \~\sa \a resize()
|
|
||||||
inline PIMap<Key, T> & clear() {
|
|
||||||
pim_content.clear();
|
|
||||||
pim_index.clear();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Swaps array `v` other with this array.
|
|
||||||
//! \~russian Меняет местами массив `v` с этим массивом.
|
|
||||||
//! \~\details
|
|
||||||
//! \~english This operation is very fast and never fails.
|
|
||||||
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
|
|
||||||
inline void swap(PIMap<Key, T> & other) {
|
|
||||||
pim_content.swap(other.pim_content);
|
pim_content.swap(other.pim_content);
|
||||||
pim_index.swap(other.pim_index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Inserts value `value` with key `key` in the array.
|
PIMap<Key, T> & insert(const Key & key, const T & value) {
|
||||||
//! \~russian Вставляет значение `value` с ключом `key` в массив.
|
|
||||||
//! \~\details
|
|
||||||
//! \~english If an element with the key `key` already exists, it will be overwritten with the value `value`.
|
|
||||||
//! \~russian Если элемент с ключом `key` уже существует, то он будет перезаписан на значение `value`.
|
|
||||||
inline PIMap<Key, T> & insert(const Key & key, const T & value) {
|
|
||||||
bool f(false);
|
bool f(false);
|
||||||
const ssize_t i = _find(key, f);
|
ssize_t i = _find(key, f);
|
||||||
|
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
|
||||||
if (f) {
|
if (f) {
|
||||||
_value(i) = value;
|
pim_content[i].second = value;
|
||||||
} else {
|
} else {
|
||||||
pim_content.push_back(value);
|
pim_content.insert(i, PIPair<Key, T>(key, value));
|
||||||
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
PIMap<Key, T> & insert(const Key & key, T && value) {
|
||||||
inline PIMap<Key, T> & insert(const Key & key, T && value) {
|
|
||||||
bool f(false);
|
bool f(false);
|
||||||
const ssize_t i = _find(key, f);
|
ssize_t i = _find(key, f);
|
||||||
|
//piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value;
|
||||||
if (f) {
|
if (f) {
|
||||||
_value(i) = std::move(value);
|
pim_content[i].second = std::move(value);
|
||||||
} else {
|
} else {
|
||||||
pim_content.push_back(std::move(value));
|
// pim_content.push_back(std::move(value));
|
||||||
pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
// pim_index.insert(i, MapIndex(key, pim_content.size() - 1));
|
||||||
|
pim_content.insert(i, PIPair<Key, T>(key, std::move(value)));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
const T value(const Key & key, const T & default_ = T()) const {
|
||||||
//! \~english Inserts value `pair` in the array.
|
|
||||||
//! \~russian Вставляет пару `pair` в массив.
|
|
||||||
//! \~\details
|
|
||||||
//! \~english The first element of the pair is the key, and the second is the value.
|
|
||||||
//! \~russian Первый элемент пары является ключом, а второй значением.
|
|
||||||
inline PIMap<Key, T> & insert(const PIPair<Key, T> & pair) {
|
|
||||||
bool f(false);
|
bool f(false);
|
||||||
const ssize_t i = _find(pair.first, f);
|
ssize_t i = _find(key, f);
|
||||||
if (f) {
|
|
||||||
_value(i) = pair.second;
|
|
||||||
} else {
|
|
||||||
pim_content.push_back(pair.second);
|
|
||||||
pim_index.insert(i, MapIndex(pair.first, pim_content.size() - 1));
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PIMap<Key, T> & insert(PIPair<Key, T> && pair) {
|
|
||||||
bool f(false);
|
|
||||||
Key k(std::move(pair.first));
|
|
||||||
const ssize_t i = _find(k, f);
|
|
||||||
if (f) {
|
|
||||||
_value(i) = std::move(pair.second);
|
|
||||||
} else {
|
|
||||||
pim_content.push_back(std::move(pair.second));
|
|
||||||
pim_index.insert(i, MapIndex(k, pim_content.size() - 1));
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns the value of the element by the key `key`
|
|
||||||
//! or `default_` if there is no such element.
|
|
||||||
//! \~russian Возвращает значение элемента по ключу `key`
|
|
||||||
//! или `default_` если такого элемента нет.
|
|
||||||
inline T value(const Key & key, const T & default_ = T()) const {
|
|
||||||
bool f(false);
|
|
||||||
const ssize_t i = _find(key, f);
|
|
||||||
if (!f) return default_;
|
if (!f) return default_;
|
||||||
return _value(i);
|
return pim_content[i].second;
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns an array of values of all elements
|
|
||||||
//! \~russian Возвращает массив значений всех эелметнов
|
|
||||||
inline PIVector<T> values() const { return pim_content; }
|
|
||||||
|
|
||||||
//! \~english Returns the key of the first element
|
|
||||||
//! whose value matches `value` or `default_` if there is no such element.
|
|
||||||
//! \~russian Возвращает ключ первого элемента, значение которого
|
|
||||||
//! совпадает с `value` или `default_` если такого элемента нет.
|
|
||||||
inline Key key(const T & value, const Key & default_ = Key()) const {
|
|
||||||
for (int i = 0; i < pim_index.size_s(); ++i) {
|
|
||||||
const auto & mi(pim_index[i]);
|
|
||||||
if (pim_content[mi.index] == value) {
|
|
||||||
return mi.key;
|
|
||||||
}
|
}
|
||||||
|
PIVector<T> values() const {
|
||||||
|
PIVector<T> ret;
|
||||||
|
for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].second;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
Key key(const T & value_, const Key & default_ = Key()) const {
|
||||||
|
for (int i = 0; i < pim_content.size_s(); ++i)
|
||||||
|
if (pim_content[i].second == value_)
|
||||||
|
return pim_content[i].first;
|
||||||
return default_;
|
return default_;
|
||||||
}
|
}
|
||||||
|
PIVector<Key> keys() const {
|
||||||
//! \~english Returns an array of keys of all elements
|
|
||||||
//! \~russian Возвращает массив ключей всех элементов
|
|
||||||
inline PIVector<Key> keys() const {
|
|
||||||
PIVector<Key> ret;
|
PIVector<Key> ret;
|
||||||
ret.reserve(pim_index.size());
|
for (size_t i = 0; i < pim_content.size(); ++i) ret << pim_content[i].first;
|
||||||
for (int i = 0; i < pim_index.size_s(); ++i) {
|
|
||||||
ret << pim_index[i].key;
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Execute function `void f(const Key & key, const T & value)` for every element in array.
|
void dump() {
|
||||||
//! \~russian Выполняет функцию `void f(const Key & key, const T & value)` для каждого элемента массива.
|
piCout << "PIMap" << size() << "entries" << PICoutManipulators::NewLine << "content:";
|
||||||
inline void forEach(std::function<void(const Key & key, const T & value)> f) const {
|
for (size_t i = 0; i < pim_content.size(); ++i)
|
||||||
for (int i = 0; i < pim_index.size_s(); ++i) {
|
piCout << PICoutManipulators::Tab << i << ":" << pim_content[i];
|
||||||
const auto & mi(pim_index[i]);
|
// piCout << "index:";
|
||||||
f(mi.key, pim_content[mi.index]);
|
// for (size_t i = 0; i < pim_index.size(); ++i)
|
||||||
}
|
// piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Сreates a new map PIMap<Key2, T2> populated with the results
|
protected:
|
||||||
//! of calling a provided function `PIPair<Key2, T2> f(const Key & key, const T & value)` on every element in the calling array.
|
// struct MapIndex {
|
||||||
//! \~russian Создаёт новый словарь PIMap<Key2, T2> с результатом вызова указанной функции
|
// MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;}
|
||||||
//! `PIPair<Key2, T2> f(const Key & key, const T & value)` для каждого элемента массива.
|
// Key key;
|
||||||
template<typename Key2, typename T2>
|
// size_t index;
|
||||||
inline PIMap<Key2, T2> map(std::function<PIPair<Key2, T2>(const Key & key, const T & value)> f) const {
|
// bool operator ==(const MapIndex & s) const {return key == s.key;}
|
||||||
PIMap<Key2, T2> ret;
|
// bool operator !=(const MapIndex & s) const {return key != s.key;}
|
||||||
ret.reserve(size());
|
// bool operator <(const MapIndex & s) const {return key < s.key;}
|
||||||
for (int i = 0; i < pim_index.size_s(); ++i) {
|
// bool operator >(const MapIndex & s) const {return key > s.key;}
|
||||||
const auto & mi(pim_index[i]);
|
// };
|
||||||
ret.insert(f(mi.key, pim_content[mi.index]));
|
// template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
|
||||||
}
|
// template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Сreates a new array PIVector<ST> populated with the results
|
ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
|
||||||
//! of calling a provided function `ST f(const Key & key, const T & value)` on every element in the calling array.
|
ssize_t mid;
|
||||||
//! \~russian Создаёт новый массив PIVector<ST> с результатом вызова указанной функции
|
|
||||||
//! `ST f(const Key & key, const T & value)` для каждого элемента массива.
|
|
||||||
template<typename ST>
|
|
||||||
inline PIVector<ST> map(std::function<ST(const Key & key, const T & value)> f) const {
|
|
||||||
PIVector<ST> ret;
|
|
||||||
ret.reserve(size());
|
|
||||||
for (int i = 0; i < pim_index.size_s(); ++i) {
|
|
||||||
const auto & mi(pim_index[i]);
|
|
||||||
ret << f(mi.key, pim_content[mi.index]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns a new array with all elements
|
|
||||||
//! that pass the test implemented by the provided function `bool test(const Key & key, const T & value)`.
|
|
||||||
//! \~russian Возвращает новый массив со всеми элементами,
|
|
||||||
//! прошедшими проверку, задаваемую в передаваемой функции `bool test(const Key & key, const T & value)`.
|
|
||||||
inline PIMap<Key, T> filter(std::function<bool(const Key & key, const T & value)> test) const {
|
|
||||||
PIMap<Key, T> ret;
|
|
||||||
for (int i = 0; i < pim_index.size_s(); ++i) {
|
|
||||||
const auto & mi(pim_index[i]);
|
|
||||||
const auto & v(pim_content[mi.index]);
|
|
||||||
if (test(mi.key, v)) {
|
|
||||||
ret.insert(mi.key, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct MapIndex {
|
|
||||||
MapIndex(const Key & k = Key(), size_t i = 0): key(k), index(i) {}
|
|
||||||
MapIndex(Key && k, size_t i = 0): key(std::move(k)), index(i) {}
|
|
||||||
Key key;
|
|
||||||
size_t index;
|
|
||||||
bool operator==(const MapIndex & s) const { return key == s.key; }
|
|
||||||
bool operator!=(const MapIndex & s) const { return key != s.key; }
|
|
||||||
bool operator<(const MapIndex & s) const { return key < s.key; }
|
|
||||||
bool operator>(const MapIndex & s) const { return key > s.key; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename P, typename Key1, typename T1>
|
|
||||||
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
|
|
||||||
template<typename P, typename Key1, typename T1>
|
|
||||||
friend PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const PIDeque<typename PIMap<Key1, T1>::MapIndex> & v);
|
|
||||||
|
|
||||||
inline ssize_t _binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const {
|
|
||||||
ssize_t mid = 0;
|
|
||||||
while (first <= last) {
|
while (first <= last) {
|
||||||
mid = (first + last) / 2;
|
mid = (first + last) / 2;
|
||||||
if (key > pim_index[mid].key)
|
if (key > pim_content[mid].first) first = mid + 1;
|
||||||
first = mid + 1;
|
else if (key < pim_content[mid].first) last = mid - 1;
|
||||||
else if (key < pim_index[mid].key)
|
else {found = true; return mid;}
|
||||||
last = mid - 1;
|
|
||||||
else {
|
|
||||||
found = true;
|
|
||||||
return mid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
found = false;
|
found = false;
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
ssize_t _find(const Key & k, bool & found) const {
|
||||||
inline ssize_t _find(const Key & k, bool & found) const {
|
if (pim_content.isEmpty()) {
|
||||||
if (pim_index.isEmpty()) {
|
|
||||||
found = false;
|
found = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return _binarySearch(0, pim_index.size_s() - 1, k, found);
|
return binarySearch(0, pim_content.size_s() - 1, k, found);
|
||||||
}
|
}
|
||||||
|
void _remove(ssize_t index) {
|
||||||
inline void _remove(ssize_t index) {
|
pim_content.remove(index);
|
||||||
const size_t ci = pim_index[index].index, bi = pim_index.size() - 1;
|
|
||||||
pim_index.remove(index);
|
|
||||||
for (size_t i = 0; i < pim_index.size(); ++i) {
|
|
||||||
if (pim_index[i].index == bi) {
|
|
||||||
pim_index[i].index = ci;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
const value_type _pair(ssize_t index) const {
|
||||||
|
if (index < 0 || index >= pim_content.size_s()) return value_type();
|
||||||
|
return pim_content[index];
|
||||||
}
|
}
|
||||||
piSwap<T>(pim_content[ci], pim_content.back());
|
Key & _key(ssize_t index) {return pim_content[index].first;}
|
||||||
pim_content.resize(pim_index.size());
|
T & _value(ssize_t index) {return pim_content[index].second;}
|
||||||
}
|
|
||||||
|
|
||||||
inline const value_type _pair(ssize_t index) const {
|
PIDeque<PIPair<Key, T>> pim_content;
|
||||||
if (index < 0 || index >= pim_index.size_s()) return value_type();
|
|
||||||
const auto & mi(pim_index[index]);
|
|
||||||
return value_type(mi.key, pim_content[mi.index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Key & _key(ssize_t index) { return pim_index[index].key; }
|
|
||||||
|
|
||||||
inline const Key & _key(ssize_t index) const { return pim_index[index].key; }
|
|
||||||
|
|
||||||
inline T & _value(ssize_t index) { return pim_content[pim_index[index].index]; }
|
|
||||||
|
|
||||||
inline const T & _value(ssize_t index) const { return pim_content[pim_index[index].index]; }
|
|
||||||
|
|
||||||
|
|
||||||
PIVector<T> pim_content;
|
|
||||||
PIDeque<MapIndex> pim_index;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \addtogroup Containers
|
|
||||||
//! \{
|
|
||||||
//! \class PIMapIteratorConst
|
|
||||||
//! \brief
|
|
||||||
//! \~english Java-style iterator for \a PIMap.
|
|
||||||
//! \~russian Итератор Java стиля для \a PIMap.
|
|
||||||
//! \~\}
|
|
||||||
//! \details
|
|
||||||
//! \~english
|
|
||||||
//! This class used to easy serial access keys and values in PIMap with read only permitions.
|
|
||||||
//! Use constructor to create iterator, or use \a PIMap::makeIterator()
|
|
||||||
//! \~russian
|
|
||||||
//! Этот класс используется для удобного перебора ключей и значений всего словаря только для чтения.
|
|
||||||
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeIterator().
|
|
||||||
//! \~
|
|
||||||
//! \code
|
|
||||||
//! PIMap<int, PIString> m;
|
|
||||||
//! m[1] = "one";
|
|
||||||
//! m[2] = "two";
|
|
||||||
//! m[4] = "four";
|
|
||||||
//! auto it = m.makeIterator();
|
|
||||||
//! while (it.next()) {
|
|
||||||
//! piCout << it.key() << it.value();
|
|
||||||
//! }
|
|
||||||
//! // 1 one
|
|
||||||
//! // 2 two
|
|
||||||
//! // 4 four
|
|
||||||
//! \endcode
|
|
||||||
template<typename Key, typename T>
|
|
||||||
class PIMapIteratorConst {
|
|
||||||
typedef PIMap<Key, T> MapType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline PIMapIteratorConst(const PIMap<Key, T> & map): m(map), pos(-1) {}
|
|
||||||
|
|
||||||
//! \~english Returns current key.
|
|
||||||
//! \~russian Возвращает ключ текущего элемента.
|
|
||||||
//! \~\sa \a value()
|
|
||||||
inline const Key & key() const { return m._key(pos); }
|
|
||||||
|
|
||||||
//! \~english Returns current value.
|
|
||||||
//! \~russian Возвращает значение текущего элемента.
|
|
||||||
//! \~\sa \a key()
|
|
||||||
inline const T & value() const { return m._value(pos); }
|
|
||||||
|
|
||||||
|
|
||||||
//! \~english Returns true if iterator can jump to next entry
|
|
||||||
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
|
|
||||||
//! \~\sa \a next()
|
|
||||||
inline bool hasNext() const { return pos < (m.size_s() - 1); }
|
|
||||||
|
|
||||||
//! \~english Jump to next entry and return true if new position is valid.
|
|
||||||
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
|
|
||||||
//! \~\sa \a hasNext(), \a reset()
|
|
||||||
inline bool next() {
|
|
||||||
++pos;
|
|
||||||
return pos < m.size_s();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Reset iterator to initial position.
|
|
||||||
//! \~russian Переходит на начало.
|
|
||||||
//! \~\sa \a next()
|
|
||||||
inline void reset() { pos = -1; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const MapType & m;
|
|
||||||
ssize_t pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//! \addtogroup Containers
|
|
||||||
//! \{
|
|
||||||
//! \class PIMapIteratorConstReverse
|
|
||||||
//! \brief
|
|
||||||
//! \~english Java-style reverse iterator for \a PIMap.
|
|
||||||
//! \~russian Итератор Java стиля для \a PIMap в обратном порядке.
|
|
||||||
//! \~\}
|
|
||||||
//! \details
|
|
||||||
//! \~english
|
|
||||||
//! This class used to easy serial reverse access keys and values in PIMap with read only permitions.
|
|
||||||
//! Use constructor to create iterator, or use \a PIMap::makeReverseIterator().
|
|
||||||
//! \~russian
|
|
||||||
//! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке только для чтения.
|
|
||||||
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeReverseIterator().
|
|
||||||
//! \~
|
|
||||||
//! \code
|
|
||||||
//! PIMap<int, PIString> m;
|
|
||||||
//! m[1] = "one";
|
|
||||||
//! m[2] = "two";
|
|
||||||
//! m[4] = "four";
|
|
||||||
//! auto it = m.makeReverseIterator();
|
|
||||||
//! while (it.next()) {
|
|
||||||
//! piCout << it.key() << it.value();
|
|
||||||
//! }
|
|
||||||
//! // 4 four
|
|
||||||
//! // 2 two
|
|
||||||
//! // 1 one
|
|
||||||
//! \endcode
|
|
||||||
template<typename Key, typename T>
|
|
||||||
class PIMapIteratorConstReverse {
|
|
||||||
typedef PIMap<Key, T> MapType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline PIMapIteratorConstReverse(const PIMap<Key, T> & map): m(map), pos(m.size_s()) {}
|
|
||||||
|
|
||||||
//! \~english Returns current key.
|
|
||||||
//! \~russian Возвращает ключ текущего элемента.
|
|
||||||
//! \~\sa \a value()
|
|
||||||
inline const Key & key() const { return m._key(pos); }
|
|
||||||
|
|
||||||
//! \~english Returns current value.
|
|
||||||
//! \~russian Возвращает значение текущего элемента.
|
|
||||||
//! \~\sa \a key()
|
|
||||||
inline const T & value() const { return m._value(pos); }
|
|
||||||
|
|
||||||
//! \~english Returns true if iterator can jump to next entry
|
|
||||||
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
|
|
||||||
//! \~\sa \a next()
|
|
||||||
inline bool hasNext() const { return pos > 0; }
|
|
||||||
|
|
||||||
//! \~english Jump to next entry and return true if new position is valid.
|
|
||||||
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
|
|
||||||
//! \~\sa \a hasNext(), \a reset()
|
|
||||||
inline bool next() {
|
|
||||||
--pos;
|
|
||||||
return pos >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Reset iterator to initial position.
|
|
||||||
//! \~russian Переходит на начало.
|
|
||||||
//! \~\sa \a next()
|
|
||||||
inline void reset() { pos = m.size_s(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const MapType & m;
|
|
||||||
ssize_t pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//! \addtogroup Containers
|
|
||||||
//! \{
|
|
||||||
//! \class PIMapIterator
|
|
||||||
//! \brief
|
|
||||||
//! \~english Java-style iterator for \a PIMap.
|
|
||||||
//! \~russian Итератор Java стиля для \a PIMap.
|
|
||||||
//! \~\}
|
|
||||||
//! \details
|
|
||||||
//! \~english
|
|
||||||
//! This class used to easy serial access keys and values in PIMap with write permitions.
|
|
||||||
//! Use constructor to create iterator, or use \a PIMap::makeIterator()
|
|
||||||
//! \~russian
|
|
||||||
//! Этот класс используется для удобного перебора ключей и значений всего словаря с доступом на запись.
|
|
||||||
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeIterator().
|
|
||||||
//! \~
|
|
||||||
//! \code
|
|
||||||
//! PIMap<int, PIString> m;
|
|
||||||
//! m[1] = "one";
|
|
||||||
//! m[2] = "two";
|
|
||||||
//! m[4] = "four";
|
|
||||||
//! auto it = m.makeIterator();
|
|
||||||
//! while (it.next()) {
|
|
||||||
//! it.value().append("_!");
|
|
||||||
//! piCout << it.key() << it.value();
|
|
||||||
//! }
|
|
||||||
//! // 1 one_!
|
|
||||||
//! // 2 two_!
|
|
||||||
//! // 4 four_!
|
|
||||||
//! \endcode
|
|
||||||
template <typename Key, typename T>
|
template <typename Key, typename T>
|
||||||
class PIMapIterator {
|
class PIMapIterator {
|
||||||
typedef PIMap<Key, T> MapType;
|
typedef PIMap<Key, T> MapType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline PIMapIterator(PIMap<Key, T> & map): m(map), pos(-1) {}
|
PIMapIterator(const PIMap<Key, T> & map, bool reverse = false): m(map), pos(-1), rev(reverse) {
|
||||||
|
if (rev) pos = m.size_s();
|
||||||
//! \~english Returns current key.
|
}
|
||||||
//! \~russian Возвращает ключ текущего элемента.
|
const Key & key() const {return const_cast<MapType & >(m)._key(pos);}
|
||||||
//! \~\sa \a value()
|
const T & value() const {return const_cast<MapType & >(m)._value(pos);}
|
||||||
inline const Key & key() const { return m._key(pos); }
|
T & valueRef() const {return const_cast<MapType & >(m)._value(pos);}
|
||||||
|
inline bool hasNext() const {
|
||||||
//! \~english Returns current value.
|
if (rev) {
|
||||||
//! \~russian Возвращает значение текущего элемента.
|
return pos > 0;
|
||||||
//! \~\sa \a key()
|
} else {
|
||||||
inline T & value() { return m._value(pos); }
|
return pos < (m.size_s() - 1);
|
||||||
|
}
|
||||||
//! \~english Returns true if iterator can jump to next entry
|
return false;
|
||||||
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
|
}
|
||||||
//! \~\sa \a next()
|
|
||||||
inline bool hasNext() const { return pos < (m.size_s() - 1); }
|
|
||||||
|
|
||||||
//! \~english Jump to next entry and return true if new position is valid.
|
|
||||||
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
|
|
||||||
//! \~\sa \a hasNext(), \a reset()
|
|
||||||
inline bool next() {
|
inline bool next() {
|
||||||
|
if (rev) {
|
||||||
|
--pos;
|
||||||
|
return pos >= 0;
|
||||||
|
} else {
|
||||||
++pos;
|
++pos;
|
||||||
return pos < m.size_s();
|
return pos < m.size_s();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
//! \~english Reset iterator to initial position.
|
}
|
||||||
//! \~russian Переходит на начало.
|
inline void reset() {
|
||||||
//! \~\sa \a next()
|
if (rev) {
|
||||||
inline void reset() { pos = -1; }
|
pos = m.size_s();
|
||||||
|
} else {
|
||||||
private:
|
pos = -1;
|
||||||
MapType & m;
|
}
|
||||||
ssize_t pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//! \addtogroup Containers
|
|
||||||
//! \{
|
|
||||||
//! \class PIMapIteratorReverse
|
|
||||||
//! \brief
|
|
||||||
//! \~english Java-style reverse iterator for \a PIMap.
|
|
||||||
//! \~russian Итератор Java стиля для \a PIMap в обратном порядке.
|
|
||||||
//! \~\}
|
|
||||||
//! \details
|
|
||||||
//! \~english
|
|
||||||
//! This class used to easy serial reverse access keys and values in PIMap with write permitions.
|
|
||||||
//! Use constructor to create iterator, or use \a PIMap::makeReverseIterator().
|
|
||||||
//! \~russian
|
|
||||||
//! Этот класс используется для удобного перебора ключей и значений всего словаря в обратном порядке с доступом на запись.
|
|
||||||
//! Можно использовать конструктор, в который передаётся словарь, или функцию словаря \a PIMap::makeReverseIterator().
|
|
||||||
//! \~
|
|
||||||
//! \code
|
|
||||||
//! PIMap<int, PIString> m;
|
|
||||||
//! m[1] = "one";
|
|
||||||
//! m[2] = "two";
|
|
||||||
//! m[4] = "four";
|
|
||||||
//! auto it = m.makeReverseIterator();
|
|
||||||
//! while (it.next()) {
|
|
||||||
//! it.value().append("_!");
|
|
||||||
//! piCout << it.key() << it.value();
|
|
||||||
//! }
|
|
||||||
//! // 4 four_!
|
|
||||||
//! // 2 two_!
|
|
||||||
//! // 1 one_!
|
|
||||||
//! \endcode
|
|
||||||
template<typename Key, typename T>
|
|
||||||
class PIMapIteratorReverse {
|
|
||||||
typedef PIMap<Key, T> MapType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline PIMapIteratorReverse(PIMap<Key, T> & map): m(map), pos(m.size_s()) {}
|
|
||||||
|
|
||||||
//! \~english Returns current key.
|
|
||||||
//! \~russian Возвращает ключ текущего элемента.
|
|
||||||
//! \~\sa \a value()
|
|
||||||
inline const Key & key() const { return m._key(pos); }
|
|
||||||
|
|
||||||
//! \~english Returns current value.
|
|
||||||
//! \~russian Возвращает значение текущего элемента.
|
|
||||||
//! \~\sa \a key()
|
|
||||||
inline T & value() { return m._value(pos); }
|
|
||||||
|
|
||||||
//! \~english Returns true if iterator can jump to next entry
|
|
||||||
//! \~russian Возвращает true если итератор может перейти к следующему элементу.
|
|
||||||
//! \~\sa \a next()
|
|
||||||
inline bool hasNext() const { return pos > 0; }
|
|
||||||
|
|
||||||
//! \~english Jump to next entry and return true if new position is valid.
|
|
||||||
//! \~russian Переходит к следующему элементу и возвращает true если он существует.
|
|
||||||
//! \~\sa \a hasNext(), \a reset()
|
|
||||||
inline bool next() {
|
|
||||||
--pos;
|
|
||||||
return pos >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Reset iterator to initial position.
|
|
||||||
//! \~russian Переходит на начало.
|
|
||||||
//! \~\sa \a next()
|
|
||||||
inline void reset() { pos = m.size_s(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MapType & m;
|
const MapType & m;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
bool rev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef PIP_STD_IOSTREAM
|
#ifdef PIP_STD_IOSTREAM
|
||||||
//! \~english Output operator to [std::ostream](https://en.cppreference.com/w/cpp/io/basic_ostream).
|
|
||||||
//! \~russian Оператор вывода в [std::ostream](https://ru.cppreference.com/w/cpp/io/basic_ostream).
|
|
||||||
template<typename Key, typename Type>
|
template<typename Key, typename Type>
|
||||||
inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v) {
|
inline std::ostream & operator <<(std::ostream & s, const PIMap<Key, Type> & v) {
|
||||||
s << "{";
|
s << "{";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (typename PIMap<Key, Type>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
for (typename PIMap<Key, Type>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||||
if (!first) s << ", ";
|
if (!first)
|
||||||
|
s << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
s << i.key() << ": " << i.value();
|
s << i->first << ": " << i->second;
|
||||||
}
|
}
|
||||||
s << "}";
|
s << "}";
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//! \relatesalso PICout
|
|
||||||
//! \~english Output operator to \a PICout
|
|
||||||
//! \~russian Оператор вывода в \a PICout
|
|
||||||
template<typename Key, typename Type>
|
template<typename Key, typename Type>
|
||||||
inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
|
inline PICout operator <<(PICout s, const PIMap<Key, Type> & v) {
|
||||||
s.space();
|
s.space();
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "{";
|
s << "{";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (typename PIMap<Key, Type>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
for (typename PIMap<Key, Type>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||||
if (!first) s << ", ";
|
if (!first)
|
||||||
|
s << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
s << i.key() << ": " << i.value();
|
s << i->first << ": " << i->second;
|
||||||
}
|
}
|
||||||
s << "}";
|
s << "}";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename Type>
|
template<typename Key, typename Type> inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {f.swap(s);}
|
||||||
inline void piSwap(PIMap<Key, Type> & f, PIMap<Key, Type> & s) {
|
|
||||||
f.swap(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PIMAP_H
|
#endif // PIMAP_H
|
||||||
|
|||||||
@@ -44,28 +44,25 @@
|
|||||||
//! \~english Class template that provides a way to store two heterogeneous objects as a single unit.
|
//! \~english Class template that provides a way to store two heterogeneous objects as a single unit.
|
||||||
//! \~russian Класс, который позволяет хранить два разнородных объекта как единое целое.
|
//! \~russian Класс, который позволяет хранить два разнородных объекта как единое целое.
|
||||||
//! \~\}
|
//! \~\}
|
||||||
|
//! \details
|
||||||
|
//! \~english
|
||||||
|
//! \~russian
|
||||||
//! \~\sa \a PIMap
|
//! \~\sa \a PIMap
|
||||||
template<typename Type0, typename Type1>
|
template<typename Type0, typename Type1>
|
||||||
class PIPair {
|
class PIPair {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! \~english Constructs an empty PIPair.
|
//! \~english Constructs an empty PIPair.
|
||||||
//! \~russian Создает пустой PIPair.
|
//! \~russian Создает пустой PIPair.
|
||||||
PIPair() : first(), second() {}
|
PIPair() : first(), second() {}
|
||||||
|
|
||||||
//! \~english Constructs PIPair from [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple).
|
//! \~english Constructs PIPair from [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple).
|
||||||
//! \~russian Создает PIPair из [std::tuple](https://ru.cppreference.com/w/cpp/utility/tuple).
|
//! \~russian Создает PIPair из [std::tuple](https://ru.cppreference.com/w/cpp/utility/tuple).
|
||||||
explicit PIPair(std::tuple<Type0, Type1> tuple) {
|
PIPair(std::tuple<Type0, Type1> tuple) {
|
||||||
first = std::get<0>(tuple);
|
first = std::get<0>(tuple);
|
||||||
second = std::get<1>(tuple);
|
second = std::get<1>(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Constructs PIPair from [std::pair](https://en.cppreference.com/w/cpp/utility/pair).
|
|
||||||
//! \~russian Создает PIPair из [std::pair](https://ru.cppreference.com/w/cpp/utility/pair).
|
|
||||||
explicit PIPair(std::pair<Type0, Type1> pair) {
|
|
||||||
first = pair.first;
|
|
||||||
second = pair.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Constructs PIPair from values `value0` and `value1`.
|
//! \~english Constructs PIPair from values `value0` and `value1`.
|
||||||
//! \~russian Создает PIPair из `value0` и `value1`.
|
//! \~russian Создает PIPair из `value0` и `value1`.
|
||||||
PIPair(const Type0 & value0, const Type1 & value1) {
|
PIPair(const Type0 & value0, const Type1 & value1) {
|
||||||
@@ -117,9 +114,9 @@ inline std::ostream & operator<<(std::ostream & s, const PIPair<Type0, Type1> &
|
|||||||
template<typename Type0, typename Type1>
|
template<typename Type0, typename Type1>
|
||||||
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {
|
inline PICout operator <<(PICout s, const PIPair<Type0, Type1> & v) {
|
||||||
s.space();
|
s.space();
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "(" << v.first << ", " << v.second << ")";
|
s << "(" << v.first << ", " << v.second << ")";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +133,6 @@ PIPair<T1, T2> createPIPair(const T1 & f, const T2 & s) {
|
|||||||
return PIPair<T1,T2>(f, s);
|
return PIPair<T1,T2>(f, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! \~english Creates \a PIPair object, deducing the target type from the types of arguments.
|
//! \~english Creates \a PIPair object, deducing the target type from the types of arguments.
|
||||||
//! \~russian Создает \a PIPair выводя типы из аргументов.
|
//! \~russian Создает \a PIPair выводя типы из аргументов.
|
||||||
//! \sa \a createPIPair()
|
//! \sa \a createPIPair()
|
||||||
@@ -145,5 +141,4 @@ PIPair<T1, T2> createPIPair(T1 && f, T2 && s) {
|
|||||||
return PIPair<T1,T2>(std::move(f), std::move(s));
|
return PIPair<T1,T2>(std::move(f), std::move(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // PIPAIR_H
|
#endif // PIPAIR_H
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
//! \addtogroup Containers
|
/*! \file piqueue.h
|
||||||
//! \{
|
* \brief Queue container
|
||||||
//! \file piqueue.h
|
*
|
||||||
//! \brief
|
* This file declare PIQueue
|
||||||
//! \~english Declares \a PIQueue
|
*/
|
||||||
//! \~russian Объявление \a PIQueue
|
|
||||||
//! \~\authors
|
|
||||||
//! \~english
|
|
||||||
//! Ivan Pelipenko peri4ko@yandex.ru;
|
|
||||||
//! Andrey Bychkov work.a.b@yandex.ru;
|
|
||||||
//! \~russian
|
|
||||||
//! Иван Пелипенко peri4ko@yandex.ru;
|
|
||||||
//! Андрей Бычков work.a.b@yandex.ru;
|
|
||||||
//! \~\}
|
|
||||||
/*
|
/*
|
||||||
PIP - Platform Independent Primitives
|
PIP - Platform Independent Primitives
|
||||||
Queue container
|
Queue container
|
||||||
@@ -37,82 +28,24 @@
|
|||||||
#include "pideque.h"
|
#include "pideque.h"
|
||||||
#include "pivector.h"
|
#include "pivector.h"
|
||||||
|
|
||||||
//! \addtogroup Containers
|
|
||||||
//! \{
|
|
||||||
//! \class PIQueue
|
|
||||||
//! \brief
|
|
||||||
//! \~english A container class inherited from the \a PIDeque with queue functionality.
|
|
||||||
//! \~russian Класс контейнера наследованый от \a PIDeque с функциональностью очереди.
|
|
||||||
//! \~\}
|
|
||||||
//! \details
|
|
||||||
//! \~english The container is a array of elements organized according to the FIFO principle (first in, first out).
|
|
||||||
//! Adds \a enqueue() and \dequeue() functions to \a PIDeque.
|
|
||||||
//! \~russian Контейнер представляющий массив элементов, организованных по принципу FIFO (первым пришёл — первым вышел).
|
|
||||||
//! Добавляет к \a PIDeque функции \a enqueue() и \a dequeue().
|
|
||||||
//! \~\sa \a PIDeque
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class PIQueue: public PIDeque<T> {
|
class PIQueue: public PIDeque<T> {
|
||||||
public:
|
public:
|
||||||
//! \~english Constructs an empty array.
|
|
||||||
//! \~russian Создает пустой массив.
|
|
||||||
PIQueue() {}
|
PIQueue() {}
|
||||||
|
virtual ~PIQueue() {}
|
||||||
//! \~english Puts an element on the queue.
|
PIDeque<T> & enqueue(const T & v) {PIDeque<T>::push_front(v); return *this;}
|
||||||
//! \~russian Кладёт элемент в очередь.
|
PIDeque<T> & enqueue(T && v) {PIDeque<T>::push_front(std::move(v)); return *this;}
|
||||||
PIDeque<T> & enqueue(const T & v) {
|
|
||||||
PIDeque<T>::push_front(v);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Move an element on the queue.
|
|
||||||
//! \~russian Перемещает элемент в очередь.
|
|
||||||
PIDeque<T> & enqueue(T && v) {
|
|
||||||
PIDeque<T>::push_front(std::move(v));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Retrieves and returns an element from the queue.
|
|
||||||
//! \~russian Забирает и возвращает элемент из очереди.
|
|
||||||
//! \~\details
|
|
||||||
//! \note
|
|
||||||
//! \~english This function assumes that the array isn't empty.
|
|
||||||
//! Otherwise will be undefined behavior.
|
|
||||||
//! \~russian Эта функция предполагает, что массив не пустой.
|
|
||||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
|
||||||
T dequeue() {return PIDeque<T>::take_back();}
|
T dequeue() {return PIDeque<T>::take_back();}
|
||||||
|
|
||||||
//! \~english Head element of the queue.
|
|
||||||
//! \~russian Головной (верхний) элемент очереди.
|
|
||||||
//! \~\details
|
|
||||||
//! \note
|
|
||||||
//! \~english Returns a reference to the head element of the queue.
|
|
||||||
//! This function assumes that the array isn't empty.
|
|
||||||
//! Otherwise will be undefined behavior.
|
|
||||||
//! \~russian Возвращает ссылку на головной (верхний) элемент очереди.
|
|
||||||
//! Эта функция предполагает, что массив не пустой.
|
|
||||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
|
||||||
T & head() {return PIDeque<T>::back();}
|
T & head() {return PIDeque<T>::back();}
|
||||||
const T & head() const {return PIDeque<T>::back();}
|
const T & head() const {return PIDeque<T>::back();}
|
||||||
|
PIVector<T> toVector() {
|
||||||
//! \~english Tail element of the queue.
|
PIVector<T> v;
|
||||||
//! \~russian Хвостовой (нижний) элемент очереди.
|
v.reserve(PIDeque<T>::size());
|
||||||
//! \~\details
|
for (uint i = 0; i < PIDeque<T>::size(); ++i)
|
||||||
//! \~english Returns a reference to the tail element of the queue.
|
v.push_back(PIDeque<T>::at(i));
|
||||||
//! This function assumes that the array isn't empty.
|
return v;
|
||||||
//! Otherwise will be undefined behavior.
|
}
|
||||||
//! \~russian Возвращает ссылку на хвостовой (нижний) элемент очереди.
|
|
||||||
//! Эта функция предполагает, что массив не пустой.
|
|
||||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
|
||||||
T & tail() { return PIDeque<T>::front(); }
|
|
||||||
const T & tail() const { return PIDeque<T>::front(); }
|
|
||||||
|
|
||||||
//! \~english Converts \a PIQueue to \a PIVector.
|
|
||||||
//! \~russian Преобразует \a PIQueue в \a PIVector.
|
|
||||||
PIVector<T> toVector() const { return PIVector<T>(PIDeque<T>::data(), PIDeque<T>::size()); }
|
|
||||||
|
|
||||||
//! \~english Converts \a PIQueue to \a PIDeque.
|
|
||||||
//! \~russian Преобразует \a PIQueue в \a PIDeque.
|
|
||||||
PIDeque<T> toDeque() const { return PIDeque<T>(*this); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PIQUEUE_H
|
#endif // PIQUEUE_H
|
||||||
|
|||||||
@@ -37,37 +37,27 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class PISet: public PIMap<T, uchar> {
|
class PISet: public PIMap<T, uchar> {
|
||||||
typedef PIMap<T, uchar> _CSet;
|
typedef PIMap<T, uchar> _CSet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Contructs an empty set
|
//! Contructs an empty set
|
||||||
PISet() {}
|
PISet() {}
|
||||||
|
|
||||||
|
virtual ~PISet() {;}
|
||||||
|
|
||||||
//! Contructs set with one element "value"
|
//! Contructs set with one element "value"
|
||||||
explicit PISet(const T & value) { _CSet::insert(value, 0); }
|
PISet(const T & value) {_CSet::insert(value, 0);}
|
||||||
|
|
||||||
//! Contructs set with elements "v0" and "v1"
|
//! Contructs set with elements "v0" and "v1"
|
||||||
PISet(const T & v0, const T & v1) {
|
PISet(const T & v0, const T & v1) {_CSet::insert(v0, 0); _CSet::insert(v1, 0);}
|
||||||
_CSet::insert(v0, 0);
|
|
||||||
_CSet::insert(v1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Contructs set with elements "v0", "v1" and "v2"
|
//! Contructs set with elements "v0", "v1" and "v2"
|
||||||
PISet(const T & v0, const T & v1, const T & v2) {
|
PISet(const T & v0, const T & v1, const T & v2) {_CSet::insert(v0, 0); _CSet::insert(v1, 0); _CSet::insert(v2, 0);}
|
||||||
_CSet::insert(v0, 0);
|
|
||||||
_CSet::insert(v1, 0);
|
|
||||||
_CSet::insert(v2, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Contructs set with elements "v0", "v1", "v2" and "v3"
|
//! Contructs set with elements "v0", "v1", "v2" and "v3"
|
||||||
PISet(const T & v0, const T & v1, const T & v2, const T & v3) {
|
PISet(const T & v0, const T & v1, const T & v2, const T & v3) {_CSet::insert(v0, 0); _CSet::insert(v1, 0); _CSet::insert(v2, 0); _CSet::insert(v3, 0);}
|
||||||
_CSet::insert(v0, 0);
|
|
||||||
_CSet::insert(v1, 0);
|
|
||||||
_CSet::insert(v2, 0);
|
|
||||||
_CSet::insert(v3, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Contructs set from vector of elements
|
//! Contructs set from vector of elements
|
||||||
explicit PISet(const PIVector<T> & values) {
|
PISet(const PIVector<T> & values) {
|
||||||
if (values.isEmpty()) return;
|
if (values.isEmpty()) return;
|
||||||
for (int i = 0; i < values.size_s(); ++i) {
|
for (int i = 0; i < values.size_s(); ++i) {
|
||||||
_CSet::insert(values[i], 0);
|
_CSet::insert(values[i], 0);
|
||||||
@@ -75,7 +65,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Contructs set from deque of elements
|
//! Contructs set from deque of elements
|
||||||
explicit PISet(const PIDeque<T> & values) {
|
PISet(const PIDeque<T> & values) {
|
||||||
if (values.isEmpty()) return;
|
if (values.isEmpty()) return;
|
||||||
for (int i = 0; i < values.size_s(); ++i) {
|
for (int i = 0; i < values.size_s(); ++i) {
|
||||||
_CSet::insert(values[i], 0);
|
_CSet::insert(values[i], 0);
|
||||||
@@ -84,39 +74,27 @@ public:
|
|||||||
|
|
||||||
typedef T key_type;
|
typedef T key_type;
|
||||||
|
|
||||||
PISet<T> & operator<<(const T & t) {
|
PISet<T> & operator <<(const T & t) {_CSet::insert(t, 0); return *this;}
|
||||||
_CSet::insert(t, 0);
|
PISet<T> & operator <<(T && t) {_CSet::insert(std::move(t), 0); return *this;}
|
||||||
return *this;
|
PISet<T> & operator <<(const PISet<T> & other) {(*(_CSet*)this) << *((_CSet*)&other); return *this;}
|
||||||
}
|
|
||||||
PISet<T> & operator<<(T && t) {
|
|
||||||
_CSet::insert(std::move(t), 0);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
PISet<T> & operator<<(const PISet<T> & other) {
|
|
||||||
(*(_CSet *)this) << *((_CSet *)&other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns if element "t" exists in this set
|
//! Returns if element "t" exists in this set
|
||||||
bool operator [](const T & t) const {return _CSet::contains(t);}
|
bool operator [](const T & t) const {return _CSet::contains(t);}
|
||||||
|
|
||||||
//! Returns if element "t" exists in this set
|
//! Returns if element "t" exists in this set
|
||||||
PISet<T> & remove(const T & t) {
|
PISet<T> & remove(const T & t) {_CSet::remove(t); return *this;}
|
||||||
_CSet::remove(t);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Unite set with "v"
|
//! Unite set with "v"
|
||||||
PISet<T> & unite(const PISet<T> & v) {
|
PISet<T> & unite(const PISet<T> & v) {
|
||||||
for (typename PIMap<T, uchar>::const_iterator i = v.begin(); i != v.end(); ++i)
|
for (typename PIMap<T, uchar>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||||
_CSet::insert(i.key(), 0);
|
_CSet::insert(i->first, 0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Subtract set with "v"
|
//! Subtract set with "v"
|
||||||
PISet<T> & subtract(const PISet<T> & v) {
|
PISet<T> & subtract(const PISet<T> & v) {
|
||||||
for (typename PIMap<T, uchar>::const_iterator i = v.begin(); i != v.end(); ++i)
|
for (typename PIMap<T, uchar>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||||
_CSet::remove(i.key());
|
_CSet::remove(i->first);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,69 +121,41 @@ public:
|
|||||||
PISet<T> & operator &=(const PISet<T> & v) {return intersect(v);}
|
PISet<T> & operator &=(const PISet<T> & v) {return intersect(v);}
|
||||||
|
|
||||||
//! Returns content of set as PIVector
|
//! Returns content of set as PIVector
|
||||||
PIVector<T> toVector() const {
|
PIVector<T> toVector() const {PIVector<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << (*i).first; return ret;}
|
||||||
PIVector<T> ret;
|
|
||||||
for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i)
|
|
||||||
ret << i.key();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns content of set as PIDeque
|
//! Returns content of set as PIDeque
|
||||||
PIDeque<T> toDeque() const {
|
PIDeque<T> toDeque() const {PIDeque<T> ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << (*i).first; return ret;}
|
||||||
PIDeque<T> ret;
|
|
||||||
for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i)
|
|
||||||
ret << i.key();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! \relatesalso PISet \brief Returns unite of two sets
|
//! \relatesalso PISet \brief Returns unite of two sets
|
||||||
template<typename T>
|
template <typename T> PISet<T> operator +(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.unite(v1); return ret;}
|
||||||
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>
|
template <typename T> PISet<T> operator -(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.subtract(v1); return ret;}
|
||||||
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>
|
template <typename T> PISet<T> operator |(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.unite(v1); return ret;}
|
||||||
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>
|
template <typename T> PISet<T> operator &(const PISet<T> & v0, const PISet<T> & v1) {PISet<T> ret(v0); ret.intersect(v1); return ret;}
|
||||||
PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
|
|
||||||
PISet<T> ret(v0);
|
|
||||||
ret.intersect(v1);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
inline PICout operator <<(PICout s, const PISet<Type> & v) {
|
inline PICout operator <<(PICout s, const PISet<Type> & v) {
|
||||||
s.space();
|
s.space();
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "{";
|
s << "{";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (typename PIMap<Type, uchar>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
for (typename PIMap<Type, uchar>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||||
if (!first) s << ", ";
|
if (!first)
|
||||||
|
s << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
s << i.key();
|
s << i->first;
|
||||||
}
|
}
|
||||||
s << "}";
|
s << "}";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
//! \addtogroup Containers
|
/*! \file pistack.h
|
||||||
//! \{
|
* \brief Stack container
|
||||||
//! \file pistack.h
|
*
|
||||||
//! \brief
|
* This file declare PIStack
|
||||||
//! \~english Declares \a PIStack
|
*/
|
||||||
//! \~russian Объявление \a PIStack
|
|
||||||
//! \~\authors
|
|
||||||
//! \~english
|
|
||||||
//! Ivan Pelipenko peri4ko@yandex.ru;
|
|
||||||
//! Andrey Bychkov work.a.b@yandex.ru;
|
|
||||||
//! \~russian
|
|
||||||
//! Иван Пелипенко peri4ko@yandex.ru;
|
|
||||||
//! Андрей Бычков work.a.b@yandex.ru;
|
|
||||||
//! \~\}
|
|
||||||
/*
|
/*
|
||||||
PIP - Platform Independent Primitives
|
PIP - Platform Independent Primitives
|
||||||
Stack container
|
Stack container
|
||||||
@@ -34,73 +25,25 @@
|
|||||||
#ifndef PISTACK_H
|
#ifndef PISTACK_H
|
||||||
#define PISTACK_H
|
#define PISTACK_H
|
||||||
|
|
||||||
#include "pideque.h"
|
|
||||||
#include "pivector.h"
|
#include "pivector.h"
|
||||||
|
|
||||||
//! \addtogroup Containers
|
|
||||||
//! \{
|
|
||||||
//! \class PIStack
|
|
||||||
//! \brief
|
|
||||||
//! \~english A container class inherited from the \a PIVector with stack functionality.
|
|
||||||
//! \~russian Класс контейнера наследованый от \a PIVector с функциональностью стека.
|
|
||||||
//! \~\}
|
|
||||||
//! \details
|
|
||||||
//! \~english The container is a array of elements organized according to the LIFO principle (last in, first out).
|
|
||||||
//! Adds \a push() and \pop() functions to \a PIVector.
|
|
||||||
//! \~russian Контейнер представляющий массив элементов, организованных по принципу LIFO (последним пришёл — первым вышел).
|
|
||||||
//! Добавляет к \a PIVector функции \a push() и \a pop().
|
|
||||||
//! \~\sa \a PIVector
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class PIStack: public PIVector<T> {
|
class PIStack: public PIVector<T> {
|
||||||
public:
|
public:
|
||||||
//! \~english Constructs an empty array.
|
PIStack() {;}
|
||||||
//! \~russian Создает пустой массив.
|
virtual ~PIStack() {;}
|
||||||
PIStack() {}
|
PIVector<T> & push(const T & v) {PIVector<T>::push_back(v); return *this;}
|
||||||
|
PIVector<T> & push(T && v) {PIVector<T>::push_back(std::move(v)); return *this;}
|
||||||
//! \~english Puts an element on the stack.
|
|
||||||
//! \~russian Кладёт элемент в стек.
|
|
||||||
PIVector<T> & push(const T & v) {
|
|
||||||
PIVector<T>::push_back(v);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Move an element on the stack.
|
|
||||||
//! \~russian Перемещает элемент в стек.
|
|
||||||
PIVector<T> & push(T && v) {
|
|
||||||
PIVector<T>::push_back(std::move(v));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Retrieves and returns an element from the stack.
|
|
||||||
//! \~russian Забирает и возвращает элемент из стека.
|
|
||||||
//! \~\details
|
|
||||||
//! \note
|
|
||||||
//! \~english This function assumes that the array isn't empty.
|
|
||||||
//! Otherwise will be undefined behavior.
|
|
||||||
//! \~russian Эта функция предполагает, что массив не пустой.
|
|
||||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
|
||||||
T pop() {return PIVector<T>::take_back();}
|
T pop() {return PIVector<T>::take_back();}
|
||||||
|
|
||||||
//! \~english Top element of the stack
|
|
||||||
//! \~russian Верхний элемент стека.
|
|
||||||
//! \~\details
|
|
||||||
//! \note
|
|
||||||
//! \~english Returns a reference to the top element of the stack.
|
|
||||||
//! This function assumes that the array isn't empty.
|
|
||||||
//! Otherwise will be undefined behavior.
|
|
||||||
//! \~russian Возвращает ссылку на верхний элемент стека.
|
|
||||||
//! Эта функция предполагает, что массив не пустой.
|
|
||||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
|
||||||
T & top() {return PIVector<T>::back();}
|
T & top() {return PIVector<T>::back();}
|
||||||
const T & top() const {return PIVector<T>::back();}
|
const T & top() const {return PIVector<T>::back();}
|
||||||
|
PIVector<T> toVector() {
|
||||||
//! \~english Converts \a PIStack to \a PIVector.
|
PIVector<T> v;
|
||||||
//! \~russian Преобразует \a PIStack в \a PIVector.
|
v.reserve(PIVector<T>::size());
|
||||||
PIVector<T> toVector() const { return PIVector<T>(*this); }
|
for (uint i = 0; i < PIVector<T>::size(); ++i)
|
||||||
|
v.push_back(PIVector<T>::at(i));
|
||||||
//! \~english Converts \a PIStack to \a PIDeque.
|
return v;
|
||||||
//! \~russian Преобразует \a PIStack в \a PIDeque.
|
}
|
||||||
PIDeque<T> toDeque() const { return PIDeque<T>(PIVector<T>::data(), PIVector<T>::size()); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PISTACK_H
|
#endif // PISTACK_H
|
||||||
|
|||||||
@@ -74,9 +74,9 @@
|
|||||||
//! if the number of elements is known beforehand.
|
//! if the number of elements is known beforehand.
|
||||||
//!
|
//!
|
||||||
//! The complexity (efficiency) of common operations on PIVector is as follows:
|
//! The complexity (efficiency) of common operations on PIVector is as follows:
|
||||||
//! - Random access - constant O(1)
|
//! - Random access - constant 𝓞(1)
|
||||||
//! - Insertion or removal of elements at the end - amortized constant O(1)
|
//! - Insertion or removal of elements at the end - amortized constant 𝓞(1)
|
||||||
//! - Insertion or removal of elements - linear in the distance to the end of the array O(n)
|
//! - Insertion or removal of elements - linear in the distance to the end of the array 𝓞(n)
|
||||||
//!
|
//!
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! Элементы хранятся непрерывно, а значит доступны не только через итераторы,
|
//! Элементы хранятся непрерывно, а значит доступны не только через итераторы,
|
||||||
@@ -109,9 +109,9 @@
|
|||||||
//! если количество элементов известно заранее.
|
//! если количество элементов известно заранее.
|
||||||
//!
|
//!
|
||||||
//! Сложность (эффективность) обычных операций над PIVector следующая:
|
//! Сложность (эффективность) обычных операций над PIVector следующая:
|
||||||
//! - Произвольный доступ — постоянная O(1)
|
//! - Произвольный доступ — постоянная 𝓞(1)
|
||||||
//! - Вставка и удаление элементов в конце — амортизированная постоянная O(1)
|
//! - Вставка и удаление элементов в конце — амортизированная постоянная 𝓞(1)
|
||||||
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива O(n)
|
//! - Вставка и удаление элементов — линейная по расстоянию до конца массива 𝓞(n)
|
||||||
//!
|
//!
|
||||||
//! \~\sa \a PIDeque, \a PIMap
|
//! \~\sa \a PIDeque, \a PIMap
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -127,13 +127,15 @@ public:
|
|||||||
|
|
||||||
//! \~english Constructs an empty array.
|
//! \~english Constructs an empty array.
|
||||||
//! \~russian Создает пустой массив.
|
//! \~russian Создает пустой массив.
|
||||||
inline PIVector() { PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T)) }
|
inline PIVector(): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||||
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Contructs array from raw `data`.
|
//! \~english Contructs array from raw `data`.
|
||||||
//! This constructor reserve `size` and copy from `data` pointer.
|
//! This constructor reserve `size` and copy from `data` pointer.
|
||||||
//! \~russian Создает массив из указателя на данные `data` и размер `size`.
|
//! \~russian Создает массив из указателя на данные `data` и размер `size`.
|
||||||
//! То есть выделяет память для `size` элементов и копирует данные из указателя `data`.
|
//! То есть выделяет память для `size` элементов и копирует данные из указателя `data`.
|
||||||
inline PIVector(const T * data, size_t size) {
|
inline PIVector(const T * data, size_t size): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
alloc(size);
|
alloc(size);
|
||||||
newT(piv_data, data, piv_size);
|
newT(piv_data, data, piv_size);
|
||||||
@@ -141,7 +143,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Copy constructor.
|
//! \~english Copy constructor.
|
||||||
//! \~russian Копирующий конструктор.
|
//! \~russian Копирующий конструктор.
|
||||||
inline PIVector(const PIVector<T> & v) {
|
inline PIVector(const PIVector<T> & v): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
alloc(v.piv_size);
|
alloc(v.piv_size);
|
||||||
newT(piv_data, v.piv_data, piv_size);
|
newT(piv_data, v.piv_data, piv_size);
|
||||||
@@ -156,7 +158,7 @@ public:
|
|||||||
//! PIVector <int> v{1,2,3};
|
//! PIVector <int> v{1,2,3};
|
||||||
//! piCout << v; // {1, 2, 3}
|
//! piCout << v; // {1, 2, 3}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
inline PIVector(std::initializer_list<T> init_list) {
|
inline PIVector(std::initializer_list<T> init_list): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
alloc(init_list.size());
|
alloc(init_list.size());
|
||||||
newT(piv_data, init_list.begin(), init_list.size());
|
newT(piv_data, init_list.begin(), init_list.size());
|
||||||
@@ -164,9 +166,9 @@ public:
|
|||||||
|
|
||||||
//! \~english Contructs array with size `size` filled elements `e`.
|
//! \~english Contructs array with size `size` filled elements `e`.
|
||||||
//! \~russian Создает массив из `size` элементов заполненных `e`.
|
//! \~russian Создает массив из `size` элементов заполненных `e`.
|
||||||
inline explicit PIVector(size_t size, const T & e = T()) {
|
inline PIVector(size_t size, const T & e = T()): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
expand(size, e);
|
resize(size, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
|
//! \~english Contructs array with size `size` and elements created by function `f(size_t i)`.
|
||||||
@@ -182,26 +184,24 @@ public:
|
|||||||
//! PIVector <int> v(5, [](size_t i){return i*2;});
|
//! PIVector <int> v(5, [](size_t i){return i*2;});
|
||||||
//! piCout << v; // {0, 2, 4, 6, 8}
|
//! piCout << v; // {0, 2, 4, 6, 8}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
inline PIVector(size_t size, std::function<T(size_t i)> f) {
|
inline PIVector(size_t size, std::function<T(size_t i)> f): piv_data(0), piv_size(0), piv_rsize(0) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
expand(size, f);
|
resize(size, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Move constructor.
|
//! \~english Move constructor.
|
||||||
//! \~russian Перемещающий конструктор.
|
//! \~russian Перемещающий конструктор.
|
||||||
inline PIVector(PIVector<T> && v) {
|
inline PIVector(PIVector<T> && v): piv_data(v.piv_data), piv_size(v.piv_size), piv_rsize(v.piv_rsize) {
|
||||||
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
PIINTROSPECTION_CONTAINER_NEW(T, sizeof(T))
|
||||||
piv_data = v.piv_data;
|
|
||||||
piv_size = v.piv_size;
|
|
||||||
piv_rsize = v.piv_rsize;
|
|
||||||
v._reset();
|
v._reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~PIVector() {
|
inline virtual ~PIVector() {
|
||||||
PIINTROSPECTION_CONTAINER_DELETE(T)
|
PIINTROSPECTION_CONTAINER_DELETE(T)
|
||||||
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
|
PIINTROSPECTION_CONTAINER_FREE(T, (piv_rsize))
|
||||||
deleteT(piv_data, piv_size);
|
deleteT(piv_data, piv_size);
|
||||||
dealloc();
|
dealloc();
|
||||||
|
_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Assign operator.
|
//! \~english Assign operator.
|
||||||
@@ -209,6 +209,7 @@ public:
|
|||||||
inline PIVector<T> & operator =(const PIVector<T> & v) {
|
inline PIVector<T> & operator =(const PIVector<T> & v) {
|
||||||
if (this == &v) return *this;
|
if (this == &v) return *this;
|
||||||
clear();
|
clear();
|
||||||
|
deleteT(piv_data, piv_size);
|
||||||
alloc(v.piv_size);
|
alloc(v.piv_size);
|
||||||
newT(piv_data, v.piv_data, piv_size);
|
newT(piv_data, v.piv_data, piv_size);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -223,12 +224,10 @@ public:
|
|||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
friend class PIVector<T>;
|
friend class PIVector<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
PIVector<T> * parent;
|
PIVector<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -248,7 +247,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline iterator operator ++(int) {
|
inline iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -257,7 +256,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline iterator operator --(int) {
|
inline iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -285,7 +284,9 @@ public:
|
|||||||
tmp -= p;
|
tmp -= p;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
friend inline std::ptrdiff_t operator-(const iterator & it1, const iterator & it2) { return it1.pos - it2.pos; }
|
friend inline std::ptrdiff_t operator -(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos - it2.pos;
|
||||||
|
}
|
||||||
|
|
||||||
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
|
friend inline iterator operator +(size_t p, const iterator & it) {return it + p;}
|
||||||
friend inline iterator operator +(const iterator & it, size_t p) {
|
friend inline iterator operator +(const iterator & it, size_t p) {
|
||||||
@@ -296,20 +297,26 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const iterator & it1, const iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const iterator & it1, const iterator & it2) {
|
||||||
friend inline bool operator<=(const iterator & it1, const iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const iterator & it1, const iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const iterator & it1, const iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const iterator & it1, const iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class const_iterator {
|
class const_iterator {
|
||||||
friend class PIVector<T>;
|
friend class PIVector<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline const_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline const_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIVector<T> * parent;
|
const PIVector<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -327,7 +334,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_iterator operator ++(int) {
|
inline const_iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -336,7 +343,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_iterator operator --(int) {
|
inline const_iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -364,7 +371,9 @@ public:
|
|||||||
tmp -= p;
|
tmp -= p;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
friend inline std::ptrdiff_t operator-(const const_iterator & it1, const const_iterator & it2) { return it1.pos - it2.pos; }
|
friend inline std::ptrdiff_t operator -(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos - it2.pos;
|
||||||
|
}
|
||||||
|
|
||||||
friend inline const_iterator operator +(size_t p, const const_iterator & it) {return it + p;}
|
friend inline const_iterator operator +(size_t p, const const_iterator & it) {return it + p;}
|
||||||
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
|
friend inline const_iterator operator +(const const_iterator & it, size_t p) {
|
||||||
@@ -375,20 +384,26 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const const_iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const const_iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const const_iterator & it1, const const_iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const const_iterator & it1, const const_iterator & it2) {
|
||||||
friend inline bool operator<=(const const_iterator & it1, const const_iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const const_iterator & it1, const const_iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const const_iterator & it1, const const_iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const const_iterator & it1, const const_iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class reverse_iterator {
|
class reverse_iterator {
|
||||||
friend class PIVector<T>;
|
friend class PIVector<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline reverse_iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline reverse_iterator(PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
PIVector<T> * parent;
|
PIVector<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -408,7 +423,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline reverse_iterator operator ++(int) {
|
inline reverse_iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -417,7 +432,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline reverse_iterator operator --(int) {
|
inline reverse_iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -445,7 +460,9 @@ public:
|
|||||||
tmp -= p;
|
tmp -= p;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
friend inline std::ptrdiff_t operator-(const reverse_iterator & it1, const reverse_iterator & it2) { return it2.pos - it1.pos; }
|
friend inline std::ptrdiff_t operator -(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it2.pos - it1.pos;
|
||||||
|
}
|
||||||
|
|
||||||
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
|
friend inline reverse_iterator operator +(size_t p, const reverse_iterator & it) {return it + p;}
|
||||||
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
|
friend inline reverse_iterator operator +(const reverse_iterator & it, size_t p) {
|
||||||
@@ -456,20 +473,26 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
friend inline bool operator<=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const reverse_iterator & it1, const reverse_iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const reverse_iterator & it1, const reverse_iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class const_reverse_iterator {
|
class const_reverse_iterator {
|
||||||
friend class PIVector<T>;
|
friend class PIVector<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline const_reverse_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
inline const_reverse_iterator(const PIVector<T> * v, ssize_t p): parent(v), pos(p) {}
|
||||||
const PIVector<T> * parent;
|
const PIVector<T> * parent;
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
@@ -486,7 +509,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_reverse_iterator operator ++(int) {
|
inline const_reverse_iterator operator ++(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
--*this;
|
--*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -495,7 +518,7 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const_reverse_iterator operator --(int) {
|
inline const_reverse_iterator operator --(int) {
|
||||||
const auto tmp = *this;
|
auto tmp = *this;
|
||||||
++*this;
|
++*this;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -536,10 +559,18 @@ public:
|
|||||||
|
|
||||||
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
inline bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);}
|
||||||
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
inline bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);}
|
||||||
friend inline bool operator<(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos < it2.pos; }
|
friend inline bool operator <(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
friend inline bool operator<=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos <= it2.pos; }
|
return it1.pos < it2.pos;
|
||||||
friend inline bool operator>(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos > it2.pos; }
|
}
|
||||||
friend inline bool operator>=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) { return it1.pos >= it2.pos; }
|
friend inline bool operator <=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
|
return it1.pos <= it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
|
return it1.pos > it2.pos;
|
||||||
|
}
|
||||||
|
friend inline bool operator >=(const const_reverse_iterator & it1, const const_reverse_iterator & it2) {
|
||||||
|
return it1.pos >= it2.pos;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \~english Iterator to the first element.
|
//! \~english Iterator to the first element.
|
||||||
@@ -614,7 +645,7 @@ public:
|
|||||||
inline size_t length() const {return piv_size;}
|
inline size_t length() const {return piv_size;}
|
||||||
|
|
||||||
//! \~english Number of elements that the container has currently allocated space for.
|
//! \~english Number of elements that the container has currently allocated space for.
|
||||||
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
|
//! \~russian Количество элементов, для которого сейчас выделена память контейнером.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english To find out the actual number of items, use the function \a size().
|
//! \~english To find out the actual number of items, use the function \a size().
|
||||||
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
|
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
|
||||||
@@ -622,18 +653,18 @@ public:
|
|||||||
inline size_t capacity() const {return piv_rsize;}
|
inline size_t capacity() const {return piv_rsize;}
|
||||||
|
|
||||||
//! \~english Checks if the container has no elements.
|
//! \~english Checks if the container has no elements.
|
||||||
//! \~russian Проверяет пуст ли массив.
|
//! \~russian Проверяет пуст ли контейнер.
|
||||||
//! \~\return
|
//! \~\return
|
||||||
//! \~english **true** if the container is empty, **false** otherwise
|
//! \~english **true** if the container is empty, **false** otherwise
|
||||||
//! \~russian **true** если массив пуст, **false** иначе.
|
//! \~russian **true** если контейнер пуст, **false** иначе.
|
||||||
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
||||||
inline bool isEmpty() const {return (piv_size == 0);}
|
inline bool isEmpty() const {return (piv_size == 0);}
|
||||||
|
|
||||||
//! \~english Checks if the container has elements.
|
//! \~english Checks if the container has elements.
|
||||||
//! \~russian Проверяет не пуст ли массив.
|
//! \~russian Проверяет не пуст ли контейнер.
|
||||||
//! \~\return
|
//! \~\return
|
||||||
//! \~english **true** if the container is not empty, **false** otherwise
|
//! \~english **true** if the container is not empty, **false** otherwise
|
||||||
//! \~russian **true** если массив не пуст, **false** иначе.
|
//! \~russian **true** если контейнер не пуст, **false** иначе.
|
||||||
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
|
||||||
inline bool isNotEmpty() const {return (piv_size > 0);}
|
inline bool isNotEmpty() const {return (piv_size > 0);}
|
||||||
|
|
||||||
@@ -717,35 +748,6 @@ public:
|
|||||||
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||||
inline const T & at(size_t index) const {return piv_data[index];}
|
inline const T & at(size_t index) const {return piv_data[index];}
|
||||||
|
|
||||||
|
|
||||||
//! \~english Returns the first element of the array that
|
|
||||||
//! passes the test implemented by the provided function `test`
|
|
||||||
//! or `def` if there is no such element.
|
|
||||||
//! \~russian Возвращает первый элемент массива, проходящего по условию,
|
|
||||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
|
||||||
//! \~\sa \a indexWhere()
|
|
||||||
inline const T & atWhere(std::function<bool(const T & e)> test, ssize_t start = 0, const T & def = T()) const {
|
|
||||||
const ssize_t i = indexWhere(test, start);
|
|
||||||
if (i < 0)
|
|
||||||
return def;
|
|
||||||
else
|
|
||||||
return at(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns the last element of the array that
|
|
||||||
//! passes the test implemented by the provided function `test`
|
|
||||||
//! or `def` if there is no such element.
|
|
||||||
//! \~russian Возвращает последний элемент массива, проходящего по условию,
|
|
||||||
//! заданному в передаваемой функции `test`, или `def` если такого элемента нет.
|
|
||||||
//! \~\sa \a lastIndexWhere()
|
|
||||||
inline const T & lastAtWhere(std::function<bool(const T & e)> test, ssize_t start = -1, const T & def = T()) const {
|
|
||||||
const ssize_t i = lastIndexWhere(test, start);
|
|
||||||
if (i < 0)
|
|
||||||
return def;
|
|
||||||
else
|
|
||||||
return at(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Last element.
|
//! \~english Last element.
|
||||||
//! \~russian Последний элемент массива.
|
//! \~russian Последний элемент массива.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -800,7 +802,7 @@ public:
|
|||||||
//! возвращается **false**, что означает, что массив даже не просматривается.
|
//! возвращается **false**, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIVector<int> v{1, 2, 3, 4};
|
//! PIVector<int> v{1, 2, 3, 4};
|
||||||
@@ -827,33 +829,6 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Tests if all elements of `v` exists in the array.
|
|
||||||
//! \~russian Проверяет наличие всех элементов `v` в массиве.
|
|
||||||
//! \~\details
|
|
||||||
//! \~\code
|
|
||||||
//! PIVector<int> v{1, 2, 3, 4};
|
|
||||||
//! piCout << v.contains({1,4}); // true
|
|
||||||
//! piCout << v.contains({1,5}); // false
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a every(), \a any(), \a entries(), \a forEach()
|
|
||||||
inline bool contains(const PIVector<T> & v, ssize_t start = 0) const {
|
|
||||||
if (start < 0) {
|
|
||||||
start = piv_size + start;
|
|
||||||
if (start < 0) start = 0;
|
|
||||||
}
|
|
||||||
for (const T & e: v) {
|
|
||||||
bool c = false;
|
|
||||||
for (size_t i = start; i < piv_size; ++i) {
|
|
||||||
if (e == piv_data[i]) {
|
|
||||||
c = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!c) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Count elements equal `e` in the array.
|
//! \~english Count elements equal `e` in the array.
|
||||||
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
|
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -870,7 +845,7 @@ public:
|
|||||||
//! возвращается 0, что означает, что массив даже не просматривается.
|
//! возвращается 0, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIVector<int> v{2, 2, 4, 2, 6};
|
//! PIVector<int> v{2, 2, 4, 2, 6};
|
||||||
@@ -910,7 +885,7 @@ public:
|
|||||||
//! возвращается 0, что означает, что массив даже не просматривается.
|
//! возвращается 0, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere()
|
//! \~\sa \a every(), \a any(), \a contains(), \a forEach(), \a indexWhere()
|
||||||
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
|
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
|
||||||
@@ -943,7 +918,7 @@ public:
|
|||||||
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIVector<int> v{2, 5, 9};
|
//! PIVector<int> v{2, 5, 9};
|
||||||
@@ -984,7 +959,7 @@ public:
|
|||||||
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
//! возвращается `-1`, что означает, что массив даже не просматривается.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу (слева на право).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
|
||||||
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIVector<PIString> v{"do", "re", "mi", "re"};
|
//! PIVector<PIString> v{"do", "re", "mi", "re"};
|
||||||
@@ -1024,7 +999,7 @@ public:
|
|||||||
//! c которого начинать поиск в обратном направлении.
|
//! c которого начинать поиск в обратном направлении.
|
||||||
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
|
||||||
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
||||||
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
||||||
//! и означает, что просматривается весь массив.
|
//! и означает, что просматривается весь массив.
|
||||||
@@ -1067,7 +1042,7 @@ public:
|
|||||||
//! c которого начинать поиск в обратном направлении.
|
//! c которого начинать поиск в обратном направлении.
|
||||||
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
//! Если индекс больше или равен длине массива, просматривается весь массив.
|
||||||
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
|
||||||
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу (справа на лево).
|
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
|
||||||
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
|
||||||
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
|
||||||
//! и означает, что просматривается весь массив.
|
//! и означает, что просматривается весь массив.
|
||||||
@@ -1134,7 +1109,7 @@ public:
|
|||||||
PIVector<T> getRange(size_t index, size_t count) const {
|
PIVector<T> getRange(size_t index, size_t count) const {
|
||||||
if (index >= piv_size || count == 0) return PIVector<T>();
|
if (index >= piv_size || count == 0) return PIVector<T>();
|
||||||
if (index + count > piv_size) count = piv_size - index;
|
if (index + count > piv_size) count = piv_size - index;
|
||||||
return PIVector(piv_data + index, count);
|
return PIVector(&(piv_data[index]), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Clear array, remove all elements.
|
//! \~english Clear array, remove all elements.
|
||||||
@@ -1144,13 +1119,16 @@ public:
|
|||||||
//! \~english Reserved memory will not be released.
|
//! \~english Reserved memory will not be released.
|
||||||
//! \~russian Зарезервированная память не освободится.
|
//! \~russian Зарезервированная память не освободится.
|
||||||
//! \~\sa \a resize()
|
//! \~\sa \a resize()
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector<T> & clear() {
|
inline PIVector<T> & clear() {
|
||||||
deleteT(piv_data, piv_size);
|
resize(0);
|
||||||
piv_size = 0;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector<T> & clear() {
|
inline PIVector<T> & clear() {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, piv_size)
|
PIINTROSPECTION_CONTAINER_UNUSED(T, piv_size)
|
||||||
piv_size = 0;
|
piv_size = 0;
|
||||||
@@ -1201,12 +1179,16 @@ public:
|
|||||||
//! \~english First does `resize(new_size)` then `fill(e)`.
|
//! \~english First does `resize(new_size)` then `fill(e)`.
|
||||||
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
|
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
|
||||||
//! \~\sa \a fill(), \a resize()
|
//! \~\sa \a fill(), \a resize()
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector<T> & assign(size_t new_size, const T & f) {
|
inline PIVector<T> & assign(size_t new_size, const T & f) {
|
||||||
resize(new_size);
|
resize(new_size);
|
||||||
return fill(f);
|
return fill(f);
|
||||||
}
|
}
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector<T> & assign(size_t new_size, const T & f) {
|
inline PIVector<T> & assign(size_t new_size, const T & f) {
|
||||||
_resizeRaw(new_size);
|
_resizeRaw(new_size);
|
||||||
return fill(f);
|
return fill(f);
|
||||||
@@ -1225,10 +1207,17 @@ public:
|
|||||||
//! \~\sa \a size(), \a clear()
|
//! \~\sa \a size(), \a clear()
|
||||||
inline PIVector<T> & resize(size_t new_size, const T & e = T()) {
|
inline PIVector<T> & resize(size_t new_size, const T & e = T()) {
|
||||||
if (new_size < piv_size) {
|
if (new_size < piv_size) {
|
||||||
deleteT(piv_data + new_size, piv_size - new_size);
|
T * de = &(piv_data[new_size]);
|
||||||
|
deleteT(de, piv_size - new_size);
|
||||||
piv_size = new_size;
|
piv_size = new_size;
|
||||||
} else if (new_size > piv_size) {
|
}
|
||||||
expand(new_size, e);
|
if (new_size > piv_size) {
|
||||||
|
size_t os = piv_size;
|
||||||
|
alloc(new_size);
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||||
|
for (size_t i = os; i < new_size; ++i) {
|
||||||
|
elementNew(piv_data + i, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1246,29 +1235,38 @@ public:
|
|||||||
//! \~\sa \a size(), \a clear()
|
//! \~\sa \a size(), \a clear()
|
||||||
inline PIVector<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
|
inline PIVector<T> & resize(size_t new_size, std::function<T(size_t i)> f) {
|
||||||
if (new_size < piv_size) {
|
if (new_size < piv_size) {
|
||||||
deleteT(piv_data + new_size, piv_size - new_size);
|
T * de = &(piv_data[new_size]);
|
||||||
|
deleteT(de, piv_size - new_size);
|
||||||
piv_size = new_size;
|
piv_size = new_size;
|
||||||
} else if (new_size > piv_size) {
|
}
|
||||||
expand(new_size, f);
|
if (new_size > piv_size) {
|
||||||
|
size_t os = piv_size;
|
||||||
|
alloc(new_size);
|
||||||
|
PIINTROSPECTION_CONTAINER_USED(T, (new_size-os))
|
||||||
|
for (size_t i = os; i < new_size; ++i) {
|
||||||
|
elementNew(piv_data + i, f(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector<T> & _resizeRaw(size_t new_size) {
|
inline PIVector<T> & _resizeRaw(size_t new_size) {
|
||||||
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
|
|
||||||
if (new_size > piv_size) {
|
if (new_size > piv_size) {
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size));
|
PIINTROSPECTION_CONTAINER_USED(T, (new_size-piv_size));
|
||||||
}
|
}
|
||||||
if (new_size < piv_size) {
|
if (new_size < piv_size) {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size));
|
PIINTROSPECTION_CONTAINER_UNUSED(T, (piv_size-new_size));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
alloc(new_size);
|
alloc(new_size);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void _copyRaw(T * dst, const T * src, size_t size) { newT(dst, src, size); }
|
inline void _copyRaw(T * dst, const T * src, size_t size) {
|
||||||
|
newT(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Attempts to allocate memory for at least `new_size` elements.
|
//! \~english Attempts to allocate memory for at least `new_size` elements.
|
||||||
//! \~russian Резервируется память под как минимум `new_size` элементов.
|
//! \~russian Резервируется память под как минимум `new_size` элементов.
|
||||||
@@ -1286,7 +1284,7 @@ public:
|
|||||||
//! \~\sa \a size(), \a capacity(), \a resize()
|
//! \~\sa \a size(), \a capacity(), \a resize()
|
||||||
inline PIVector<T> & reserve(size_t new_size) {
|
inline PIVector<T> & reserve(size_t new_size) {
|
||||||
if (new_size <= piv_rsize) return *this;
|
if (new_size <= piv_rsize) return *this;
|
||||||
const size_t os = piv_size;
|
size_t os = piv_size;
|
||||||
alloc(new_size);
|
alloc(new_size);
|
||||||
piv_size = os;
|
piv_size = os;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1306,8 +1304,8 @@ public:
|
|||||||
inline PIVector<T> & insert(size_t index, const T & e = T()) {
|
inline PIVector<T> & insert(size_t index, const T & e = T()) {
|
||||||
alloc(piv_size + 1);
|
alloc(piv_size + 1);
|
||||||
if (index < piv_size - 1) {
|
if (index < piv_size - 1) {
|
||||||
const size_t os = piv_size - index - 1;
|
size_t os = piv_size - index - 1;
|
||||||
memmove(reinterpret_cast<void *>(piv_data + index + 1), reinterpret_cast<const void *>(piv_data + index), os * sizeof(T));
|
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||||
}
|
}
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||||
elementNew(piv_data + index, e);
|
elementNew(piv_data + index, e);
|
||||||
@@ -1323,8 +1321,8 @@ public:
|
|||||||
inline PIVector<T> & insert(size_t index, T && e) {
|
inline PIVector<T> & insert(size_t index, T && e) {
|
||||||
alloc(piv_size + 1);
|
alloc(piv_size + 1);
|
||||||
if (index < piv_size - 1) {
|
if (index < piv_size - 1) {
|
||||||
const size_t os = piv_size - index - 1;
|
size_t os = piv_size - index - 1;
|
||||||
memmove(reinterpret_cast<void *>(piv_data + index + 1), reinterpret_cast<const void *>(piv_data + index), os * sizeof(T));
|
memmove((void*)(&(piv_data[index + 1])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||||
}
|
}
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
PIINTROSPECTION_CONTAINER_USED(T, 1)
|
||||||
elementNew(piv_data + index, std::move(e));
|
elementNew(piv_data + index, std::move(e));
|
||||||
@@ -1345,12 +1343,10 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(&v != this);
|
assert(&v != this);
|
||||||
const ssize_t os = piv_size - index;
|
ssize_t os = piv_size - index;
|
||||||
alloc(piv_size + v.piv_size);
|
alloc(piv_size + v.piv_size);
|
||||||
if (os > 0) {
|
if (os > 0) {
|
||||||
memmove(reinterpret_cast<void *>(piv_data + index + v.piv_size),
|
memmove((void*)(&(piv_data[index + v.piv_size])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||||
reinterpret_cast<const void *>(piv_data + index),
|
|
||||||
os * sizeof(T));
|
|
||||||
}
|
}
|
||||||
newT(piv_data + index, v.piv_data, v.piv_size);
|
newT(piv_data + index, v.piv_data, v.piv_size);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1367,13 +1363,10 @@ public:
|
|||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||||
//! \~\sa \a append(), \a prepend(), \a remove()
|
//! \~\sa \a append(), \a prepend(), \a remove()
|
||||||
inline PIVector<T> & insert(size_t index, std::initializer_list<T> init_list) {
|
inline PIVector<T> & insert(size_t index, std::initializer_list<T> init_list) {
|
||||||
if (init_list.size() == 0) return *this;
|
ssize_t os = piv_size - index;
|
||||||
const ssize_t os = piv_size - index;
|
|
||||||
alloc(piv_size + init_list.size());
|
alloc(piv_size + init_list.size());
|
||||||
if (os > 0) {
|
if (os > 0) {
|
||||||
memmove(reinterpret_cast<void *>(piv_data + index + init_list.size()),
|
memmove((void*)(&(piv_data[index + init_list.size()])), (const void*)(&(piv_data[index])), os * sizeof(T));
|
||||||
reinterpret_cast<const void *>(piv_data + index),
|
|
||||||
os * sizeof(T));
|
|
||||||
}
|
}
|
||||||
newT(piv_data + index, init_list.begin(), init_list.size());
|
newT(piv_data + index, init_list.begin(), init_list.size());
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1391,16 +1384,13 @@ public:
|
|||||||
inline PIVector<T> & remove(size_t index, size_t count = 1) {
|
inline PIVector<T> & remove(size_t index, size_t count = 1) {
|
||||||
if (count == 0) return *this;
|
if (count == 0) return *this;
|
||||||
if (index + count >= piv_size) {
|
if (index + count >= piv_size) {
|
||||||
if (index < piv_size) {
|
resize(index);
|
||||||
deleteT(piv_data + index, piv_size - index);
|
return *this;
|
||||||
piv_size = index;
|
|
||||||
}
|
}
|
||||||
} else {
|
size_t os = piv_size - index - count;
|
||||||
const size_t os = piv_size - index - count;
|
deleteT(&(piv_data[index]), count);
|
||||||
deleteT(piv_data + index, count);
|
memmove((void*)(&(piv_data[index])), (const void*)(&(piv_data[index + count])), os * sizeof(T));
|
||||||
memmove(reinterpret_cast<void *>(piv_data + index), reinterpret_cast<const void *>(piv_data + index + count), os * sizeof(T));
|
|
||||||
piv_size -= count;
|
piv_size -= count;
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1454,11 +1444,16 @@ public:
|
|||||||
//! Complexity `O(N·log(N))`.
|
//! Complexity `O(N·log(N))`.
|
||||||
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
|
//! \~russian Сохранность порядка элементов, имеющих одинаковое значение, не гарантируется.
|
||||||
//! Для сравнения элементов используется функция сравнения `comp`.
|
//! Для сравнения элементов используется функция сравнения `comp`.
|
||||||
//! Функция сравнения, возвращает `true` если первый аргумент меньше
|
//! Функция сравнения, возвращает `true` если первый аргумент меньше второго.
|
||||||
//! второго. Сигнатура функции сравнения должна быть эквивалентна следующей: \code bool comp(const T &a, const T &b); \endcode Сигнатура
|
//! Сигнатура функции сравнения должна быть эквивалентна следующей:
|
||||||
//! не обязана содержать const &, однако, функция не может изменять переданные объекты. Функция обязана возвращать `false` для
|
//! \code
|
||||||
//! одинаковых элементов, иначе это приведёт к неопределённому поведению программы и ошибкам памяти. Для сортировки используется функция
|
//! bool comp(const T &a, const T &b);
|
||||||
//! [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort). Сложность сортировки `O(N·log(N))`.
|
//! \endcode
|
||||||
|
//! Сигнатура не обязана содержать const &, однако, функция не может изменять переданные объекты.
|
||||||
|
//! Функция обязана возвращать `false` для одинаковых элементов,
|
||||||
|
//! иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
|
||||||
|
//! Для сортировки используется функция [std::sort](https://ru.cppreference.com/w/cpp/algorithm/sort).
|
||||||
|
//! Сложность сортировки `O(N·log(N))`.
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIVector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
|
//! PIVector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
|
||||||
//! v.sort([](const int & a, const int & b){return a > b;});
|
//! v.sort([](const int & a, const int & b){return a > b;});
|
||||||
@@ -1487,7 +1482,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a reversed()
|
//! \~\sa \a reversed()
|
||||||
inline PIVector<T> & reverse() {
|
inline PIVector<T> & reverse() {
|
||||||
const size_t s2 = piv_size / 2;
|
size_t s2 = piv_size/2;
|
||||||
for (size_t i = 0; i < s2; ++i) {
|
for (size_t i = 0; i < s2; ++i) {
|
||||||
piSwap<T>(piv_data[i], piv_data[piv_size-i-1]);
|
piSwap<T>(piv_data[i], piv_data[piv_size-i-1]);
|
||||||
}
|
}
|
||||||
@@ -1517,12 +1512,10 @@ public:
|
|||||||
//! Если `add_size < 0`, то с конца массива удаляются элементы.
|
//! Если `add_size < 0`, то с конца массива удаляются элементы.
|
||||||
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
|
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
|
||||||
//! \~\sa \a resize()
|
//! \~\sa \a resize()
|
||||||
inline PIVector<T> & enlarge(ssize_t add_size, const T & e = T()) {
|
inline PIVector<T> & enlarge(llong add_size, const T & e = T()) {
|
||||||
const ssize_t ns = size_s() + add_size;
|
llong ns = size_s() + add_size;
|
||||||
if (ns <= 0)
|
if (ns <= 0) clear();
|
||||||
clear();
|
else resize(size_t(ns), e);
|
||||||
else
|
|
||||||
resize(size_t(ns), e);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1640,8 +1633,7 @@ public:
|
|||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||||
//! \~\sa \a push_back()
|
//! \~\sa \a push_back()
|
||||||
inline PIVector<T> & push_back(std::initializer_list<T> init_list) {
|
inline PIVector<T> & push_back(std::initializer_list<T> init_list) {
|
||||||
if (init_list.size() == 0) return *this;
|
size_t ps = piv_size;
|
||||||
const size_t ps = piv_size;
|
|
||||||
alloc(piv_size + init_list.size());
|
alloc(piv_size + init_list.size());
|
||||||
newT(piv_data + ps, init_list.begin(), init_list.size());
|
newT(piv_data + ps, init_list.begin(), init_list.size());
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1654,14 +1646,13 @@ public:
|
|||||||
//! \~russian Перегруженая функция.
|
//! \~russian Перегруженая функция.
|
||||||
//! \~\sa \a push_back()
|
//! \~\sa \a push_back()
|
||||||
inline PIVector<T> & push_back(const PIVector<T> & v) {
|
inline PIVector<T> & push_back(const PIVector<T> & v) {
|
||||||
if (v.isEmpty()) return *this;
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (&v == this) {
|
if (&v == this) {
|
||||||
printf("error with PIVector<%s>::push_back\n", __PIP_TYPENAME__(T));
|
printf("error with PIVector<%s>::push_back\n", __PIP_TYPENAME__(T));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(&v != this);
|
assert(&v != this);
|
||||||
const size_t ps = piv_size;
|
size_t ps = piv_size;
|
||||||
alloc(piv_size + v.piv_size);
|
alloc(piv_size + v.piv_size);
|
||||||
newT(piv_data + ps, v.piv_data, v.piv_size);
|
newT(piv_data + ps, v.piv_data, v.piv_size);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1776,7 +1767,10 @@ public:
|
|||||||
//! piCout << v; // {5, 4, 1, 2, 3}
|
//! piCout << v; // {5, 4, 1, 2, 3}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
|
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
|
||||||
inline PIVector<T> & push_front(const T & e) { return insert(0, e); }
|
inline PIVector<T> & push_front(const T & e) {
|
||||||
|
insert(0, e);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Appends the given element `e` to the begin of the array.
|
//! \~english Appends the given element `e` to the begin of the array.
|
||||||
//! \~russian Добавляет элемент `e` в начало массива.
|
//! \~russian Добавляет элемент `e` в начало массива.
|
||||||
@@ -1784,7 +1778,10 @@ public:
|
|||||||
//! \~english Overloaded function.
|
//! \~english Overloaded function.
|
||||||
//! \~russian Перегруженая функция.
|
//! \~russian Перегруженая функция.
|
||||||
//! \~\sa \a push_front()
|
//! \~\sa \a push_front()
|
||||||
inline PIVector<T> & push_front(T && e) { return insert(0, std::move(e)); }
|
inline PIVector<T> & push_front(T && e) {
|
||||||
|
insert(0, std::move(e));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Appends the given array `v` to the begin of the array.
|
//! \~english Appends the given array `v` to the begin of the array.
|
||||||
//! \~russian Добавляет массив `v` в начало массива.
|
//! \~russian Добавляет массив `v` в начало массива.
|
||||||
@@ -1797,7 +1794,10 @@ public:
|
|||||||
//! piCout << v; // {4, 5, 1, 2, 3}
|
//! piCout << v; // {4, 5, 1, 2, 3}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a push_front()
|
//! \~\sa \a push_front()
|
||||||
inline PIVector<T> & push_front(const PIVector<T> & v) { return insert(0, v); }
|
inline PIVector<T> & push_front(const PIVector<T> & v) {
|
||||||
|
insert(0, v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Appends the given elements to the begin of the array.
|
//! \~english Appends the given elements to the begin of the array.
|
||||||
//! \~russian Добавляет элементы в начало массива.
|
//! \~russian Добавляет элементы в начало массива.
|
||||||
@@ -1809,7 +1809,10 @@ public:
|
|||||||
//! Добавляет элементы из
|
//! Добавляет элементы из
|
||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||||||
//! \~\sa \a append()
|
//! \~\sa \a append()
|
||||||
inline PIVector<T> & push_front(std::initializer_list<T> init_list) { return insert(0, init_list); }
|
inline PIVector<T> & push_front(std::initializer_list<T> init_list) {
|
||||||
|
insert(0, init_list);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//! \~english Appends the given element `e` to the begin of the array.
|
//! \~english Appends the given element `e` to the begin of the array.
|
||||||
//! \~russian Добавляет элемент `e` в начало массива.
|
//! \~russian Добавляет элемент `e` в начало массива.
|
||||||
@@ -1877,8 +1880,7 @@ public:
|
|||||||
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
|
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
|
||||||
inline PIVector<T> & pop_back() {
|
inline PIVector<T> & pop_back() {
|
||||||
if (piv_size == 0) return *this;
|
if (piv_size == 0) return *this;
|
||||||
deleteT(piv_data + piv_size - 1, 1);
|
resize(piv_size - 1);
|
||||||
piv_size = piv_size - 1;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1913,7 +1915,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
||||||
inline T take_back() {
|
inline T take_back() {
|
||||||
const T e(back());
|
T e(back());
|
||||||
pop_back();
|
pop_back();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -1928,7 +1930,7 @@ public:
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
|
||||||
inline T take_front() {
|
inline T take_front() {
|
||||||
const T e(front());
|
T e(front());
|
||||||
pop_front();
|
pop_front();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -1944,8 +1946,7 @@ public:
|
|||||||
//! \~\sa \a map()
|
//! \~\sa \a map()
|
||||||
template <typename ST>
|
template <typename ST>
|
||||||
inline PIVector<ST> toType() const {
|
inline PIVector<ST> toType() const {
|
||||||
PIVector<ST> ret;
|
PIVector<ST> ret; ret.reserve(piv_size);
|
||||||
ret.reserve(piv_size);
|
|
||||||
for (size_t i = 0; i < piv_size; ++i) {
|
for (size_t i = 0; i < piv_size; ++i) {
|
||||||
ret << ST(piv_data[i]);
|
ret << ST(piv_data[i]);
|
||||||
}
|
}
|
||||||
@@ -1953,9 +1954,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Returns a new array with all elements
|
//! \~english Returns a new array with all elements
|
||||||
//! that pass the test implemented by the provided function `bool test(const T & e)`.
|
//! that pass the test implemented by the provided function `test`.
|
||||||
//! \~russian Возвращает новый массив со всеми элементами,
|
//! \~russian Возвращает новый массив со всеми элементами,
|
||||||
//! прошедшими проверку, задаваемую в передаваемой функции `bool test(const T & e)`.
|
//! прошедшими проверку, задаваемую в передаваемой функции `test`.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIVector<int> v{3, 2, 5, 2, 7};
|
//! PIVector<int> v{3, 2, 5, 2, 7};
|
||||||
@@ -1971,39 +1972,6 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a filter() but with `index` parameter in `test`.
|
|
||||||
//! \~russian Аналогично \a filter() но с параметром индекса `index` в функции `test`.
|
|
||||||
//! \~\sa \a filter()
|
|
||||||
inline PIVector<T> filterIndexed(std::function<bool(size_t index, const T & e)> test) const {
|
|
||||||
PIVector<T> ret;
|
|
||||||
for (size_t i = 0; i < piv_size; ++i) {
|
|
||||||
if (test(i, piv_data[i])) ret << piv_data[i];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a filter() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a filter() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a filter()
|
|
||||||
inline PIVector<T> filterReverse(std::function<bool(const T & e)> test) const {
|
|
||||||
PIVector<T> ret;
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
if (test(piv_data[i])) ret << piv_data[i];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a filterReverse() but with `index` parameter in `test`.
|
|
||||||
//! \~russian Аналогично \a filterReverse() но с параметром индекса `index` в функции `test`.
|
|
||||||
//! \~\sa \a filterReverse()
|
|
||||||
inline PIVector<T> filterReverseIndexed(std::function<bool(size_t index, const T & e)> test) const {
|
|
||||||
PIVector<T> ret;
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
if (test(i, piv_data[i])) ret << piv_data[i];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Execute function `void f(const T & e)` for every element in array.
|
//! \~english Execute function `void f(const T & e)` for every element in array.
|
||||||
//! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива.
|
//! \~russian Выполняет функцию `void f(const T & e)` для каждого элемента массива.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -2044,63 +2012,6 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a forEach() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a forEach() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\sa \a forEach()
|
|
||||||
inline void forEachIndexed(std::function<void(size_t index, const T & e)> f) const {
|
|
||||||
for (size_t i = 0; i < piv_size; ++i) {
|
|
||||||
f(i, piv_data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachIndexed(), but allows you to change the elements of the array.
|
|
||||||
//! \~russian Аналогично \a forEachIndexed(), но позволяет изменять элементы массива.
|
|
||||||
//! \~\sa \a forEach(), \a forEachIndexed()
|
|
||||||
inline PIVector<T> & forEachIndexed(std::function<void(size_t index, T & e)> f) {
|
|
||||||
for (size_t i = 0; i < piv_size; ++i) {
|
|
||||||
f(i, piv_data[i]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEach() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a forEach() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a forEach()
|
|
||||||
inline void forEachReverse(std::function<void(const T & e)> f) const {
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
f(piv_data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachReverse(), but allows you to change the elements of the array.
|
|
||||||
//! \~russian Аналогично \a forEachReverse(), но позволяет изменять элементы массива.
|
|
||||||
//! \~\sa \a forEach(), \a forEachReverse()
|
|
||||||
inline PIVector<T> & forEachReverse(std::function<void(T & e)> f) {
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
f(piv_data[i]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachIndexed() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a forEachIndexed() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a forEachIndexed(), \a forEachReverse(), \a forEach()
|
|
||||||
inline void forEachReverseIndexed(std::function<void(size_t index, const T & e)> f) const {
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
f(i, piv_data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a forEachReverseIndexed(), but allows you to change the elements of the array.
|
|
||||||
//! \~russian Аналогично \a forEachReverseIndexed(), но позволяет изменять элементы массива.
|
|
||||||
//! \~\sa \a forEachReverseIndexed(), \a forEachIndexed(), \a forEachReverse(), \a forEach()
|
|
||||||
inline PIVector<T> & forEachReverseIndexed(std::function<void(size_t index, T & e)> f) {
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
f(i, piv_data[i]);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Сreates a new array populated with the results
|
//! \~english Сreates a new array populated with the results
|
||||||
//! of calling a provided function `ST f(const T & e)` on every element in the calling array.
|
//! of calling a provided function `ST f(const T & e)` on every element in the calling array.
|
||||||
//! \~russian Создаёт новый массив с результатом вызова указанной функции
|
//! \~russian Создаёт новый массив с результатом вызова указанной функции
|
||||||
@@ -2115,73 +2026,18 @@ public:
|
|||||||
//! \~\code
|
//! \~\code
|
||||||
//! PIVector<int> v{1, 2, 3};
|
//! PIVector<int> v{1, 2, 3};
|
||||||
//! PIVector<PIString> sl = v.map<PIString>([](const int & i){return PIString::fromNumber(i);});
|
//! PIVector<PIString> sl = v.map<PIString>([](const int & i){return PIString::fromNumber(i);});
|
||||||
//! piCout << sl; // {"1", "2", "3"}
|
//! piCout << sl; {"1", "2", "3"}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a forEach(), \a reduce()
|
//! \~\sa \a forEach(), \a reduce()
|
||||||
template <typename ST>
|
template <typename ST>
|
||||||
inline PIVector<ST> map(std::function<ST(const T & e)> f) const {
|
inline PIVector<ST> map(std::function<ST(const T & e)> f) const {
|
||||||
PIVector<ST> ret;
|
PIVector<ST> ret; ret.reserve(piv_size);
|
||||||
ret.reserve(piv_size);
|
|
||||||
for (size_t i = 0; i < piv_size; ++i) {
|
for (size_t i = 0; i < piv_size; ++i) {
|
||||||
ret << f(piv_data[i]);
|
ret << f(piv_data[i]);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a map() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a map() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\code
|
|
||||||
//! PIVector<int> v{1, 2, 3};
|
|
||||||
//! PIVector<PIString> sl = v.mapIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
|
|
||||||
//! piCout << sl; // {"0", "1", "2"}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a map()
|
|
||||||
template<typename ST>
|
|
||||||
inline PIVector<ST> mapIndexed(std::function<ST(size_t index, const T & e)> f) const {
|
|
||||||
PIVector<ST> ret;
|
|
||||||
ret.reserve(piv_size);
|
|
||||||
for (size_t i = 0; i < piv_size; ++i) {
|
|
||||||
ret << f(i, piv_data[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a map() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a map() но от конца до начала (справа на лево).
|
|
||||||
//! \~\code
|
|
||||||
//! PIVector<int> v{1, 2, 3};
|
|
||||||
//! PIVector<PIString> sl = v.mapReverse<PIString>([](const int & i){return PIString::fromNumber(i);});
|
|
||||||
//! piCout << sl; // {"3", "2", "1"}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a map()
|
|
||||||
template<typename ST>
|
|
||||||
inline PIVector<ST> mapReverse(std::function<ST(const T & e)> f) const {
|
|
||||||
PIVector<ST> ret;
|
|
||||||
ret.reserve(piv_size);
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
ret << f(piv_data[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a mapReverse() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a mapReverse() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\code
|
|
||||||
//! PIVector<int> v{1, 2, 3};
|
|
||||||
//! PIVector<PIString> sl = v.mapReverseIndexed<PIString>([](size_t index, const int & i){return PIString::fromNumber(index);});
|
|
||||||
//! piCout << sl; // {"2", "1", "0"}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a mapReverse()
|
|
||||||
template<typename ST>
|
|
||||||
inline PIVector<ST> mapReverseIndexed(std::function<ST(size_t index, const T & e)> f) const {
|
|
||||||
PIVector<ST> ret;
|
|
||||||
ret.reserve(piv_size);
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
ret << f(i, piv_data[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Applies the function `ST f(const T & e, const ST & acc)`
|
//! \~english Applies the function `ST f(const T & e, const ST & acc)`
|
||||||
//! to each element of the array (from left to right), returns one value.
|
//! to each element of the array (from left to right), returns one value.
|
||||||
//! \~russian Применяет функцию `ST f(const T & e, const ST & acc)`
|
//! \~russian Применяет функцию `ST f(const T & e, const ST & acc)`
|
||||||
@@ -2232,42 +2088,6 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Same as \a reduce() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a reduce() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\sa \a reduce()
|
|
||||||
template<typename ST>
|
|
||||||
inline ST reduceIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
|
||||||
ST ret(initial);
|
|
||||||
for (size_t i = 0; i < piv_size; ++i) {
|
|
||||||
ret = f(i, piv_data[i], ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a reduce() but from end to begin (from right to left).
|
|
||||||
//! \~russian Аналогично \a reduce() но от конца до начала (справа на лево).
|
|
||||||
//! \~\sa \a reduce()
|
|
||||||
template<typename ST>
|
|
||||||
inline ST reduceReverse(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
|
||||||
ST ret(initial);
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
ret = f(piv_data[i], ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Same as \a reduceReverse() but with `index` parameter in `f`.
|
|
||||||
//! \~russian Аналогично \a reduceReverse() но с параметром индекса `index` в функции `f`.
|
|
||||||
//! \~\sa \a reduceReverse()
|
|
||||||
template<typename ST>
|
|
||||||
inline ST reduceReverseIndexed(std::function<ST(size_t index, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
|
|
||||||
ST ret(initial);
|
|
||||||
for (ssize_t i = piv_size; i >= 0; --i) {
|
|
||||||
ret = f(i, piv_data[i], ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
|
//! \~english Changes the dimension of the array, creates a two-dimensional array from a one-dimensional array.
|
||||||
//! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
|
//! \~russian Изменяет размерность массива, из одномерного массива создает двухмерный.
|
||||||
//! \~\details
|
//! \~\details
|
||||||
@@ -2296,7 +2116,7 @@ public:
|
|||||||
assert(rows*cols == piv_size);
|
assert(rows*cols == piv_size);
|
||||||
PIVector<PIVector<T>> ret;
|
PIVector<PIVector<T>> ret;
|
||||||
if (isEmpty()) return ret;
|
if (isEmpty()) return ret;
|
||||||
ret.expand(rows);
|
ret.resize(rows);
|
||||||
if (order == ReshapeByRow) {
|
if (order == ReshapeByRow) {
|
||||||
for (size_t r = 0; r < rows; r++) {
|
for (size_t r = 0; r < rows; r++) {
|
||||||
ret[r] = PIVector<T>(&(piv_data[r*cols]), cols);
|
ret[r] = PIVector<T>(&(piv_data[r*cols]), cols);
|
||||||
@@ -2327,12 +2147,14 @@ public:
|
|||||||
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
|
//! piCout << xv.flatten<int>(); // {1, 2, 3, 4, 5, 6}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a map(), \a reduce(), \a reshape()
|
//! \~\sa \a map(), \a reduce(), \a reshape()
|
||||||
template<typename C, typename std::enable_if<std::is_same<T, PIVector<C>>::value, int>::type = 0>
|
template<typename C, typename std::enable_if<
|
||||||
|
std::is_same<T, PIVector<C>>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector<C> flatten(ReshapeOrder order = ReshapeByRow) const {
|
inline PIVector<C> flatten(ReshapeOrder order = ReshapeByRow) const {
|
||||||
PIVector<C> ret;
|
PIVector<C> ret;
|
||||||
if (isEmpty()) return ret;
|
if (isEmpty()) return ret;
|
||||||
const size_t rows = size();
|
size_t rows = size();
|
||||||
const size_t cols = at(0).size();
|
size_t cols = at(0).size();
|
||||||
ret.reserve(rows * cols);
|
ret.reserve(rows * cols);
|
||||||
if (order == ReshapeByRow) {
|
if (order == ReshapeByRow) {
|
||||||
for (size_t r = 0; r < rows; r++) {
|
for (size_t r = 0; r < rows; r++) {
|
||||||
@@ -2368,195 +2190,96 @@ public:
|
|||||||
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
|
//! piCout << xv.reshape<int>(2,3); // {{1, 2, 3}, {4, 5, 6}}
|
||||||
//! \endcode
|
//! \endcode
|
||||||
//! \~\sa \a map(), \a reduce(), \a reshape()
|
//! \~\sa \a map(), \a reduce(), \a reshape()
|
||||||
template<typename C, typename std::enable_if<std::is_same<T, PIVector<C>>::value, int>::type = 0>
|
template<typename C, typename std::enable_if<
|
||||||
|
std::is_same<T, PIVector<C>>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector<PIVector<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
|
inline PIVector<PIVector<C>> reshape(size_t rows, size_t cols, ReshapeOrder order = ReshapeByRow) const {
|
||||||
PIVector<C> fl = flatten<C>();
|
PIVector<C> fl = flatten<C>();
|
||||||
return fl.reshape(rows, cols, order);
|
return fl.reshape(rows, cols, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \~english Divides an array into a two-dimensional array using the separator `separator`.
|
|
||||||
//! \~russian Разделяет массив на двумерный массив с помощью разделителя`separator`.
|
|
||||||
//! \~\code
|
|
||||||
//! PIVector<int> v{1, 2, 3, 99, 4, 5, 99, 6};
|
|
||||||
//! piCout << v.split(99); // {{1, 2, 3}, {4, 5}, {6}}
|
|
||||||
//! \endcode
|
|
||||||
//! \~\sa \a splitBySize()
|
|
||||||
inline PIVector<PIVector<T>> split(const T & separator) const {
|
|
||||||
PIVector<PIVector<T>> ret;
|
|
||||||
if (isEmpty()) return ret;
|
|
||||||
size_t start = 0;
|
|
||||||
ssize_t ci = indexOf(separator, start);
|
|
||||||
while (ci >= 0) {
|
|
||||||
ret << PIVector<T>(piv_data + start, ci - start);
|
|
||||||
start = ci + 1;
|
|
||||||
ci = indexOf(separator, start);
|
|
||||||
}
|
|
||||||
if (start < piv_size) {
|
|
||||||
ret << PIVector<T>(piv_data + start, piv_size - start);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Divides an array into a two-dimensional array in chunks of no more than `sz`.
|
|
||||||
//! \~russian Разделяет массив на двумерный массив по кускам не более чем `sz`.
|
|
||||||
//! \~\sa \a split()
|
|
||||||
inline PIVector<PIVector<T>> splitBySize(size_t sz) const {
|
|
||||||
PIVector<PIVector<T>> ret;
|
|
||||||
if (isEmpty() || sz == 0) return ret;
|
|
||||||
const size_t ch = piv_size / sz;
|
|
||||||
for (size_t i = 0; i < ch; ++i) {
|
|
||||||
ret << PIVector<T>(piv_data + sz * i, sz);
|
|
||||||
}
|
|
||||||
const size_t t = ch * sz;
|
|
||||||
if (t < piv_size) {
|
|
||||||
ret << PIVector<T>(piv_data + t, piv_size - t);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Cut sub-array of this array.
|
|
||||||
//! \~russian Вырезает подмассив, то есть кусок из текущего массива.
|
|
||||||
//! \~english
|
|
||||||
//! \param index - index of this array where sub-array starts
|
|
||||||
//! \param count - sub-array size
|
|
||||||
//! \~russian
|
|
||||||
//! \param index - индекс в текущем массиве, откуда начинётся подмассив
|
|
||||||
//! \param count - размер подмассива
|
|
||||||
//! \~\details
|
|
||||||
//! \~english
|
|
||||||
//! Index must be in range from `0` to `size()-1`.
|
|
||||||
//! If sub-array size more than this array size, than ends early.
|
|
||||||
//! \~russian
|
|
||||||
//! Индекс начала должен лежать в диапазоне от `0` до `size()-1`.
|
|
||||||
//! Если заданный размер подмассива превышает размер текущего массива,
|
|
||||||
//! то вернется подмассив меньшего размера (`size()-index-1`).
|
|
||||||
inline PIVector<T> takeRange(size_t index, size_t count) {
|
|
||||||
PIVector<T> ret;
|
|
||||||
if (index >= piv_size || count == 0) return ret;
|
|
||||||
if (index + count > piv_size) count = piv_size - index;
|
|
||||||
ret.alloc(count);
|
|
||||||
memcpy(reinterpret_cast<void *>(ret.piv_data), reinterpret_cast<const void *>(piv_data + index), count * sizeof(T));
|
|
||||||
const size_t os = piv_size - index - count;
|
|
||||||
if (os > 0) {
|
|
||||||
memmove(reinterpret_cast<void *>(piv_data + index), reinterpret_cast<const void *>(piv_data + index + count), os * sizeof(T));
|
|
||||||
piv_size -= count;
|
|
||||||
} else {
|
|
||||||
piv_size = index;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void _reset() {
|
inline void _reset() {piv_size = piv_rsize = 0; piv_data = 0;}
|
||||||
piv_size = 0;
|
|
||||||
piv_rsize = 0;
|
|
||||||
piv_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t asize(size_t s) {
|
inline size_t asize(size_t s) {
|
||||||
if (s == 0) return 0;
|
if (s == 0) return 0;
|
||||||
if (piv_rsize * 2 >= s && piv_rsize < s) {
|
if (piv_rsize + piv_rsize >= s && piv_rsize < s) {
|
||||||
return piv_rsize * 2;
|
return piv_rsize + piv_rsize;
|
||||||
}
|
}
|
||||||
ssize_t t = _PIContainerConstants<T>::minCountPoT();
|
ssize_t t = _PIContainerConstants<T>::minCountPoT(), s_ = s - 1;
|
||||||
s -= 1;
|
while (s_ >> t)
|
||||||
while (s >> t)
|
|
||||||
++t;
|
++t;
|
||||||
return (1 << t);
|
return (1 << t);
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline void newT(T * dst, const T * src, size_t s) {
|
inline void newT(T * dst, const T * src, size_t s) {
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||||
for (size_t i = 0; i < s; ++i) {
|
for (size_t i = 0; i < s; ++i)
|
||||||
elementNew(dst + i, src[i]);
|
elementNew(dst + i, src[i]);
|
||||||
}
|
}
|
||||||
}
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
, int>::type = 0>
|
||||||
inline void newT(T * dst, const T * src, size_t s) {
|
inline void newT(T * dst, const T * src, size_t s) {
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, s)
|
PIINTROSPECTION_CONTAINER_USED(T, s)
|
||||||
memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<const void *>(src), s * sizeof(T));
|
memcpy((void*)(dst), (const void*)(src), s * sizeof(T));
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
!std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline void deleteT(T * d, size_t sz) {
|
inline void deleteT(T * d, size_t sz) {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||||
if (d != nullptr) {
|
if ((uchar*)d != 0) {
|
||||||
for (size_t i = 0; i < sz; ++i) {
|
for (size_t i = 0; i < sz; ++i) {
|
||||||
elementDelete(d[i]);
|
elementDelete(d[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline void deleteT(T * d, size_t sz) {
|
inline void deleteT(T * d, size_t sz) {
|
||||||
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
PIINTROSPECTION_CONTAINER_UNUSED(T, sz)
|
||||||
}
|
}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
!std::is_trivially_copyable<T1>::value
|
||||||
inline void elementNew(T * to, const T & from) {
|
, int>::type = 0>
|
||||||
new (to) T(from);
|
inline void elementNew(T * to, const T & from) {new(to)T(from);}
|
||||||
}
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
!std::is_trivially_copyable<T1>::value
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
, int>::type = 0>
|
||||||
inline void elementNew(T * to, T && from) {
|
inline void elementNew(T * to, T && from) {new(to)T(std::move(from));}
|
||||||
new (to) T(std::move(from));
|
template<typename T1 = T, typename std::enable_if<
|
||||||
}
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
inline void elementNew(T1 * to, const T & from) {(*to) = from;}
|
||||||
inline void elementNew(T1 * to, const T & from) {
|
template<typename T1 = T, typename std::enable_if<
|
||||||
(*to) = from;
|
std::is_trivially_copyable<T1>::value
|
||||||
}
|
, int>::type = 0>
|
||||||
|
inline void elementNew(T * to, T && from) {(*to) = std::move(from);}
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
inline void elementNew(T * to, T && from) {
|
!std::is_trivially_copyable<T1>::value
|
||||||
(*to) = std::move(from);
|
, int>::type = 0>
|
||||||
}
|
inline void elementDelete(T & from) {from.~T();}
|
||||||
|
template<typename T1 = T, typename std::enable_if<
|
||||||
template<typename T1 = T, typename std::enable_if<!std::is_trivially_copyable<T1>::value, int>::type = 0>
|
std::is_trivially_copyable<T1>::value
|
||||||
inline void elementDelete(T & from) {
|
, int>::type = 0>
|
||||||
from.~T();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
|
||||||
inline void elementDelete(T & from) {}
|
inline void elementDelete(T & from) {}
|
||||||
|
|
||||||
inline void dealloc() {
|
inline void dealloc() {
|
||||||
if (piv_data != nullptr) {
|
if ((uchar*)piv_data != 0) free((uchar*)piv_data);
|
||||||
free(reinterpret_cast<void *>(piv_data));
|
piv_data = 0;
|
||||||
piv_data = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inline void expand(size_t new_size, const T & e = T()) {
|
|
||||||
const size_t os = piv_size;
|
|
||||||
alloc(new_size);
|
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
|
|
||||||
for (size_t i = os; i < new_size; ++i) {
|
|
||||||
elementNew(piv_data + i, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void expand(size_t new_size, std::function<T(size_t i)> f) {
|
|
||||||
const size_t os = piv_size;
|
|
||||||
alloc(new_size);
|
|
||||||
PIINTROSPECTION_CONTAINER_USED(T, (new_size - os))
|
|
||||||
for (size_t i = os; i < new_size; ++i) {
|
|
||||||
elementNew(piv_data + i, f(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void alloc(size_t new_size) {
|
inline void alloc(size_t new_size) {
|
||||||
if (new_size <= piv_rsize) {
|
if (new_size <= piv_rsize) {
|
||||||
piv_size = new_size;
|
piv_size = new_size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
piv_size = new_size;
|
piv_size = new_size;
|
||||||
const size_t as = asize(new_size);
|
size_t as = asize(new_size);
|
||||||
if (as == piv_rsize) return;
|
if (as == piv_rsize) return;
|
||||||
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-piv_rsize))
|
PIINTROSPECTION_CONTAINER_ALLOC(T, (as-piv_rsize))
|
||||||
T * p_d = reinterpret_cast<T *>(realloc(reinterpret_cast<void *>(piv_data), as * sizeof(T)));
|
T * p_d = (T*)(realloc((void*)(piv_data), as*sizeof(T)));
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (!p_d) {
|
if (!p_d) {
|
||||||
printf("error with PIVector<%s>::alloc\n", __PIP_TYPENAME__(T));
|
printf("error with PIVector<%s>::alloc\n", __PIP_TYPENAME__(T));
|
||||||
@@ -2567,9 +2290,8 @@ private:
|
|||||||
piv_rsize = as;
|
piv_rsize = as;
|
||||||
}
|
}
|
||||||
|
|
||||||
T * piv_data = nullptr;
|
T * piv_data;
|
||||||
size_t piv_size = 0;
|
size_t piv_size, piv_rsize;
|
||||||
size_t piv_rsize = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -2594,7 +2316,7 @@ inline std::ostream & operator<<(std::ostream & s, const PIVector<T> & v) {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline PICout operator <<(PICout s, const PIVector<T> & v) {
|
inline PICout operator <<(PICout s, const PIVector<T> & v) {
|
||||||
s.space();
|
s.space();
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "{";
|
s << "{";
|
||||||
for (size_t i = 0; i < v.size(); ++i) {
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
s << v[i];
|
s << v[i];
|
||||||
@@ -2603,13 +2325,11 @@ inline PICout operator<<(PICout s, const PIVector<T> & v) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
s << "}";
|
s << "}";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void piSwap(PIVector<T> & f, PIVector<T> & s) {
|
inline void piSwap(PIVector<T> & f, PIVector<T> & s) {f.swap(s);}
|
||||||
f.swap(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // PIVECTOR_H
|
#endif // PIVECTOR_H
|
||||||
|
|||||||
@@ -39,17 +39,17 @@ template<typename T>
|
|||||||
class PIVector2D {
|
class PIVector2D {
|
||||||
public:
|
public:
|
||||||
inline PIVector2D() {rows_ = cols_ = 0;}
|
inline PIVector2D() {rows_ = cols_ = 0;}
|
||||||
|
|
||||||
inline PIVector2D(size_t rows, size_t cols, const T & f = T()) {
|
inline PIVector2D(size_t rows, size_t cols, const T & f = T()) {
|
||||||
rows_ = rows;
|
rows_ = rows;
|
||||||
cols_ = cols;
|
cols_ = cols;
|
||||||
mat.resize(rows*cols, f);
|
mat.resize(rows*cols, f);
|
||||||
}
|
}
|
||||||
|
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v) : rows_(rows), cols_(cols), mat(v) {
|
||||||
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v): rows_(rows), cols_(cols), mat(v) { mat.resize(rows * cols); }
|
mat.resize(rows*cols);
|
||||||
|
}
|
||||||
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v): rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows * cols); }
|
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v) : rows_(rows), cols_(cols), mat(std::move(v)) {
|
||||||
|
mat.resize(rows*cols);
|
||||||
|
}
|
||||||
inline PIVector2D(const PIVector<PIVector<T>> & v) {
|
inline PIVector2D(const PIVector<PIVector<T>> & v) {
|
||||||
rows_ = v.size();
|
rows_ = v.size();
|
||||||
if (rows_) {
|
if (rows_) {
|
||||||
@@ -64,32 +64,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline size_t rows() const {return rows_;}
|
inline size_t rows() const {return rows_;}
|
||||||
|
|
||||||
inline size_t cols() const {return cols_;}
|
inline size_t cols() const {return cols_;}
|
||||||
|
|
||||||
inline size_t size() const {return mat.size();}
|
inline size_t size() const {return mat.size();}
|
||||||
|
|
||||||
inline ssize_t size_s() const {return mat.size_s();}
|
inline ssize_t size_s() const {return mat.size_s();}
|
||||||
|
|
||||||
inline size_t length() const {return mat.length();}
|
inline size_t length() const {return mat.length();}
|
||||||
|
|
||||||
inline size_t capacity() const {return mat.capacity();}
|
inline size_t capacity() const {return mat.capacity();}
|
||||||
|
|
||||||
inline bool isEmpty() const {return mat.isEmpty();}
|
inline bool isEmpty() const {return mat.isEmpty();}
|
||||||
|
|
||||||
inline bool isNotEmpty() const { return mat.isNotEmpty(); }
|
|
||||||
|
|
||||||
class Row {
|
class Row {
|
||||||
friend class PIVector2D<T>;
|
friend class PIVector2D<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline Row(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
|
inline Row(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;}
|
||||||
st_ = p->cols_ * row;
|
|
||||||
sz_ = p->cols_;
|
|
||||||
}
|
|
||||||
PIVector<T> * p_;
|
PIVector<T> * p_;
|
||||||
size_t st_, sz_;
|
size_t st_, sz_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline size_t size() const {return sz_;}
|
inline size_t size() const {return sz_;}
|
||||||
inline T & operator [](size_t index) {return (*p_)[st_ + index];}
|
inline T & operator [](size_t index) {return (*p_)[st_ + index];}
|
||||||
@@ -98,12 +85,12 @@ public:
|
|||||||
inline const T * data(size_t index = 0) const {return p_->data(st_ + index);}
|
inline const T * data(size_t index = 0) const {return p_->data(st_ + index);}
|
||||||
inline Row & operator =(const Row & other) {
|
inline Row & operator =(const Row & other) {
|
||||||
if (p_ == other.p_ && st_ == other.st_) return *this;
|
if (p_ == other.p_ && st_ == other.st_) return *this;
|
||||||
const size_t sz = piMin<size_t>(sz_, other.sz_);
|
size_t sz = piMin<size_t>(sz_, other.sz_);
|
||||||
p_->_copyRaw(p_->data(st_), other.data(), sz);
|
p_->_copyRaw(p_->data(st_), other.data(), sz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline Row & operator =(const PIVector<T> & other) {
|
inline Row & operator =(const PIVector<T> & other) {
|
||||||
const size_t sz = piMin<size_t>(sz, other.size());
|
size_t sz = piMin<size_t>(sz, other.size());
|
||||||
p_->_copyRaw(p_->data(st_), other.data(), sz);
|
p_->_copyRaw(p_->data(st_), other.data(), sz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -112,16 +99,10 @@ public:
|
|||||||
|
|
||||||
class Col {
|
class Col {
|
||||||
friend class PIVector2D<T>;
|
friend class PIVector2D<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline Col(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
|
inline Col(PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;}
|
||||||
step_ = p->cols_;
|
|
||||||
row_ = row;
|
|
||||||
sz_ = p->rows_;
|
|
||||||
}
|
|
||||||
PIVector<T> * p_;
|
PIVector<T> * p_;
|
||||||
size_t step_, row_, sz_;
|
size_t step_, row_, sz_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline size_t size() const {return sz_;}
|
inline size_t size() const {return sz_;}
|
||||||
inline T & operator [](size_t index) {return (*p_)[index * step_ + row_];}
|
inline T & operator [](size_t index) {return (*p_)[index * step_ + row_];}
|
||||||
@@ -130,37 +111,29 @@ public:
|
|||||||
inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);}
|
inline const T * data(size_t index = 0) const {return p_->data(index * step_ + row_);}
|
||||||
inline Col & operator =(const Col & other) {
|
inline Col & operator =(const Col & other) {
|
||||||
if (p_ == other.p_ && row_ == other.row_) return *this;
|
if (p_ == other.p_ && row_ == other.row_) return *this;
|
||||||
const size_t sz = piMin<size_t>(sz_, other.sz_);
|
size_t sz = piMin<size_t>(sz_, other.sz_);
|
||||||
for (int i = 0; i < sz; ++i)
|
for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i];
|
||||||
(*p_)[i * step_ + row_] = other[i];
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline Row & operator =(const PIVector<T> & other) {
|
inline Row & operator =(const PIVector<T> & other) {
|
||||||
const size_t sz = piMin<size_t>(sz_, other.size());
|
size_t sz = piMin<size_t>(sz_, other.size());
|
||||||
for (int i = 0; i < sz; ++i)
|
for (int i=0; i<sz; ++i) (*p_)[i * step_ + row_] = other[i];
|
||||||
(*p_)[i * step_ + row_] = other[i];
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline PIVector<T> toVector() const {
|
inline PIVector<T> toVector() const {
|
||||||
PIVector<T> ret;
|
PIVector<T> ret;
|
||||||
ret.reserve(sz_);
|
ret.reserve(sz_);
|
||||||
for (size_t i = 0; i < sz_; i++)
|
for (size_t i=0; i<sz_; i++) ret << (*p_)[i * step_ + row_];
|
||||||
ret << (*p_)[i * step_ + row_];
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RowConst {
|
class RowConst {
|
||||||
friend class PIVector2D<T>;
|
friend class PIVector2D<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
|
inline RowConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {st_ = p->cols_ * row; sz_ = p->cols_;}
|
||||||
st_ = p->cols_ * row;
|
|
||||||
sz_ = p->cols_;
|
|
||||||
}
|
|
||||||
const PIVector<T> * p_;
|
const PIVector<T> * p_;
|
||||||
size_t st_, sz_;
|
size_t st_, sz_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline size_t size() const {return sz_;}
|
inline size_t size() const {return sz_;}
|
||||||
inline const T & operator [](size_t index) const {return (*p_)[st_ + index];}
|
inline const T & operator [](size_t index) const {return (*p_)[st_ + index];}
|
||||||
@@ -170,16 +143,10 @@ public:
|
|||||||
|
|
||||||
class ColConst {
|
class ColConst {
|
||||||
friend class PIVector2D<T>;
|
friend class PIVector2D<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline ColConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
|
inline ColConst(const PIVector2D<T> * p, size_t row) : p_(&(p->mat)) {step_ = p->cols_; row_ = row; sz_ = p->rows_;}
|
||||||
step_ = p->cols_;
|
|
||||||
row_ = row;
|
|
||||||
sz_ = p->rows_;
|
|
||||||
}
|
|
||||||
const PIVector<T> * p_;
|
const PIVector<T> * p_;
|
||||||
size_t step_, row_, sz_;
|
size_t step_, row_, sz_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline size_t size() const {return p_->rows_;}
|
inline size_t size() const {return p_->rows_;}
|
||||||
inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];}
|
inline const T & operator [](size_t index) const {return (*p_)[index * step_ + row_];}
|
||||||
@@ -187,8 +154,7 @@ public:
|
|||||||
inline PIVector<T> toVector() const {
|
inline PIVector<T> toVector() const {
|
||||||
PIVector<T> ret;
|
PIVector<T> ret;
|
||||||
ret.reserve(sz_);
|
ret.reserve(sz_);
|
||||||
for (int i = 0; i < size(); i++)
|
for (int i=0; i<size(); i++) ret << (*p_)[i * step_ + row_];
|
||||||
ret << (*p_)[i * step_ + row_];
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -206,24 +172,24 @@ public:
|
|||||||
inline Col col(size_t index) {return Col(this, index);}
|
inline Col col(size_t index) {return Col(this, index);}
|
||||||
inline ColConst col(size_t index) const {return ColConst(this, index);}
|
inline ColConst col(size_t index) const {return ColConst(this, index);}
|
||||||
inline PIVector2D<T> & setRow(size_t row, const Row & other) {
|
inline PIVector2D<T> & setRow(size_t row, const Row & other) {
|
||||||
const size_t sz = piMin<size_t>(cols_, other.sz_);
|
size_t sz = piMin<size_t>(cols_, other.sz_);
|
||||||
mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
|
mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline PIVector2D<T> & setRow(size_t row, const RowConst & other) {
|
inline PIVector2D<T> & setRow(size_t row, const RowConst & other) {
|
||||||
const size_t sz = piMin<size_t>(cols_, other.sz_);
|
size_t sz = piMin<size_t>(cols_, other.sz_);
|
||||||
mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
|
mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) {
|
inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) {
|
||||||
const size_t sz = piMin<size_t>(cols_, other.size());
|
size_t sz = piMin<size_t>(cols_, other.size());
|
||||||
mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
|
mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline PIVector2D<T> & addRow(const Row & other) {
|
inline PIVector2D<T> & addRow(const Row & other) {
|
||||||
if (cols_ == 0) cols_ = other.sz_;
|
if (cols_ == 0) cols_ = other.sz_;
|
||||||
const size_t sz = piMin<size_t>(cols_, other.sz_);
|
size_t sz = piMin<size_t>(cols_, other.sz_);
|
||||||
const size_t ps = mat.size();
|
size_t ps = mat.size();
|
||||||
mat.resize(mat.size() + cols_);
|
mat.resize(mat.size() + cols_);
|
||||||
mat._copyRaw(mat.data(ps), other.data(), sz);
|
mat._copyRaw(mat.data(ps), other.data(), sz);
|
||||||
rows_++;
|
rows_++;
|
||||||
@@ -231,8 +197,8 @@ public:
|
|||||||
}
|
}
|
||||||
inline PIVector2D<T> & addRow(const RowConst & other) {
|
inline PIVector2D<T> & addRow(const RowConst & other) {
|
||||||
if (cols_ == 0) cols_ = other.sz_;
|
if (cols_ == 0) cols_ = other.sz_;
|
||||||
const size_t sz = piMin<size_t>(cols_, other.sz_);
|
size_t sz = piMin<size_t>(cols_, other.sz_);
|
||||||
const size_t ps = mat.size();
|
size_t ps = mat.size();
|
||||||
mat.resize(mat.size() + cols_);
|
mat.resize(mat.size() + cols_);
|
||||||
mat._copyRaw(mat.data(ps), other.data(), sz);
|
mat._copyRaw(mat.data(ps), other.data(), sz);
|
||||||
rows_++;
|
rows_++;
|
||||||
@@ -240,8 +206,8 @@ public:
|
|||||||
}
|
}
|
||||||
inline PIVector2D<T> & addRow(const PIVector<T> & other) {
|
inline PIVector2D<T> & addRow(const PIVector<T> & other) {
|
||||||
if (cols_ == 0) cols_ = other.size();
|
if (cols_ == 0) cols_ = other.size();
|
||||||
const size_t sz = piMin<size_t>(cols_, other.size());
|
size_t sz = piMin<size_t>(cols_, other.size());
|
||||||
const size_t ps = mat.size();
|
size_t ps = mat.size();
|
||||||
mat.resize(mat.size() + cols_);
|
mat.resize(mat.size() + cols_);
|
||||||
mat._copyRaw(mat.data(ps), other.data(), sz);
|
mat._copyRaw(mat.data(ps), other.data(), sz);
|
||||||
rows_++;
|
rows_++;
|
||||||
@@ -251,7 +217,7 @@ public:
|
|||||||
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) {
|
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) {
|
||||||
mat.resize(rows*cols_, f);
|
mat.resize(rows*cols_, f);
|
||||||
rows_ = rows;
|
rows_ = rows;
|
||||||
const int cs = (cols - cols_);
|
int cs = (cols - cols_);
|
||||||
if (cs < 0) {
|
if (cs < 0) {
|
||||||
for (size_t r=0; r<rows; ++r) {
|
for (size_t r=0; r<rows; ++r) {
|
||||||
mat.remove(r*cols + cols, -cs);
|
mat.remove(r*cols + cols, -cs);
|
||||||
@@ -271,24 +237,22 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator ==(const PIVector2D<T> & t) const {
|
inline bool operator ==(const PIVector2D<T> & t) const {
|
||||||
if (cols_ != t.cols_ || rows_ != t.rows_) return false;
|
if (cols_ != t.cols_ || rows_ != t.rows_)
|
||||||
|
return false;
|
||||||
return mat == t.mat;
|
return mat == t.mat;
|
||||||
}
|
}
|
||||||
inline bool operator !=(const PIVector2D<T> & t) const {return !(*this == t);}
|
inline bool operator !=(const PIVector2D<T> & t) const {return !(*this == t);}
|
||||||
|
|
||||||
inline PIVector<PIVector<T>> toVectors() const {
|
PIVector<PIVector<T> > toVectors() const {
|
||||||
PIVector<PIVector<T> > ret;
|
PIVector<PIVector<T> > ret;
|
||||||
ret.reserve(rows_);
|
ret.reserve(rows_);
|
||||||
for(size_t i = 0; i < rows_; ++i)
|
for(size_t i = 0; i < rows_; ++i)
|
||||||
ret << PIVector<T>(mat.data(i*cols_), cols_);
|
ret << PIVector<T>(mat.data(i*cols_), cols_);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
PIVector<T> toPlainVector() const {return mat;}
|
||||||
inline PIVector<T> toPlainVector() const { return mat; }
|
PIVector<T> & plainVector() {return mat;}
|
||||||
|
const PIVector<T> & plainVector() const {return mat;}
|
||||||
inline PIVector<T> & plainVector() { return mat; }
|
|
||||||
|
|
||||||
inline const PIVector<T> & plainVector() const { return mat; }
|
|
||||||
|
|
||||||
inline void swap(PIVector2D<T> & other) {
|
inline void swap(PIVector2D<T> & other) {
|
||||||
mat.swap(other.mat);
|
mat.swap(other.mat);
|
||||||
@@ -296,7 +260,9 @@ public:
|
|||||||
piSwap<size_t>(cols_, other.cols_);
|
piSwap<size_t>(cols_, other.cols_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
|
template<typename T1 = T, typename std::enable_if<
|
||||||
|
std::is_trivially_copyable<T1>::value
|
||||||
|
, int>::type = 0>
|
||||||
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
|
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
|
||||||
rows_ = r;
|
rows_ = r;
|
||||||
cols_ = c;
|
cols_ = c;
|
||||||
@@ -309,14 +275,11 @@ public:
|
|||||||
mat.clear();
|
mat.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ST>
|
void forEach(std::function<void(const T &)> f) const {
|
||||||
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const {
|
mat.forEach(f);
|
||||||
return PIVector2D<ST>(rows_, cols_, mat.map(f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void forEach(std::function<void(const T &)> f) const { mat.forEach(f); }
|
PIVector2D<T> & forEach(std::function<void(T &)> f) {
|
||||||
|
|
||||||
inline PIVector2D<T> & forEach(std::function<void(T &)> f) {
|
|
||||||
mat.forEach(f);
|
mat.forEach(f);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -329,7 +292,7 @@ protected:
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
|
inline PICout operator <<(PICout s, const PIVector2D<T> & v) {
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "{";
|
s << "{";
|
||||||
for (size_t i = 0; i < v.rows(); ++i) {
|
for (size_t i = 0; i < v.rows(); ++i) {
|
||||||
s << "{ ";
|
s << "{ ";
|
||||||
@@ -342,7 +305,7 @@ inline PICout operator<<(PICout s, const PIVector2D<T> & v) {
|
|||||||
}
|
}
|
||||||
if (v.isEmpty()) s << "{ }";
|
if (v.isEmpty()) s << "{ }";
|
||||||
s << "}";
|
s << "}";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,20 +34,370 @@
|
|||||||
#ifndef PIBASE_H
|
#ifndef PIBASE_H
|
||||||
#define PIBASE_H
|
#define PIBASE_H
|
||||||
|
|
||||||
#include "pibase_macros.h"
|
#include "pip_version.h"
|
||||||
|
#include "piplatform.h"
|
||||||
#include "pip_export.h"
|
#include "pip_export.h"
|
||||||
|
#include "pip_defs.h"
|
||||||
#include <string.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
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Major value of PIP version
|
||||||
|
//! \~russian Мажорная версия PIP
|
||||||
|
# define PIP_VERSION_MAJOR
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Minor value of PIP version
|
||||||
|
//! \~russian Минорная версия PIP
|
||||||
|
# define PIP_VERSION_MINOR
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Revision value of PIP version
|
||||||
|
//! \~russian Ревизия версии PIP
|
||||||
|
# define PIP_VERSION_REVISION
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Suffix of PIP version
|
||||||
|
//! \~russian Суффикс версии PIP
|
||||||
|
# define PIP_VERSION_SUFFIX
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
||||||
|
//! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision)
|
||||||
|
# define PIP_VERSION
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when compile-time debug is enabled
|
||||||
|
//! \~russian Макрос объявлен когда включена compile-time отладка
|
||||||
|
# define PIP_DEBUG
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when operation system is any Windows
|
||||||
|
//! \~russian Макрос объявлен когда операционная система Windows
|
||||||
|
# define WINDOWS
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when operation system is QNX or Blackberry
|
||||||
|
//! \~russian Макрос объявлен когда операционная система QNX или Blackberry
|
||||||
|
# define QNX
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when operation system is Blackberry
|
||||||
|
//! \~russian Макрос объявлен когда операционная система Blackberry
|
||||||
|
# define BLACKBERRY
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when operation system is FreeBSD
|
||||||
|
//! \~russian Макрос объявлен когда операционная система FreeBSD
|
||||||
|
# define FREE_BSD
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when operation system is Mac OS
|
||||||
|
//! \~russian Макрос объявлен когда операционная система Mac OS
|
||||||
|
# define MAC_OS
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when operation system is Android
|
||||||
|
//! \~russian Макрос объявлен когда операционная система Android
|
||||||
|
# define ANDROID
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when operation system is any Linux
|
||||||
|
//! \~russian Макрос объявлен когда операционная система Linux
|
||||||
|
# define LINUX
|
||||||
|
|
||||||
|
//! \~\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
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro is defined when PIP is decided that host is support language
|
||||||
|
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
|
||||||
|
# define HAS_LOCALE
|
||||||
|
|
||||||
|
//! \~\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
|
||||||
|
|
||||||
|
//! \~\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
|
||||||
|
|
||||||
|
//! \~\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
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro to declare private section, "export" is optional
|
||||||
|
//! \~russian Макрос для объявления частной секции, "export" необязателен
|
||||||
|
# define PRIVATE_DECLARATION(export)
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro to start definition of private section
|
||||||
|
//! \~russian Макрос для начала реализации частной секции
|
||||||
|
# define PRIVATE_DEFINITION_START(Class)
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro to end definition of private section
|
||||||
|
//! \~russian Макрос для окончания реализации частной секции
|
||||||
|
# define PRIVATE_DEFINITION_END(Class)
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro to access private section by pointer
|
||||||
|
//! \~russian Макрос для доступа к частной секции
|
||||||
|
# define PRIVATE
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro to access private section by pointer without brakes ()
|
||||||
|
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
|
||||||
|
# define PRIVATEWB
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro to start static initializer
|
||||||
|
//! \~russian Макрос для начала статической инициализации
|
||||||
|
# define STATIC_INITIALIZER_BEGIN
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro to end static initializer
|
||||||
|
//! \~russian Макрос для окончания статической инициализации
|
||||||
|
# define STATIC_INITIALIZER_END
|
||||||
|
|
||||||
|
#undef MICRO_PIP
|
||||||
|
#undef FREERTOS
|
||||||
|
#endif //DOXYGEN
|
||||||
|
|
||||||
#ifdef CC_AVR_GCC
|
#ifdef CC_AVR_GCC
|
||||||
# include <ArduinoSTL.h>
|
# include <ArduinoSTL.h>
|
||||||
#endif
|
#endif
|
||||||
#include <atomic>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <initializer_list>
|
#include <cstddef>
|
||||||
|
#include <cassert>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#ifdef WINDOWS
|
||||||
|
# ifdef CC_VC
|
||||||
|
# define SHUT_RDWR 2
|
||||||
|
# pragma comment(lib, "Ws2_32.lib")
|
||||||
|
# pragma comment(lib, "Iphlpapi.lib")
|
||||||
|
# pragma comment(lib, "Psapi.lib")
|
||||||
|
# ifdef ARCH_BITS_32
|
||||||
|
# define _X86_
|
||||||
|
# else
|
||||||
|
# define _IA64_
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define SHUT_RDWR SD_BOTH
|
||||||
|
# endif
|
||||||
|
typedef int socklen_t;
|
||||||
|
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;}
|
||||||
|
//inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAC_OS
|
||||||
|
# define environ (*_NSGetEnviron())
|
||||||
|
typedef long time_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINUX
|
||||||
|
# define environ __environ
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FREE_BSD
|
||||||
|
extern char ** environ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NO_UNUSED
|
||||||
|
# define NO_UNUSED(x) (void)x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef assert
|
||||||
|
# define assert(x)
|
||||||
|
# define assertm(exp, msg)
|
||||||
|
#else
|
||||||
|
# define assertm(exp, msg) assert(((void)msg, exp))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MICRO_PIP
|
||||||
|
# define __PIP_TYPENAME__(T) "?"
|
||||||
|
#else
|
||||||
|
# define __PIP_TYPENAME__(T) typeid(T).name()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CC_GCC
|
||||||
|
# undef DEPRECATED
|
||||||
|
# define DEPRECATED __attribute__((deprecated))
|
||||||
|
# if CC_GCC_VERSION > 0x025F // > 2.95
|
||||||
|
# ifdef LINUX
|
||||||
|
# define HAS_LOCALE
|
||||||
|
# endif
|
||||||
|
# ifdef MAC_OS
|
||||||
|
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
|
||||||
|
# pragma GCC diagnostic ignored "-Wc++11-extensions"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# ifdef ANDROID
|
||||||
|
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
# pragma GCC diagnostic ignored "-Wextra"
|
||||||
|
# pragma GCC diagnostic ignored "-Wc++11-extensions"
|
||||||
|
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
|
||||||
|
//# pragma GCC diagnostic ignored "-Wliteral-suffix"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CC_VC
|
||||||
|
# undef DEPRECATED
|
||||||
|
# define DEPRECATED
|
||||||
|
# pragma warning(disable: 4018)
|
||||||
|
# pragma warning(disable: 4061)
|
||||||
|
# pragma warning(disable: 4100)
|
||||||
|
# pragma warning(disable: 4239)
|
||||||
|
# pragma warning(disable: 4242)
|
||||||
|
# pragma warning(disable: 4244)
|
||||||
|
# pragma warning(disable: 4251)
|
||||||
|
# pragma warning(disable: 4365)
|
||||||
|
# pragma warning(disable: 4512)
|
||||||
|
# pragma warning(disable: 4668)
|
||||||
|
# pragma warning(disable: 4710)
|
||||||
|
# pragma warning(disable: 4800)
|
||||||
|
# pragma warning(disable: 4820)
|
||||||
|
# pragma warning(disable: 4986)
|
||||||
|
# pragma warning(disable: 4996)
|
||||||
|
# ifdef ARCH_BITS_32
|
||||||
|
typedef long ssize_t;
|
||||||
|
# else
|
||||||
|
typedef long long ssize_t;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CC_OTHER
|
||||||
|
# undef DEPRECATED
|
||||||
|
# define DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //DOXYGEN
|
||||||
|
// Private data macros
|
||||||
|
#ifndef DOXYGEN
|
||||||
|
|
||||||
|
#define PRIVATE_DECLARATION(e) \
|
||||||
|
struct __Private__; \
|
||||||
|
friend struct __Private__; \
|
||||||
|
struct e __PrivateInitializer__ { \
|
||||||
|
__PrivateInitializer__(); \
|
||||||
|
__PrivateInitializer__(const __PrivateInitializer__ & o); \
|
||||||
|
~__PrivateInitializer__(); \
|
||||||
|
__PrivateInitializer__ & operator =(const __PrivateInitializer__ & o); \
|
||||||
|
__Private__ * p; \
|
||||||
|
}; \
|
||||||
|
__PrivateInitializer__ __privateinitializer__;
|
||||||
|
|
||||||
|
#define PRIVATE_DEFINITION_START(c) \
|
||||||
|
struct c::__Private__ {
|
||||||
|
|
||||||
|
#define PRIVATE_DEFINITION_END(c) \
|
||||||
|
}; \
|
||||||
|
c::__PrivateInitializer__::__PrivateInitializer__() {p = new c::__Private__();} \
|
||||||
|
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \
|
||||||
|
c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
|
||||||
|
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & ) {if (p) delete p; p = new c::__Private__(); return *this;}
|
||||||
|
|
||||||
|
#define PRIVATE (__privateinitializer__.p)
|
||||||
|
#define PRIVATEWB __privateinitializer__.p
|
||||||
|
|
||||||
|
#endif //DOXYGEN
|
||||||
|
|
||||||
|
#define NO_COPY_CLASS(name) \
|
||||||
|
name(const name&) = delete; \
|
||||||
|
name& operator=(const name&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
#define _PIP_ADD_COUNTER_WS(a, cnt) a##cnt
|
||||||
|
#define _PIP_ADD_COUNTER_WF(a, cnt) _PIP_ADD_COUNTER_WS(a, cnt)
|
||||||
|
#define _PIP_ADD_COUNTER(a) _PIP_ADD_COUNTER_WF(a, __COUNTER__)
|
||||||
|
|
||||||
|
|
||||||
|
#define STATIC_INITIALIZER_BEGIN \
|
||||||
|
class { \
|
||||||
|
class _Initializer_ { \
|
||||||
|
public: \
|
||||||
|
_Initializer_() {
|
||||||
|
|
||||||
|
#define STATIC_INITIALIZER_END \
|
||||||
|
} \
|
||||||
|
} _initializer_; \
|
||||||
|
} _PIP_ADD_COUNTER(_pip_initializer_);
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\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
|
||||||
|
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro used for infinite loop
|
||||||
|
//! \~russian Макрос для бесконечного цикла
|
||||||
|
#define FOREVER for (;;)
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro used for infinite wait
|
||||||
|
//! \~russian Макрос для бесконечного ожидания
|
||||||
|
#define FOREVER_WAIT FOREVER piMinSleep();
|
||||||
|
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english Macro used for infinite wait
|
||||||
|
//! \~russian Макрос для бесконечного ожидания
|
||||||
|
#define WAIT_FOREVER FOREVER piMinSleep();
|
||||||
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Global variable enabling output to piCout, default is true
|
//! \~english Global variable enabling output to piCout, default is true
|
||||||
@@ -75,12 +425,7 @@ typedef long double ldouble;
|
|||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english Example:\n \snippet piincludes.cpp swap
|
//! \~english Example:\n \snippet piincludes.cpp swap
|
||||||
//! \~russian Пример:\n \snippet piincludes.cpp swap
|
//! \~russian Пример:\n \snippet piincludes.cpp swap
|
||||||
template<typename T>
|
template<typename T> inline void piSwap(T & f, T & s) {T t(std::move(f)); f = std::move(s); s = std::move(t);}
|
||||||
inline void piSwap(T & f, T & s) {
|
|
||||||
T t(std::move(f));
|
|
||||||
f = std::move(s);
|
|
||||||
s = std::move(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function for swap two values without "="
|
//! \~english Templated function for swap two values without "="
|
||||||
@@ -88,8 +433,7 @@ inline void piSwap(T & f, T & s) {
|
|||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english Example:\n \snippet piincludes.cpp swapBinary
|
//! \~english Example:\n \snippet piincludes.cpp swapBinary
|
||||||
//! \~russian Пример:\n \snippet piincludes.cpp swapBinary
|
//! \~russian Пример:\n \snippet piincludes.cpp swapBinary
|
||||||
template<typename T>
|
template<typename T> inline void piSwapBinary(T & f, T & s) {
|
||||||
inline void piSwapBinary(T & f, T & s) {
|
|
||||||
if ((size_t*)&f == (size_t*)&s) return;
|
if ((size_t*)&f == (size_t*)&s) return;
|
||||||
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
|
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@@ -105,8 +449,7 @@ inline void piSwapBinary(T & f, T & s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<> inline void piSwapBinary(const void *& f, const void *& s) {
|
||||||
inline void piSwapBinary(const void *& f, const void *& s) {
|
|
||||||
if ((size_t*)f == (size_t*)s) return;
|
if ((size_t*)f == (size_t*)s) return;
|
||||||
size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *);
|
size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@@ -132,7 +475,8 @@ inline void piSwapBinary(const void *& f, const void *& s) {
|
|||||||
//! \~russian Пример:\n \snippet piincludes.cpp compareBinary
|
//! \~russian Пример:\n \snippet piincludes.cpp compareBinary
|
||||||
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
||||||
for (size_t i = 0; i < size; ++i)
|
for (size_t i = 0; i < size; ++i)
|
||||||
if (((const uchar *)f)[i] != ((const uchar *)s)[i]) return false;
|
if (((const uchar*)f)[i] != ((const uchar*)s)[i])
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,10 +500,7 @@ inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp round
|
//! \snippet piincludes.cpp round
|
||||||
template<typename T>
|
template<typename T> inline constexpr int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
|
||||||
inline constexpr int piRound(const T & v) {
|
|
||||||
return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function return floor of float falue
|
//! \~english Templated function return floor of float falue
|
||||||
@@ -181,10 +522,7 @@ inline constexpr int piRound(const T & v) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp floor
|
//! \snippet piincludes.cpp floor
|
||||||
template<typename T>
|
template<typename T> inline constexpr int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
|
||||||
inline constexpr int piFloor(const T & v) {
|
|
||||||
return v < T(0) ? int(v) - 1 : int(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function return ceil of float falue
|
//! \~english Templated function return ceil of float falue
|
||||||
@@ -206,10 +544,7 @@ inline constexpr int piFloor(const T & v) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp ceil
|
//! \snippet piincludes.cpp ceil
|
||||||
template<typename T>
|
template<typename T> inline constexpr int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
|
||||||
inline constexpr int piCeil(const T & v) {
|
|
||||||
return v < T(0) ? int(v) : int(v) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function return absolute of numeric falue
|
//! \~english Templated function return absolute of numeric falue
|
||||||
@@ -239,20 +574,11 @@ inline constexpr int piCeil(const T & v) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp abs
|
//! \snippet piincludes.cpp abs
|
||||||
template<typename T>
|
template<typename T> inline constexpr T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
||||||
inline constexpr T piAbs(const T & v) {
|
|
||||||
return (v >= T(0) ? v : -v);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr T piMin(const T & f, const T & s) {
|
|
||||||
return ((f > s) ? s : f);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function return minimum of several values
|
//! \~english Templated function return minimum of two values
|
||||||
//! \~russian Шаблонный метод, возвращающий минимум из нескольких значений
|
//! \~russian Шаблонный метод, возвращающий минимум из двух значений
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english
|
//! \~english
|
||||||
//! There are some macros:
|
//! There are some macros:
|
||||||
@@ -276,20 +602,39 @@ constexpr T piMin(const T & f, const T & s) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp min2
|
//! \snippet piincludes.cpp min2
|
||||||
template<typename T, typename... Args>
|
template<typename T> inline constexpr T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
|
||||||
constexpr T piMin(const T & f, const T & s, const Args &... args) {
|
|
||||||
return piMin<T>(piMin<T>(f, s), args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr T piMax(const T & f, const T & s) {
|
|
||||||
return ((f < s) ? s : f);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function return maximum of several values
|
//! \~english Templated function return minimum of tree values
|
||||||
//! \~russian Шаблонный метод, возвращающий максимум из нескольких значений
|
//! \~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
|
||||||
|
//! \~english Templated function return maximum of two values
|
||||||
|
//! \~russian Шаблонный метод, возвращающий максимум из двух значений
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english
|
//! \~english
|
||||||
//! There are some macros:
|
//! There are some macros:
|
||||||
@@ -313,11 +658,35 @@ constexpr T piMax(const T & f, const T & s) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp max2
|
//! \snippet piincludes.cpp max2
|
||||||
template<typename T, typename... Args>
|
template<typename T> inline constexpr T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
|
||||||
constexpr T piMax(const T & f, const T & s, const Args &... args) {
|
|
||||||
return piMax<T>(piMax<T>(f, s), args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//! \~\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
|
//! \~\brief
|
||||||
//! \~english Templated function return clamped value
|
//! \~english Templated function return clamped value
|
||||||
@@ -347,10 +716,7 @@ constexpr T piMax(const T & f, const T & s, const Args &... args) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp clamp
|
//! \snippet piincludes.cpp clamp
|
||||||
template<typename T>
|
template<typename T> inline constexpr T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
|
||||||
inline constexpr T piClamp(const T & v, const T & min, const T & max) {
|
|
||||||
return (v > max ? max : (v < min ? min : v));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
|
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
|
||||||
@@ -386,10 +752,7 @@ inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric
|
|||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function that inverse byte order of value "v"
|
//! \~english Templated function that inverse byte order of value "v"
|
||||||
//! \~russian Шаблонный метод, меняющий порядок байт в переменной "v"
|
//! \~russian Шаблонный метод, меняющий порядок байт в переменной "v"
|
||||||
template<typename T>
|
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
|
||||||
inline void piLetobe(T * v) {
|
|
||||||
piLetobe(v, sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Templated function that returns "v" with inversed byte order
|
//! \~english Templated function that returns "v" with inversed byte order
|
||||||
@@ -415,24 +778,12 @@ inline void piLetobe(T * v) {
|
|||||||
//!
|
//!
|
||||||
//! Пример:
|
//! Пример:
|
||||||
//! \snippet piincludes.cpp letobe
|
//! \snippet piincludes.cpp letobe
|
||||||
template<typename T>
|
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
|
||||||
inline T piLetobe(const T & v) {
|
|
||||||
T tv(v);
|
|
||||||
piLetobe(&tv, sizeof(T));
|
|
||||||
return tv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// specialization
|
// specialization
|
||||||
template<>
|
template<> inline uint16_t piLetobe(const uint16_t & v) {return (v << 8) | (v >> 8);}
|
||||||
inline uint16_t piLetobe(const uint16_t & v) {
|
template<> inline uint32_t piLetobe(const uint32_t & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
||||||
return (v << 8) | (v >> 8);
|
template<> inline float piLetobe(const float & v) {
|
||||||
}
|
|
||||||
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 {
|
union _pletobe_f {
|
||||||
_pletobe_f(const float &f_) {f = f_;}
|
_pletobe_f(const float &f_) {f = f_;}
|
||||||
float f;
|
float f;
|
||||||
@@ -485,98 +836,21 @@ inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> inline uint piHash(const T & v) {
|
||||||
inline uint piHash(const T & v) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<> inline uint piHash(const char & v) {return (uint)v;}
|
||||||
inline uint piHash(const char & v) {
|
template<> inline uint piHash(const uchar & v) {return (uint)v;}
|
||||||
return (uint)v;
|
template<> inline uint piHash(const short & v) {return (uint)v;}
|
||||||
}
|
template<> inline uint piHash(const ushort & v) {return (uint)v;}
|
||||||
template<>
|
template<> inline uint piHash(const int & v) {return (uint)v;}
|
||||||
inline uint piHash(const uchar & v) {
|
template<> inline uint piHash(const uint & v) {return (uint)v;}
|
||||||
return (uint)v;
|
template<> inline uint piHash(const llong & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||||
}
|
template<> inline uint piHash(const ullong & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||||
template<>
|
template<> inline uint piHash(const float & v) {return (uint)v;}
|
||||||
inline uint piHash(const short & v) {
|
template<> inline uint piHash(const double & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||||
return (uint)v;
|
template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const ushort & v) {
|
|
||||||
return (uint)v;
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const int & v) {
|
|
||||||
return (uint)v;
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const uint & v) {
|
|
||||||
return (uint)v;
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const llong & v) {
|
|
||||||
return piHashData((const uchar *)&v, sizeof(v));
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const ullong & v) {
|
|
||||||
return piHashData((const uchar *)&v, sizeof(v));
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const float & v) {
|
|
||||||
return (uint)v;
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const double & v) {
|
|
||||||
return piHashData((const uchar *)&v, sizeof(v));
|
|
||||||
}
|
|
||||||
template<>
|
|
||||||
inline uint piHash(const ldouble & v) {
|
|
||||||
return piHashData((const uchar *)&v, sizeof(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Call \b delete on each "container" element.
|
|
||||||
//! \~russian Вызывает \b delete на каждый элемент "container".
|
|
||||||
template<typename T>
|
|
||||||
inline void piDeleteAll(const T & container) {
|
|
||||||
for (auto i: container) {
|
|
||||||
delete i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Call \b delete on each element of
|
|
||||||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
|
||||||
//! \~russian Вызывает \b delete на каждый элемент
|
|
||||||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
|
||||||
template<typename T>
|
|
||||||
inline void piDeleteAll(std::initializer_list<T> container) {
|
|
||||||
for (auto i: container) {
|
|
||||||
delete i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Call \b delete on each "container" element and clear container.
|
|
||||||
//! \~russian Вызывает \b delete на каждый элемент "container" и очищает контейнер.
|
|
||||||
template<typename T>
|
|
||||||
inline void piDeleteAllAndClear(T & container) {
|
|
||||||
piDeleteAll(container);
|
|
||||||
container.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Call \b delete if "pointer" is not null and set it to null. Returns if deleted.
|
|
||||||
//! \~russian Вызывает \b delete на "pointer" если он не нулевой и устанавливает его в ноль. Возвращает было ли удаление.
|
|
||||||
template<typename T>
|
|
||||||
inline bool piDeleteSafety(T *& pointer) {
|
|
||||||
if (!pointer) return false;
|
|
||||||
delete pointer;
|
|
||||||
pointer = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define piRoundf piRound<float>
|
#define piRoundf piRound<float>
|
||||||
#define piRoundd piRound<double>
|
#define piRoundd piRound<double>
|
||||||
@@ -617,55 +891,4 @@ inline bool piDeleteSafety(T *& pointer) {
|
|||||||
#define piLetobef piLetobe<float>
|
#define piLetobef piLetobe<float>
|
||||||
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Class for executing a function upon scope exit
|
|
||||||
//! \~russian Класс для выполнения функции при выходе из области видимости
|
|
||||||
//! \~\details
|
|
||||||
//! \~english Example
|
|
||||||
//! \~russian Пример
|
|
||||||
//! \~\code
|
|
||||||
//! bool yourFunc() {
|
|
||||||
//! PIScopeExitCall error_call([]() { piCout << "Error!"; });
|
|
||||||
//! ...
|
|
||||||
//! if (!good0) {
|
|
||||||
//! ...
|
|
||||||
//! return false;
|
|
||||||
//! }
|
|
||||||
//! if (!good1) {
|
|
||||||
//! ...
|
|
||||||
//! return false;
|
|
||||||
//! }
|
|
||||||
//! ...
|
|
||||||
//! error_call.cancel();
|
|
||||||
//! return true;
|
|
||||||
//! }
|
|
||||||
//! \endcode
|
|
||||||
//! \~english In this example "Error!" will be printed on every \b false function return.
|
|
||||||
//! \~russian В данном примере будет выведен "Error!" при каждом \b false возврате из функции.
|
|
||||||
class PIP_EXPORT PIScopeExitCall {
|
|
||||||
public:
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Constructor that takes a function to execute
|
|
||||||
//! \~russian Конструктор, который принимает функцию для выполнения
|
|
||||||
explicit PIScopeExitCall(std::function<void()> f): func(f) {}
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Destructor that executes the function if it exists
|
|
||||||
//! \~russian Деструктор, который выполняет функцию, если она существует
|
|
||||||
~PIScopeExitCall() {
|
|
||||||
if (func) func();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Method for canceling the function
|
|
||||||
//! \~russian Метод для отмены функции
|
|
||||||
void cancel() { func = nullptr; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
NO_COPY_CLASS(PIScopeExitCall)
|
|
||||||
|
|
||||||
std::function<void()> func;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PIBASE_H
|
#endif // PIBASE_H
|
||||||
|
|||||||
@@ -1,419 +0,0 @@
|
|||||||
/*! \file pibase_macros.h
|
|
||||||
* \ingroup Core
|
|
||||||
* \~\brief
|
|
||||||
* \~english Base macros
|
|
||||||
* \~russian Базовые макросы
|
|
||||||
*
|
|
||||||
* \~\details
|
|
||||||
* \~english
|
|
||||||
* This file declares basic useful maros
|
|
||||||
* \~russian
|
|
||||||
* Этот файл объявляет основные вспомогательные макросы
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
PIP - Platform Independent Primitives
|
|
||||||
Base macros
|
|
||||||
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 PIBASE_MACROS_H
|
|
||||||
#define PIBASE_MACROS_H
|
|
||||||
|
|
||||||
#include "pip_defs.h"
|
|
||||||
#include "pip_version.h"
|
|
||||||
#include "piplatform.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
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Major value of PIP version
|
|
||||||
//! \~russian Мажорная версия PIP
|
|
||||||
# define PIP_VERSION_MAJOR
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Minor value of PIP version
|
|
||||||
//! \~russian Минорная версия PIP
|
|
||||||
# define PIP_VERSION_MINOR
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Revision value of PIP version
|
|
||||||
//! \~russian Ревизия версии PIP
|
|
||||||
# define PIP_VERSION_REVISION
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Suffix of PIP version
|
|
||||||
//! \~russian Суффикс версии PIP
|
|
||||||
# define PIP_VERSION_SUFFIX
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
|
||||||
//! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision)
|
|
||||||
# define PIP_VERSION
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when compile-time debug is enabled
|
|
||||||
//! \~russian Макрос объявлен когда включена compile-time отладка
|
|
||||||
# define PIP_DEBUG
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when operation system is any Windows
|
|
||||||
//! \~russian Макрос объявлен когда операционная система Windows
|
|
||||||
# define WINDOWS
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when operation system is QNX or Blackberry
|
|
||||||
//! \~russian Макрос объявлен когда операционная система QNX или Blackberry
|
|
||||||
# define QNX
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when operation system is Blackberry
|
|
||||||
//! \~russian Макрос объявлен когда операционная система Blackberry
|
|
||||||
# define BLACKBERRY
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when operation system is FreeBSD
|
|
||||||
//! \~russian Макрос объявлен когда операционная система FreeBSD
|
|
||||||
# define FREE_BSD
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when operation system is Mac OS
|
|
||||||
//! \~russian Макрос объявлен когда операционная система Mac OS
|
|
||||||
# define MAC_OS
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when operation system is Android
|
|
||||||
//! \~russian Макрос объявлен когда операционная система Android
|
|
||||||
# define ANDROID
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when operation system is any Linux
|
|
||||||
//! \~russian Макрос объявлен когда операционная система Linux
|
|
||||||
# define LINUX
|
|
||||||
|
|
||||||
//! \~\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
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro is defined when PIP is decided that host is support language
|
|
||||||
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
|
|
||||||
# define HAS_LOCALE
|
|
||||||
|
|
||||||
//! \~\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
|
|
||||||
|
|
||||||
//! \~\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
|
|
||||||
|
|
||||||
//! \~\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
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to declare private section, "export" is optional
|
|
||||||
//! \~russian Макрос для объявления частной секции, "export" необязателен
|
|
||||||
# define PRIVATE_DECLARATION(export)
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to start definition of private section
|
|
||||||
//! \~russian Макрос для начала реализации частной секции
|
|
||||||
# define PRIVATE_DEFINITION_START(Class)
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to end definition of private section
|
|
||||||
//! \~russian Макрос для окончания реализации частной секции
|
|
||||||
# define PRIVATE_DEFINITION_END(Class)
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to access private section by pointer
|
|
||||||
//! \~russian Макрос для доступа к частной секции
|
|
||||||
# define PRIVATE
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to access private section by pointer without brakes ()
|
|
||||||
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
|
|
||||||
# define PRIVATEWB
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to start static initializer
|
|
||||||
//! \~russian Макрос для начала статической инициализации
|
|
||||||
# define STATIC_INITIALIZER_BEGIN
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to end static initializer
|
|
||||||
//! \~russian Макрос для окончания статической инициализации
|
|
||||||
# define STATIC_INITIALIZER_END
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to remove class copy availability
|
|
||||||
//! \~russian Макрос для запрета копирования класса
|
|
||||||
# define NO_COPY_CLASS(Class)
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro to supress compiler warning about unused variable
|
|
||||||
//! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной
|
|
||||||
# define NO_UNUSED(x)
|
|
||||||
|
|
||||||
# undef MICRO_PIP
|
|
||||||
# undef FREERTOS
|
|
||||||
|
|
||||||
#endif // DOXYGEN
|
|
||||||
|
|
||||||
#ifdef WINDOWS
|
|
||||||
# ifdef CC_VC
|
|
||||||
# define SHUT_RDWR 2
|
|
||||||
# pragma comment(lib, "Ws2_32.lib")
|
|
||||||
# pragma comment(lib, "Iphlpapi.lib")
|
|
||||||
# pragma comment(lib, "Psapi.lib")
|
|
||||||
# ifdef ARCH_BITS_32
|
|
||||||
# define _X86_
|
|
||||||
# else
|
|
||||||
# define _IA64_
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# define SHUT_RDWR SD_BOTH
|
|
||||||
# endif
|
|
||||||
typedef int socklen_t;
|
|
||||||
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;}
|
|
||||||
// inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef MAC_OS
|
|
||||||
# define environ (*_NSGetEnviron())
|
|
||||||
typedef long time_t;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef LINUX
|
|
||||||
# define environ __environ
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef FREE_BSD
|
|
||||||
extern char ** environ;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifndef NO_UNUSED
|
|
||||||
# define NO_UNUSED(x) (void)x
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifndef assert
|
|
||||||
# define assert(x)
|
|
||||||
# define assertm(exp, msg)
|
|
||||||
# else
|
|
||||||
# define assertm(exp, msg) assert(((void)msg, exp))
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef MICRO_PIP
|
|
||||||
# define __PIP_TYPENAME__(T) "?"
|
|
||||||
# else
|
|
||||||
# define __PIP_TYPENAME__(T) typeid(T).name()
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef CC_GCC
|
|
||||||
# undef DEPRECATED
|
|
||||||
# undef DEPRECATEDM
|
|
||||||
# define DEPRECATED __attribute__((deprecated))
|
|
||||||
# define DEPRECATEDM(msg) __attribute__((deprecated(msg)))
|
|
||||||
# if CC_GCC_VERSION > 0x025F // > 2.95
|
|
||||||
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
|
|
||||||
# ifdef LINUX
|
|
||||||
# define HAS_LOCALE
|
|
||||||
# endif
|
|
||||||
# ifdef MAC_OS
|
|
||||||
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
|
|
||||||
# pragma GCC diagnostic ignored "-Wc++11-extensions"
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# ifdef ANDROID
|
|
||||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
# pragma GCC diagnostic ignored "-Wextra"
|
|
||||||
# pragma GCC diagnostic ignored "-Wc++11-extensions"
|
|
||||||
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
|
|
||||||
// # pragma GCC diagnostic ignored "-Wliteral-suffix"
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef CC_VC
|
|
||||||
# undef DEPRECATED
|
|
||||||
# undef DEPRECATEDM
|
|
||||||
# define DEPRECATED __declspec(deprecated)
|
|
||||||
# define DEPRECATEDM(msg) __declspec(deprecated(msg))
|
|
||||||
# pragma warning(disable: 4018)
|
|
||||||
# pragma warning(disable: 4061)
|
|
||||||
# pragma warning(disable: 4100)
|
|
||||||
# pragma warning(disable: 4239)
|
|
||||||
# pragma warning(disable: 4242)
|
|
||||||
# pragma warning(disable: 4244)
|
|
||||||
# pragma warning(disable: 4251)
|
|
||||||
# pragma warning(disable: 4365)
|
|
||||||
# pragma warning(disable: 4512)
|
|
||||||
# pragma warning(disable: 4668)
|
|
||||||
# pragma warning(disable: 4710)
|
|
||||||
# pragma warning(disable: 4800)
|
|
||||||
# pragma warning(disable: 4820)
|
|
||||||
# pragma warning(disable: 4986)
|
|
||||||
# pragma warning(disable: 4996)
|
|
||||||
# ifdef ARCH_BITS_32
|
|
||||||
typedef long ssize_t;
|
|
||||||
# else
|
|
||||||
typedef long long ssize_t;
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef CC_OTHER
|
|
||||||
# undef DEPRECATED
|
|
||||||
# undef DEPRECATEDM
|
|
||||||
# define DEPRECATED
|
|
||||||
# define DEPRECATEDM(msg)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif // DOXYGEN
|
|
||||||
|
|
||||||
|
|
||||||
// Private data macros
|
|
||||||
#ifndef DOXYGEN
|
|
||||||
|
|
||||||
# define PRIVATE_DECLARATION(e) \
|
|
||||||
struct __Private__; \
|
|
||||||
friend struct __Private__; \
|
|
||||||
struct e __PrivateInitializer__ { \
|
|
||||||
__PrivateInitializer__(); \
|
|
||||||
__PrivateInitializer__(const __PrivateInitializer__ & o); \
|
|
||||||
~__PrivateInitializer__(); \
|
|
||||||
__PrivateInitializer__ & operator=(const __PrivateInitializer__ & o); \
|
|
||||||
__Private__ * p; \
|
|
||||||
}; \
|
|
||||||
__PrivateInitializer__ __privateinitializer__;
|
|
||||||
|
|
||||||
# define PRIVATE_DEFINITION_START(c) struct c::__Private__ {
|
|
||||||
# define PRIVATE_DEFINITION_END(c) \
|
|
||||||
} \
|
|
||||||
; \
|
|
||||||
c::__PrivateInitializer__::__PrivateInitializer__() { \
|
|
||||||
p = new c::__Private__(); \
|
|
||||||
} \
|
|
||||||
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ &) { /*if (p) delete p;*/ \
|
|
||||||
p = new c::__Private__(); \
|
|
||||||
} \
|
|
||||||
c::__PrivateInitializer__::~__PrivateInitializer__() { \
|
|
||||||
delete p; \
|
|
||||||
p = 0; \
|
|
||||||
} \
|
|
||||||
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator=(const c::__PrivateInitializer__ &) { \
|
|
||||||
if (p) delete p; \
|
|
||||||
p = new c::__Private__(); \
|
|
||||||
return *this; \
|
|
||||||
}
|
|
||||||
|
|
||||||
# define PRIVATE (__privateinitializer__.p)
|
|
||||||
# define PRIVATEWB __privateinitializer__.p
|
|
||||||
|
|
||||||
#endif // DOXYGEN
|
|
||||||
|
|
||||||
#define NO_COPY_CLASS(name) \
|
|
||||||
name(const name &) = delete; \
|
|
||||||
name & operator=(const name &) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
#define _PIP_ADD_COUNTER_WS(a, cnt, line) a##cnt##_##line
|
|
||||||
#define _PIP_ADD_COUNTER_WF(a, cnt, line) _PIP_ADD_COUNTER_WS(a, cnt, line)
|
|
||||||
#define _PIP_ADD_COUNTER(a) _PIP_ADD_COUNTER_WF(a, __COUNTER__, __LINE__)
|
|
||||||
|
|
||||||
|
|
||||||
#define STATIC_INITIALIZER_BEGIN \
|
|
||||||
class { \
|
|
||||||
class _Initializer_ { \
|
|
||||||
public: \
|
|
||||||
_Initializer_() {
|
|
||||||
#define STATIC_INITIALIZER_END \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
_initializer_; \
|
|
||||||
} \
|
|
||||||
_PIP_ADD_COUNTER(_pip_initializer_);
|
|
||||||
|
|
||||||
|
|
||||||
//! \~\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
|
|
||||||
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro used for infinite loop
|
|
||||||
//! \~russian Макрос для бесконечного цикла
|
|
||||||
#define FOREVER for (;;)
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro used for infinite wait
|
|
||||||
//! \~russian Макрос для бесконечного ожидания
|
|
||||||
#define FOREVER_WAIT FOREVER piMinSleep();
|
|
||||||
|
|
||||||
//! \~\brief
|
|
||||||
//! \~english Macro used for infinite wait
|
|
||||||
//! \~russian Макрос для бесконечного ожидания
|
|
||||||
#define WAIT_FOREVER FOREVER piMinSleep();
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PIBASE_MACROS_H
|
|
||||||
44
libs/main/core/pibitarray.cpp
Normal file
44
libs/main/core/pibitarray.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
PIP - Platform Independent Primitives
|
||||||
|
Bit array
|
||||||
|
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 "pibitarray.h"
|
||||||
|
#include "picout.h"
|
||||||
|
|
||||||
|
|
||||||
|
PICout operator <<(PICout s, const PIBitArray & ba) {
|
||||||
|
s.space();
|
||||||
|
s.setControl(0, true);
|
||||||
|
for (uint i = 0; i < ba.bitSize(); ++i) {
|
||||||
|
s << int(ba[i]);
|
||||||
|
if (i % 8 == 7) s << ' ';
|
||||||
|
}
|
||||||
|
s.restoreControl();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PIP_STD_IOSTREAM
|
||||||
|
std::ostream &operator <<(std::ostream & s, const PIBitArray & ba) {
|
||||||
|
for (uint i = 0; i < ba.bitSize(); ++i) {
|
||||||
|
s << ba[i];
|
||||||
|
if (i % 8 == 7) s << ' ';
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
114
libs/main/core/pibitarray.h
Normal file
114
libs/main/core/pibitarray.h
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*! \file pibitarray.h
|
||||||
|
* \~\brief
|
||||||
|
* \~english Bit array
|
||||||
|
* \~russian Битовый массив
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
PIP - Platform Independent Primitives
|
||||||
|
Bit array
|
||||||
|
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 PIBITARRAY_H
|
||||||
|
#define PIBITARRAY_H
|
||||||
|
|
||||||
|
#include "pivector.h"
|
||||||
|
|
||||||
|
class PIP_EXPORT PIBitArray {
|
||||||
|
friend PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v);
|
||||||
|
friend PIByteArray & operator >>(PIByteArray & s, PIBitArray & v);
|
||||||
|
public:
|
||||||
|
PIBitArray(const int & size = 0) {resize(size);}
|
||||||
|
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
|
||||||
|
PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
PIBitArray(ulong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
PIBitArray(const uchar * bytes, uint size) {resize(size * 8); memcpy(data(), bytes, size);}
|
||||||
|
|
||||||
|
uint bitSize() const {return size_;}
|
||||||
|
uint byteSize() const {return bytesInBits(size_);}
|
||||||
|
PIBitArray & resize(const uint & size) {size_ = size; data_.resize(bytesInBits(size_)); return *this;}
|
||||||
|
|
||||||
|
PIBitArray & clearBit(const uint & index) {data_[index / 8] &= ~(1 << (index % 8)); return *this;}
|
||||||
|
PIBitArray & setBit(const uint & index) {data_[index / 8] |= (1 << (index % 8)); return *this;}
|
||||||
|
PIBitArray & writeBit(const uint & index, const bool & value) {if (value) setBit(index); else clearBit(index); return *this;}
|
||||||
|
PIBitArray & writeBit(const uint & index, const uchar & value) {return writeBit(index, value > 0);}
|
||||||
|
|
||||||
|
PIBitArray & push_back(const bool & value) {resize(size_ + 1); writeBit(size_ - 1, value); return *this;}
|
||||||
|
PIBitArray & push_back(const uchar & value) {return push_back(value > 0);}
|
||||||
|
PIBitArray & insert(const uint & index, const bool & value) {
|
||||||
|
resize(size_ + 1);
|
||||||
|
uint fi = byteSize() - 1, si = index / 8, ti = index % 8;
|
||||||
|
uchar c = data_[si];
|
||||||
|
for (uint i = fi; i > si; --i) {
|
||||||
|
data_[i] <<= 1;
|
||||||
|
if ((0x80 & data_[i - 1]) == 0x80) data_[i] |= 1;
|
||||||
|
else data_[i] &= 0xFE;}
|
||||||
|
data_[si] &= (0xFF >> (7 - ti));
|
||||||
|
data_[si] |= ((c << 1) & (0xFF << (ti)));
|
||||||
|
if (value) data_[si] |= (1 << ti);
|
||||||
|
else data_[si] &= ~(1 << ti);
|
||||||
|
return *this;}
|
||||||
|
PIBitArray & insert(const uint & index, const uchar & value) {return insert(index, value > 0);}
|
||||||
|
PIBitArray & push_front(const bool & value) {return insert(0, value);}
|
||||||
|
PIBitArray & push_front(const uchar & value) {return push_front(value > 0);}
|
||||||
|
PIBitArray & pop_back() {return resize(size_ - 1);}
|
||||||
|
PIBitArray & pop_front() {
|
||||||
|
if (size_ == 0) return *this;
|
||||||
|
uint fi = byteSize() - 1;
|
||||||
|
for (uint i = 0; i < fi; ++i) {
|
||||||
|
data_[i] >>= 1;
|
||||||
|
if ((1 & data_[i + 1]) == 1) data_[i] |= 0x80;
|
||||||
|
else data_[i] &= 0x7F;}
|
||||||
|
data_[fi] >>= 1;
|
||||||
|
resize(size_ - 1);
|
||||||
|
return *this;}
|
||||||
|
PIBitArray & append(const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) push_back(ba[i]); return *this;}
|
||||||
|
|
||||||
|
uchar * data() {return data_.data();}
|
||||||
|
uchar toUChar() {if (size_ == 0) return 0; return data_[0];}
|
||||||
|
ushort toUShort() {ushort t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
|
||||||
|
uint toUInt() {uint t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
|
||||||
|
ulong toULong() {ulong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
|
||||||
|
ullong toULLong() {ullong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
|
||||||
|
|
||||||
|
bool at(const uint & index) const {return (1 & (data_[index / 8] >> (index % 8))) == 1 ? true : false;}
|
||||||
|
bool operator [](const uint & index) const {return at(index);}
|
||||||
|
void operator +=(const PIBitArray & ba) {append(ba);}
|
||||||
|
bool operator ==(const PIBitArray & ba) const {if (bitSize() != ba.bitSize()) return false; for (uint i = 0; i < bitSize(); ++i) if (at(i) != ba[i]) return false; return true;}
|
||||||
|
bool operator !=(const PIBitArray & ba) const {return !(*this == ba);}
|
||||||
|
void operator =(const uchar & val) {resize(sizeof(val) * 8); data_[0] = val;}
|
||||||
|
void operator =(const ushort & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
void operator =(const uint & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
void operator =(const ulong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
void operator =(const ullong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static uint bytesInBits(const uint & bits) {return (bits + 7) / 8;}
|
||||||
|
|
||||||
|
PIVector<uchar> data_;
|
||||||
|
uint size_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef PIP_STD_IOSTREAM
|
||||||
|
//std::ostream & operator <<(std::ostream & s, const PIBitArray & ba);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PICout operator <<(PICout s, const PIBitArray & ba);
|
||||||
|
|
||||||
|
#endif // PIBITARRAY_H
|
||||||
@@ -18,10 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pibytearray.h"
|
#include "pibytearray.h"
|
||||||
|
|
||||||
#include "picrc.h"
|
|
||||||
#include "pistringlist.h"
|
#include "pistringlist.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
//! \class PIByteArray pibytearray.h
|
//! \class PIByteArray pibytearray.h
|
||||||
@@ -31,30 +28,53 @@
|
|||||||
//! It can be constructed from any data and size.
|
//! It can be constructed from any data and size.
|
||||||
//! You can use %PIByteArray as binary stream
|
//! You can use %PIByteArray as binary stream
|
||||||
//! to serialize/deserialize any objects and data.
|
//! to serialize/deserialize any objects and data.
|
||||||
//! See details \ref iostream.
|
//! This class based on PIDeque<uchar> and provide some handle function
|
||||||
//! This class use PIDeque<uchar> and provide some handle function
|
|
||||||
//! to manipulate it.
|
//! to manipulate it.
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! %PIByteArray используется для хранения байтов.
|
//! %PIByteArray используется для хранения байтов.
|
||||||
//! Он может быть сконструирован из любых даных.
|
//! Он может быть сконструирован из любых даных.
|
||||||
//! Можно использовать %PIByteArray как потоковый объект
|
//! Можно использовать %PIByteArray как потоковый объект
|
||||||
//! для сериализации/десериализации любых типов и данных.
|
//! для сериализации/десериализации любых типов и данных.
|
||||||
//! Подробнее \ref iostream.
|
//! Этот класс наследован от PIDeque<uchar> и предоставляет набор
|
||||||
//! Этот класс использует PIDeque<uchar> и предоставляет набор
|
|
||||||
//! удобных методов для работы с байтами.
|
//! удобных методов для работы с байтами.
|
||||||
//!
|
//!
|
||||||
//! \~english \section PIByteArray_sec0 Usage
|
//! \~english \section PIByteArray_sec0 Usage
|
||||||
//! \~russian \section PIByteArray_sec0 Использование
|
//! \~russian \section PIByteArray_sec0 Использование
|
||||||
//! \~english
|
//! \~english
|
||||||
//! %PIByteArray subclass PIBinaryStream and can be used to store custom data and manipulate it.
|
//! %PIByteArray can be used to store custom data and manipulate it. There are many
|
||||||
//! Store operators places data at the end of array, restore operators takes data from the beginning
|
//! 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.
|
//! of array.
|
||||||
//! In addition there are Hex and Base64 convertions.
|
//! In addition there are Hex and Base64 convertions
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! %PIByteArray наследован от PIBinaryStream и может быть использован для сохранения любых данных и работы с ними.
|
//! %PIByteArray может быть использован для сохранения любых данных и работы с ними.
|
||||||
|
//! Он предоставляет множество операторов для сохранения/извлечения общих типов.
|
||||||
//! Операторы сохранения добавляют данные в конец массива, а операторы извлечения
|
//! Операторы сохранения добавляют данные в конец массива, а операторы извлечения
|
||||||
//! берут данные из его начала.
|
//! берут данные из его начала.
|
||||||
//! Также есть методы для преобразования в Hex и Base64.
|
//!
|
||||||
|
//! \~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
|
//! \~english \section PIByteArray_sec1 Attention
|
||||||
//! \~russian \section PIByteArray_sec1 Внимание
|
//! \~russian \section PIByteArray_sec1 Внимание
|
||||||
@@ -68,32 +88,56 @@
|
|||||||
//! а не просто добавляет его содержимое в конец. Этот оператор полезен для управляемой
|
//! а не просто добавляет его содержимое в конец. Этот оператор полезен для управляемой
|
||||||
//! упаковки произвольных данных в виде %PIByteArray.
|
//! упаковки произвольных данных в виде %PIByteArray.
|
||||||
//! Для добавления содержимого одного байтового массива к другому используется
|
//! Для добавления содержимого одного байтового массива к другому используется
|
||||||
//! метод \a append().
|
//! метов \a append().
|
||||||
//! \~\snippet pibytearray.cpp 3
|
//! \~\snippet pibytearray.cpp 3
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
|
||||||
static const uchar base64Table[64] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
static const uchar base64Table[64] = {
|
||||||
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
|
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||||
0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
|
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
||||||
0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f};
|
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||||
|
0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
|
||||||
|
0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
|
||||||
|
0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
|
||||||
|
0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33,
|
||||||
|
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f};
|
||||||
|
|
||||||
static const uchar base64InvTable[256] = {
|
static const uchar base64InvTable[256] = {
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0, 0x0, 0x0, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x17, 0x18, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3F,
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x3C, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE,
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
|
0x17, 0x18, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
|
||||||
|
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||||
|
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
|
||||||
|
0x31, 0x32, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
|
||||||
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
struct base64HelpStruct {
|
struct base64HelpStruct {
|
||||||
base64HelpStruct() {v = 0;}
|
base64HelpStruct() {v = 0;}
|
||||||
inline void setBytes(const uchar * r, int size = 3) {
|
inline void setBytes(const uchar * r, int size = 3) {
|
||||||
@@ -126,7 +170,6 @@ struct base64HelpStruct {
|
|||||||
}
|
}
|
||||||
uint v;
|
uint v;
|
||||||
};
|
};
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
|
|
||||||
PIByteArray &PIByteArray::convertToBase64() {
|
PIByteArray &PIByteArray::convertToBase64() {
|
||||||
@@ -143,8 +186,7 @@ PIByteArray PIByteArray::toBase64() const {
|
|||||||
if (isEmpty()) return PIByteArray();
|
if (isEmpty()) return PIByteArray();
|
||||||
base64HelpStruct hs;
|
base64HelpStruct hs;
|
||||||
PIByteArray ret;
|
PIByteArray ret;
|
||||||
const int sz = (size_s() / 3) * 3;
|
int sz = (size_s() / 3) * 3, ri = -1;
|
||||||
int ri = -1;
|
|
||||||
uchar t[4];
|
uchar t[4];
|
||||||
ret.resize(((size_s() - 1) / 3 + 1) * 4);
|
ret.resize(((size_s() - 1) / 3 + 1) * 4);
|
||||||
for (int i = 0; i < sz; i += 3) {
|
for (int i = 0; i < sz; i += 3) {
|
||||||
@@ -155,7 +197,7 @@ PIByteArray PIByteArray::toBase64() const {
|
|||||||
ret[++ri] = (t[2]);
|
ret[++ri] = (t[2]);
|
||||||
ret[++ri] = (t[3]);
|
ret[++ri] = (t[3]);
|
||||||
}
|
}
|
||||||
const int der = size_s() % 3;
|
int der = size_s() % 3;
|
||||||
switch (der) {
|
switch (der) {
|
||||||
case 1:
|
case 1:
|
||||||
hs.setBytes(data(sz), 1);
|
hs.setBytes(data(sz), 1);
|
||||||
@@ -183,8 +225,7 @@ PIByteArray PIByteArray::fromBase64(const PIByteArray & base64) {
|
|||||||
if (base64.isEmpty()) return PIByteArray();
|
if (base64.isEmpty()) return PIByteArray();
|
||||||
base64HelpStruct hs;
|
base64HelpStruct hs;
|
||||||
PIByteArray ret;
|
PIByteArray ret;
|
||||||
const int sz = base64.size_s();
|
int sz = base64.size_s(), ind = -1;
|
||||||
int ind = -1;
|
|
||||||
uchar t[4];
|
uchar t[4];
|
||||||
ret.resize(sz / 4 * 3);
|
ret.resize(sz / 4 * 3);
|
||||||
for (int i = 0; i < sz; i += 4) {
|
for (int i = 0; i < sz; i += 4) {
|
||||||
@@ -195,8 +236,7 @@ PIByteArray PIByteArray::fromBase64(const PIByteArray & base64) {
|
|||||||
ret[++ind] = (t[2]);
|
ret[++ind] = (t[2]);
|
||||||
}
|
}
|
||||||
if (base64.back() == '=') ret.pop_back();
|
if (base64.back() == '=') ret.pop_back();
|
||||||
if (sz > 1)
|
if (sz > 1) if (base64[sz - 2] == '=') ret.pop_back();
|
||||||
if (base64[sz - 2] == '=') ret.pop_back();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,15 +248,14 @@ PIByteArray PIByteArray::fromBase64(const PIString & base64) {
|
|||||||
|
|
||||||
PIByteArray & PIByteArray::compressRLE(uchar threshold) {
|
PIByteArray & PIByteArray::compressRLE(uchar threshold) {
|
||||||
PIByteArray t;
|
PIByteArray t;
|
||||||
uchar fb;
|
uchar fb, clen, mlen = 255 - threshold;
|
||||||
uchar clen;
|
|
||||||
const uchar mlen = 255 - threshold;
|
|
||||||
for (uint i = 0; i < size();) {
|
for (uint i = 0; i < size();) {
|
||||||
fb = at(i);
|
fb = at(i);
|
||||||
clen = 1;
|
clen = 1;
|
||||||
while (at(++i) == fb) {
|
while (at(++i) == fb) {
|
||||||
++clen;
|
++clen;
|
||||||
if (clen == mlen) break;
|
if (clen == mlen)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (clen > 1) {
|
if (clen > 1) {
|
||||||
t.push_back(threshold + clen);
|
t.push_back(threshold + clen);
|
||||||
@@ -236,8 +275,7 @@ PIByteArray & PIByteArray::compressRLE(uchar threshold) {
|
|||||||
|
|
||||||
PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
|
PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
|
||||||
PIByteArray t;
|
PIByteArray t;
|
||||||
uchar fb;
|
uchar fb, clen;
|
||||||
uchar clen;
|
|
||||||
for (uint i = 0; i < size(); ++i) {
|
for (uint i = 0; i < size(); ++i) {
|
||||||
fb = at(i);
|
fb = at(i);
|
||||||
if (fb >= threshold) {
|
if (fb >= threshold) {
|
||||||
@@ -269,7 +307,7 @@ PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
uchar PIByteArray::checksumPlain8(bool inverse) const {
|
uchar PIByteArray::checksumPlain8(bool inverse) const {
|
||||||
uchar c = 0;
|
uchar c = 0;
|
||||||
const int sz = size_s();
|
int sz = size_s();
|
||||||
for (int i = 0; i < sz; ++i)
|
for (int i = 0; i < sz; ++i)
|
||||||
c += at(i);
|
c += at(i);
|
||||||
if (inverse) c = ~(c + 1);
|
if (inverse) c = ~(c + 1);
|
||||||
@@ -277,19 +315,6 @@ uchar PIByteArray::checksumPlain8(bool inverse) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uchar PIByteArray::checksumCRC8() const {
|
|
||||||
return standardCRC_8().calculate(data(), size());
|
|
||||||
}
|
|
||||||
|
|
||||||
ushort PIByteArray::checksumCRC16() const {
|
|
||||||
return standardCRC_16().calculate(data(), size());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint PIByteArray::checksumCRC32() const {
|
|
||||||
return standardCRC_32().calculate(data(), size());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \~\details
|
//! \~\details
|
||||||
//! \~english
|
//! \~english
|
||||||
//! This is sum of all bytes multiplied by index+1, if inverse then add 1 and inverse.
|
//! This is sum of all bytes multiplied by index+1, if inverse then add 1 and inverse.
|
||||||
@@ -305,7 +330,7 @@ uint PIByteArray::checksumCRC32() const {
|
|||||||
//! \endcode
|
//! \endcode
|
||||||
uint PIByteArray::checksumPlain32(bool inverse) const {
|
uint PIByteArray::checksumPlain32(bool inverse) const {
|
||||||
uint c = 0;
|
uint c = 0;
|
||||||
const int sz = size_s();
|
int sz = size_s();
|
||||||
for (int i = 0; i < sz; ++i)
|
for (int i = 0; i < sz; ++i)
|
||||||
c += at(i) * (i + 1);
|
c += at(i) * (i + 1);
|
||||||
if (inverse) c = ~(c + 1);
|
if (inverse) c = ~(c + 1);
|
||||||
@@ -320,7 +345,7 @@ uint PIByteArray::hash() const {
|
|||||||
|
|
||||||
PIString PIByteArray::toString(int base) const {
|
PIString PIByteArray::toString(int base) const {
|
||||||
PIString ret;
|
PIString ret;
|
||||||
const int sz = size_s();
|
int sz = size_s();
|
||||||
for (int i = 0; i < sz; ++i) {
|
for (int i = 0; i < sz; ++i) {
|
||||||
if (i > 0) ret += " ";
|
if (i > 0) ret += " ";
|
||||||
if (base == 2) ret += "b";
|
if (base == 2) ret += "b";
|
||||||
@@ -338,17 +363,13 @@ PIString PIByteArray::toHex() const {
|
|||||||
const uchar *d = data();
|
const uchar *d = data();
|
||||||
for (int i = 0; i < size_s(); ++i) {
|
for (int i = 0; i < size_s(); ++i) {
|
||||||
int j = (d[i] >> 4) & 0xf;
|
int j = (d[i] >> 4) & 0xf;
|
||||||
if (j <= 9)
|
if (j <= 9) hexData[i*2] = (j + '0');
|
||||||
hexData[i * 2] = (j + '0');
|
else hexData[i*2] = (j + 'a' - 10);
|
||||||
else
|
|
||||||
hexData[i * 2] = (j + 'a' - 10);
|
|
||||||
j = d[i] & 0xf;
|
j = d[i] & 0xf;
|
||||||
if (j <= 9)
|
if (j <= 9) hexData[i*2+1] = (j + '0');
|
||||||
hexData[i * 2 + 1] = (j + '0');
|
else hexData[i*2+1] = (j + 'a' - 10);
|
||||||
else
|
|
||||||
hexData[i * 2 + 1] = (j + 'a' - 10);
|
|
||||||
}
|
}
|
||||||
return PIString::fromAscii(hex);
|
return PIString(hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -356,10 +377,10 @@ PIByteArray PIByteArray::fromUserInput(PIString str) {
|
|||||||
PIByteArray ret;
|
PIByteArray ret;
|
||||||
if (str.trim().isEmpty()) return ret;
|
if (str.trim().isEmpty()) return ret;
|
||||||
str.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ");
|
str.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ");
|
||||||
const PIStringList bl(str.split(" "));
|
PIStringList bl(str.split(" "));
|
||||||
bool ok(false);
|
bool ok(false);
|
||||||
for (const auto & b: bl) {
|
piForeachC (PIString & b, bl) {
|
||||||
const int bv = b.toInt(-1, &ok);
|
int bv = b.toInt(-1, &ok);
|
||||||
if (ok) ret << uchar(bv);
|
if (ok) ret << uchar(bv);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -367,21 +388,17 @@ PIByteArray PIByteArray::fromUserInput(PIString str) {
|
|||||||
|
|
||||||
|
|
||||||
PIByteArray PIByteArray::fromHex(PIString str) {
|
PIByteArray PIByteArray::fromHex(PIString str) {
|
||||||
const PIByteArray hexEncoded = str.toByteArray();
|
PIByteArray hexEncoded = str.toByteArray();
|
||||||
PIByteArray res((hexEncoded.size() + 1)/ 2);
|
PIByteArray res((hexEncoded.size() + 1)/ 2);
|
||||||
uchar *result = res.data() + res.size();
|
uchar *result = res.data() + res.size();
|
||||||
bool odd_digit = true;
|
bool odd_digit = true;
|
||||||
for (int i = hexEncoded.size() - 1; i >= 0; --i) {
|
for (int i = hexEncoded.size() - 1; i >= 0; --i) {
|
||||||
int ch = hexEncoded.at(i);
|
int ch = hexEncoded.at(i);
|
||||||
int tmp;
|
int tmp;
|
||||||
if (ch >= '0' && ch <= '9')
|
if (ch >= '0' && ch <= '9') tmp = ch - '0';
|
||||||
tmp = ch - '0';
|
else if (ch >= 'a' && ch <= 'f') tmp = ch - 'a' + 10;
|
||||||
else if (ch >= 'a' && ch <= 'f')
|
else if (ch >= 'A' && ch <= 'F') tmp = ch - 'A' + 10;
|
||||||
tmp = ch - 'a' + 10;
|
else continue;
|
||||||
else if (ch >= 'A' && ch <= 'F')
|
|
||||||
tmp = ch - 'A' + 10;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
if (odd_digit) {
|
if (odd_digit) {
|
||||||
--result;
|
--result;
|
||||||
*result = tmp;
|
*result = tmp;
|
||||||
@@ -398,14 +415,14 @@ PIByteArray PIByteArray::fromHex(PIString str) {
|
|||||||
|
|
||||||
PICout operator <<(PICout s, const PIByteArray & ba) {
|
PICout operator <<(PICout s, const PIByteArray & ba) {
|
||||||
s.space();
|
s.space();
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
s << "{";
|
s << "{";
|
||||||
for (uint i = 0; i < ba.size(); ++i) {
|
for (uint i = 0; i < ba.size(); ++i) {
|
||||||
s << ba[i];
|
s << ba[i];
|
||||||
if (i < ba.size() - 1) s << ", ";
|
if (i < ba.size() - 1) s << ", ";
|
||||||
}
|
}
|
||||||
s << "}";
|
s << "}";
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,3 +438,38 @@ std::ostream & operator<<(std::ostream & s, const PIByteArray & ba) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
s.clear();
|
||||||
|
v.clear();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
int sz = 0;
|
||||||
|
s >> sz;
|
||||||
|
if (sz > s.size_s()) {
|
||||||
|
piCout << "[PIByteArray] Warning: operator >> wants too much data, discard!" << sz << s.size_s();
|
||||||
|
s.clear();
|
||||||
|
v.clear();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
v.resize(sz);
|
||||||
|
if (sz > 0) {
|
||||||
|
memcpy(v.data(), s.data(), sz);
|
||||||
|
s.remove(0, sz);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {
|
||||||
|
s << int(v.size_s());
|
||||||
|
int os = s.size_s();
|
||||||
|
if (v.size_s() > 0) {
|
||||||
|
s.enlarge(v.size_s());
|
||||||
|
memcpy(s.data(os), v.data(), v.size());
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
712
libs/main/core/pibytearray.h
Normal file
712
libs/main/core/pibytearray.h
Normal file
@@ -0,0 +1,712 @@
|
|||||||
|
/*! \file pibytearray.h
|
||||||
|
* \ingroup Core
|
||||||
|
* \~\brief
|
||||||
|
* \~english Byte array
|
||||||
|
* \~russian Байтовый массив
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
PIP - Platform Independent Primitives
|
||||||
|
Byte array
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PIBYTEARRAY_H
|
||||||
|
#define PIBYTEARRAY_H
|
||||||
|
|
||||||
|
#include "pichar.h"
|
||||||
|
#include "pibitarray.h"
|
||||||
|
#include "pimap.h"
|
||||||
|
#include "pivector2d.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
class PIString;
|
||||||
|
class PIByteArray;
|
||||||
|
|
||||||
|
|
||||||
|
//! \ingroup Core
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english The %PIByteArray class provides an array of bytes.
|
||||||
|
//! \~russian Класс %PIByteArray представляет собой массив байтов.
|
||||||
|
class PIP_EXPORT PIByteArray: public PIDeque<uchar>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! \~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)) {}
|
||||||
|
|
||||||
|
//! \~english Constructs 0-filled byte array with size "size"
|
||||||
|
//! \~russian Создает заполненный "0" байтовый массив размером "size"
|
||||||
|
PIByteArray(const uint size) {resize(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)) {}
|
||||||
|
|
||||||
|
//! \~english Constructs byte array with size "size" filled by "t"
|
||||||
|
//! \~russian Создает заполненный "t" байтовый массив размером "size"
|
||||||
|
PIByteArray(const uint size, uchar t): PIDeque<uchar>(size, t) {}
|
||||||
|
|
||||||
|
|
||||||
|
//! \~english Help struct to store/restore custom blocks of data to/from PIByteArray
|
||||||
|
//! \~russian Вспомогательная структура для сохранения/извлечения произвольного блока данных в/из байтового массива
|
||||||
|
struct RawData {
|
||||||
|
friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
|
||||||
|
friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
|
||||||
|
public:
|
||||||
|
//! \~english Constructs data block
|
||||||
|
//! \~russian Создает блок данных
|
||||||
|
RawData(void * data = 0, int size = 0) {d = data; s = size;}
|
||||||
|
RawData(const RawData & o) {d = o.d; s = o.s;}
|
||||||
|
//! \~english Constructs data block
|
||||||
|
//! \~russian Создает блок данных
|
||||||
|
RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;}
|
||||||
|
RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
|
||||||
|
private:
|
||||||
|
void * d;
|
||||||
|
int s;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \~english Return resized byte array
|
||||||
|
//! \~russian Возвращает копию байтового массива с измененным размером
|
||||||
|
PIByteArray resized(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
|
||||||
|
|
||||||
|
//! \~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();
|
||||||
|
|
||||||
|
//! \~english Convert data from Base 64 and return this byte array
|
||||||
|
//! \~russian Преобразует данные из Base 64 и возвращает текущий массив
|
||||||
|
PIByteArray & convertFromBase64();
|
||||||
|
|
||||||
|
//! \~english Return converted to Base 64 data
|
||||||
|
//! \~russian Возвращает копию байтового массива, преобразованного в Base 64
|
||||||
|
PIByteArray toBase64() const;
|
||||||
|
|
||||||
|
PIByteArray & compressRLE(uchar threshold = 192);
|
||||||
|
PIByteArray & decompressRLE(uchar threshold = 192);
|
||||||
|
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;
|
||||||
|
|
||||||
|
//! \~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;
|
||||||
|
|
||||||
|
//! \~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;}
|
||||||
|
|
||||||
|
//! \~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;}
|
||||||
|
|
||||||
|
//! \~english Add to the end "t"
|
||||||
|
//! \~russian Добавляет в конец массива байт "t"
|
||||||
|
PIByteArray & append(uchar t) {push_back(t); return *this;}
|
||||||
|
|
||||||
|
//! \~english Returns 8-bit checksum
|
||||||
|
//! \~russian Возвращает 8-битную контрольную сумму
|
||||||
|
uchar checksumPlain8(bool inverse = true) const;
|
||||||
|
|
||||||
|
//! \~english Returns 32-bit checksum
|
||||||
|
//! \~russian Возвращает 32-битную контрольную сумму
|
||||||
|
uint checksumPlain32(bool inverse = true) const;
|
||||||
|
|
||||||
|
//! \~english Returns hash of content
|
||||||
|
//! \~russian Возвращает хэш содержимого
|
||||||
|
uint hash() const;
|
||||||
|
|
||||||
|
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
|
||||||
|
|
||||||
|
PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
|
||||||
|
|
||||||
|
PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;}
|
||||||
|
|
||||||
|
static PIByteArray fromUserInput(PIString str);
|
||||||
|
|
||||||
|
static PIByteArray fromHex(PIString str);
|
||||||
|
|
||||||
|
//! \~english Return converted from Base 64 data
|
||||||
|
//! \~russian Возвращает массив из Base 64 представления
|
||||||
|
static PIByteArray fromBase64(const PIByteArray & base64);
|
||||||
|
static PIByteArray fromBase64(const PIString & base64);
|
||||||
|
|
||||||
|
|
||||||
|
class StreamRef {
|
||||||
|
public:
|
||||||
|
StreamRef(PIByteArray & s): ba(s) {}
|
||||||
|
operator PIByteArray&() {return ba;}
|
||||||
|
private:
|
||||||
|
PIByteArray & ba;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \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
|
||||||
|
//! \~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
|
||||||
|
//! \~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
|
||||||
|
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Output operator to \a PICout
|
||||||
|
//! \~russian Оператор вывода в \a PICout
|
||||||
|
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// store operators for basic types
|
||||||
|
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator
|
||||||
|
//! \~russian Оператор сохранения
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const bool v) {s.push_back(v); return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator
|
||||||
|
//! \~russian Оператор сохранения
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const char v) {s.push_back(v); return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator
|
||||||
|
//! \~russian Оператор сохранения
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const uchar v) {s.push_back(v); return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator for any trivial copyable type
|
||||||
|
//! \~russian Оператор сохранения для тривиальных типов
|
||||||
|
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray::StreamRef operator <<(PIByteArray & s, const T & v) {
|
||||||
|
int os = s.size_s();
|
||||||
|
s.enlarge(sizeof(v));
|
||||||
|
memcpy(s.data(os), &v, sizeof(v));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator, see \ref PIByteArray_sec1 for details
|
||||||
|
//! \~russian Оператор сохранения, подробнее в \ref PIByteArray_sec1
|
||||||
|
PIP_EXPORT PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v);
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator
|
||||||
|
//! \~russian Оператор сохранения
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {
|
||||||
|
int os = s.size_s();
|
||||||
|
if (v.s > 0) {
|
||||||
|
s.enlarge(v.s);
|
||||||
|
memcpy(s.data(os), v.d, v.s);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator for PIVector of any trivial copyable type
|
||||||
|
//! \~russian Оператор сохранения для PIVector тривиальных типов
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||||
|
s << int(v.size_s());
|
||||||
|
int os = s.size_s();
|
||||||
|
if (v.size_s() > 0) {
|
||||||
|
s.enlarge(v.size_s()*sizeof(T));
|
||||||
|
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||||
|
s << int(v.size_s());
|
||||||
|
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator for PIDeque of any trivial copyable type
|
||||||
|
//! \~russian Оператор сохранения для PIDeque тривиальных типов
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||||
|
s << int(v.size_s());
|
||||||
|
int os = s.size_s();
|
||||||
|
if (v.size_s() > 0) {
|
||||||
|
s.enlarge(v.size_s()*sizeof(T));
|
||||||
|
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||||
|
s << int(v.size_s());
|
||||||
|
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator for PIVector2D of any trivial copyable type
|
||||||
|
//! \~russian Оператор сохранения для PIVector2D тривиальных типов
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||||
|
s << int(v.rows()) << int(v.cols());
|
||||||
|
int os = s.size_s();
|
||||||
|
if (v.size_s() > 0) {
|
||||||
|
s.enlarge(v.size_s()*sizeof(T));
|
||||||
|
memcpy(s.data(os), v.data(), v.size_s()*sizeof(T));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||||
|
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator
|
||||||
|
//! \~russian Оператор сохранения
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIPair
|
||||||
|
//! \~english Store operator
|
||||||
|
//! \~russian Оператор сохранения
|
||||||
|
template<typename Type0, typename Type1>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// restore operators for basic types
|
||||||
|
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator
|
||||||
|
//! \~russian Оператор извлечения
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator
|
||||||
|
//! \~russian Оператор извлечения
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator
|
||||||
|
//! \~russian Оператор извлечения
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator for any trivial copyable type
|
||||||
|
//! \~russian Оператор извлечения для тривиальных типов
|
||||||
|
template<typename T, typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray::StreamRef operator >>(PIByteArray & s, T & v) {
|
||||||
|
if (s.size() < sizeof(v)) {
|
||||||
|
printf("error with %s\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size() >= sizeof(v));
|
||||||
|
}
|
||||||
|
memcpy((void*)(&v), s.data(), sizeof(v));
|
||||||
|
s.remove(0, sizeof(v));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator, see \ref PIByteArray_sec1 for details
|
||||||
|
//! \~russian Оператор извлечения, подробнее в \ref PIByteArray_sec1
|
||||||
|
PIP_EXPORT PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator
|
||||||
|
//! \~russian Оператор извлечения
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {
|
||||||
|
if (s.size_s() < v.s) {
|
||||||
|
printf("error with RawData %d < %d\n", (int)s.size_s(), v.s);
|
||||||
|
assert(s.size_s() >= v.s);
|
||||||
|
}
|
||||||
|
if (v.s > 0) {
|
||||||
|
memcpy((void*)(v.d), s.data(), v.s);
|
||||||
|
s.remove(0, v.s);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator for PIVector of any trivial copyable type
|
||||||
|
//! \~russian Оператор извлечения для PIVector тривиальных типов
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
}
|
||||||
|
int sz; s >> sz;
|
||||||
|
v._resizeRaw(sz);
|
||||||
|
if (sz > 0) {
|
||||||
|
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||||
|
s.remove(0, sz*sizeof(T));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
}
|
||||||
|
int sz; s >> sz;
|
||||||
|
v.resize(sz);
|
||||||
|
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator for PIDeque of any trivial copyable type
|
||||||
|
//! \~russian Оператор извлечения для PIDeque тривиальных типов
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
}
|
||||||
|
int sz; s >> sz;
|
||||||
|
v._resizeRaw(sz);
|
||||||
|
if (sz > 0) {
|
||||||
|
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||||
|
s.remove(0, sz*sizeof(T));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
}
|
||||||
|
int sz; s >> sz;
|
||||||
|
v.resize(sz);
|
||||||
|
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator for PIVector2D of any trivial copyable type
|
||||||
|
//! \~russian Оператор извлечения для PIVector2D тривиальных типов
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if< std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||||
|
if (s.size_s() < 8) {
|
||||||
|
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 8);
|
||||||
|
}
|
||||||
|
int r, c; s >> r >> c;
|
||||||
|
v._resizeRaw(r, c);
|
||||||
|
int sz = r*c;
|
||||||
|
if (sz > 0) {
|
||||||
|
memcpy(v.data(), s.data(), sz*sizeof(T));
|
||||||
|
s.remove(0, sz*sizeof(T));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<typename T,
|
||||||
|
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
|
||||||
|
typename std::enable_if<!std::is_same<decltype(std::declval<PIByteArray&>() << std::declval<const T &>()), PIByteArray::StreamRef>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||||
|
if (s.size_s() < 8) {
|
||||||
|
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 8);
|
||||||
|
}
|
||||||
|
int r,c;
|
||||||
|
PIVector<T> tmp;
|
||||||
|
s >> r >> c >> tmp;
|
||||||
|
v = PIVector2D<T>(r, c, tmp);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator
|
||||||
|
//! \~russian Оператор извлечения
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
|
||||||
|
|
||||||
|
//! \relatesalso PIPair
|
||||||
|
//! \~english Restore operator
|
||||||
|
//! \~russian Оператор извлечения
|
||||||
|
template<typename Type0, typename Type1>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// store operators for complex types
|
||||||
|
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator for PIVector of any compound type
|
||||||
|
//! \~russian Оператор сохранения для PIVector сложных типов
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {
|
||||||
|
s << int(v.size_s());
|
||||||
|
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator for PIDeque of any compound type
|
||||||
|
//! \~russian Оператор сохранения для PIDeque сложных типов
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {
|
||||||
|
s << int(v.size_s());
|
||||||
|
for (uint i = 0; i < v.size(); ++i) s << v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator for PIVector2D of any compound type
|
||||||
|
//! \~russian Оператор сохранения для PIVector2D сложных типов
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {
|
||||||
|
s << int(v.rows()) << int(v.cols()) << v.toPlainVector();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// restore operators for complex types
|
||||||
|
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator for PIVector of any compound type
|
||||||
|
//! \~russian Оператор извлечения для PIVector сложных типов
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
}
|
||||||
|
int sz; s >> sz;
|
||||||
|
v.resize(sz);
|
||||||
|
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator for PIDeque of any compound type
|
||||||
|
//! \~russian Оператор извлечения для PIDeque сложных типов
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
}
|
||||||
|
int sz; s >> sz;
|
||||||
|
v.resize(sz);
|
||||||
|
for (int i = 0; i < sz; ++i) s >> v[i];
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator for PIVector2D of any compound type
|
||||||
|
//! \~russian Оператор извлечения для PIVector2D сложных типов
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {
|
||||||
|
if (s.size_s() < 8) {
|
||||||
|
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 8);
|
||||||
|
}
|
||||||
|
int r,c;
|
||||||
|
PIVector<T> tmp;
|
||||||
|
s >> r >> c >> tmp;
|
||||||
|
v = PIVector2D<T>(r, c, tmp);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// other types
|
||||||
|
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Store operator
|
||||||
|
//! \~russian Оператор сохранения
|
||||||
|
template <typename Key, typename T>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
|
||||||
|
// s << int(v.pim_index.size_s());
|
||||||
|
// for (uint i = 0; i < v.size(); ++i)
|
||||||
|
// s << int(v.pim_index[i].index) << v.pim_index[i].key;
|
||||||
|
s << v.pim_content;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \relatesalso PIByteArray
|
||||||
|
//! \~english Restore operator
|
||||||
|
//! \~russian Оператор извлечения
|
||||||
|
template <typename Key, typename T>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
|
||||||
|
if (s.size_s() < 4) {
|
||||||
|
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
|
||||||
|
assert(s.size_s() >= 4);
|
||||||
|
}
|
||||||
|
// int sz; s >> sz; v.pim_index.resize(sz);
|
||||||
|
// int ind = 0;
|
||||||
|
// for (int i = 0; i < sz; ++i) {
|
||||||
|
// s >> ind >> v.pim_index[i].key;
|
||||||
|
// v.pim_index[i].index = ind;
|
||||||
|
// }
|
||||||
|
s >> v.pim_content;
|
||||||
|
// if (v.pim_content.size_s() != v.pim_index.size_s()) {
|
||||||
|
// piCout << "Warning: loaded invalid PIMap, clear";
|
||||||
|
// v.clear();
|
||||||
|
// }
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator <<(PIByteArray & s, const T & ) {
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator << for complex type!");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
|
||||||
|
inline PIByteArray & operator >>(PIByteArray & s, T & ) {
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value, "[PIByteArray] Error: using undeclared operator >> for complex type!");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \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()) {
|
||||||
|
PIByteArray ba(data);
|
||||||
|
ba >> ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PIBYTEARRAY_H
|
||||||
@@ -87,10 +87,11 @@ ushort charFromCodepage(const char * c, int size, const char * codepage, int * t
|
|||||||
|
|
||||||
|
|
||||||
int charCompare(const PIChar & f, const PIChar & s) {
|
int charCompare(const PIChar & f, const PIChar & s) {
|
||||||
if (f.isAscii() && s.isAscii()) return strncmp(f.toCharPtr(), s.toCharPtr(), 1);
|
if (f.isAscii() && s.isAscii())
|
||||||
|
return strncmp(f.toCharPtr(), s.toCharPtr(), 1);
|
||||||
return
|
return
|
||||||
#ifdef PIP_ICU
|
#ifdef PIP_ICU
|
||||||
u_strCompare((const UChar *)f.toWCharPtr(), 1, (const UChar *)s.toWCharPtr(), 1, 0);
|
u_strCompare((const UChar*)f.toWCharPtr(), 1, (const UChar*)s.toWCharPtr(), 1, FALSE);
|
||||||
#else
|
#else
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
CompareStringW(LOCALE_USER_DEFAULT, 0, (PCNZWCH)f.toWCharPtr(), 1, (PCNZWCH)s.toWCharPtr(), 1) - 2;
|
CompareStringW(LOCALE_USER_DEFAULT, 0, (PCNZWCH)f.toWCharPtr(), 1, (PCNZWCH)s.toWCharPtr(), 1) - 2;
|
||||||
@@ -111,6 +112,13 @@ bool winIsCharType(const ushort * ch, int type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PIChar::PIChar(const char * c, int * bytes) {
|
||||||
|
ch = charFromCodepage(c, 4, __syslocname__, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PIChar PIChar::fromConsole(char c) {
|
PIChar PIChar::fromConsole(char c) {
|
||||||
PIChar ret;
|
PIChar ret;
|
||||||
ret.ch = charFromCodepage(&c, 1, __sysoemname__);
|
ret.ch = charFromCodepage(&c, 1, __sysoemname__);
|
||||||
@@ -125,21 +133,10 @@ PIChar PIChar::fromSystem(char c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIChar PIChar::fromSystem(const char * c) {
|
|
||||||
PIChar ret;
|
|
||||||
int l = 0;
|
|
||||||
while (c[l] != '\0' && l < 4)
|
|
||||||
++l;
|
|
||||||
ret.ch = charFromCodepage(c, l, __syslocname__);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PIChar PIChar::fromUTF8(const char * c) {
|
PIChar PIChar::fromUTF8(const char * c) {
|
||||||
PIChar ret;
|
PIChar ret;
|
||||||
int l = 0;
|
int l = 0;
|
||||||
while (c[l] != '\0' && l < 4)
|
while (c[l] != '\0') ++l;
|
||||||
++l;
|
|
||||||
ret.ch = charFromCodepage(c, l, __utf8name__);
|
ret.ch = charFromCodepage(c, l, __utf8name__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -334,7 +331,8 @@ PIChar PIChar::toUpper() const {
|
|||||||
#else
|
#else
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
ushort wc = 0;
|
ushort wc = 0;
|
||||||
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1) return PIChar(wc);
|
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1)
|
||||||
|
return PIChar(wc);
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
return PIChar((ushort)towupper(ch));
|
return PIChar((ushort)towupper(ch));
|
||||||
@@ -351,7 +349,8 @@ PIChar PIChar::toLower() const {
|
|||||||
#else
|
#else
|
||||||
# ifdef WINDOWS
|
# ifdef WINDOWS
|
||||||
ushort wc = 0;
|
ushort wc = 0;
|
||||||
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1) return PIChar(wc);
|
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1)
|
||||||
|
return PIChar(wc);
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
return PIChar((ushort)towlower(ch));
|
return PIChar((ushort)towlower(ch));
|
||||||
@@ -360,9 +359,8 @@ PIChar PIChar::toLower() const {
|
|||||||
|
|
||||||
PICout operator <<(PICout s, const PIChar & v) {
|
PICout operator <<(PICout s, const PIChar & v) {
|
||||||
s.space();
|
s.space();
|
||||||
s.saveAndSetControls(0);
|
s.setControl(0, true);
|
||||||
if (v.isAscii())
|
if (v.isAscii()) s << char(v.ch);
|
||||||
s << char(v.ch);
|
|
||||||
else {
|
else {
|
||||||
#ifdef PIP_ICU
|
#ifdef PIP_ICU
|
||||||
UErrorCode e((UErrorCode)0);
|
UErrorCode e((UErrorCode)0);
|
||||||
@@ -382,6 +380,6 @@ PICout operator<<(PICout s, const PIChar & v) {
|
|||||||
s << PIString(v);
|
s << PIString(v);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
s.restoreControls();
|
s.restoreControl();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*! \file pichar.h
|
/*! \file pichar.h
|
||||||
* \ingroup Text
|
* \ingroup Core
|
||||||
* \~\brief
|
* \~\brief
|
||||||
* \~english Single string character
|
* \~english Single string character
|
||||||
* \~russian Один символ строки
|
* \~russian Один символ строки
|
||||||
@@ -32,18 +32,18 @@ extern PIP_EXPORT char * __syslocname__;
|
|||||||
extern PIP_EXPORT char * __sysoemname__;
|
extern PIP_EXPORT char * __sysoemname__;
|
||||||
extern PIP_EXPORT char * __utf8name__;
|
extern PIP_EXPORT char * __utf8name__;
|
||||||
|
|
||||||
//! \ingroup Text
|
//! \ingroup Core
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english %PIChar represents a single character.
|
//! \~english %PIChar represents a single character.
|
||||||
//! \~russian %PIChar представляет собой один символ строки.
|
//! \~russian %PIChar представляет собой один символ строки.
|
||||||
class PIP_EXPORT PIChar {
|
class PIP_EXPORT PIChar
|
||||||
|
{
|
||||||
friend class PIString;
|
friend class PIString;
|
||||||
friend PIP_EXPORT PICout operator<<(PICout s, const PIChar & v);
|
friend PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! \~english Contructs Ascii symbol
|
//! \~english Contructs Ascii symbol
|
||||||
//! \~russian Создает символ Ascii
|
//! \~russian Создает символ Ascii
|
||||||
PIChar(char c) { ch = c; }
|
PIChar(char c) {ch = c; ch &= 0xFF;}
|
||||||
|
|
||||||
//! \~english Contructs ascii symbol
|
//! \~english Contructs ascii symbol
|
||||||
//! \~russian Создает символ Ascii
|
//! \~russian Создает символ Ascii
|
||||||
@@ -57,23 +57,17 @@ public:
|
|||||||
//! \~russian Создает 2-байтный символ из `wchar_t`
|
//! \~russian Создает 2-байтный символ из `wchar_t`
|
||||||
PIChar(wchar_t c) {ch = c;}
|
PIChar(wchar_t c) {ch = c;}
|
||||||
|
|
||||||
//! \~english Contructs 2-bytes symbol from `char16_t`
|
//! \~english Contructs symbol from system locale and no more than 4 bytes of string
|
||||||
//! \~russian Создает 2-байтный символ из `char16_t`
|
//! \~russian Создает символ из системной локали не более 4 байт длины
|
||||||
PIChar(char16_t c) { ch = c; }
|
PIChar(const char * c, int * bytes = 0);
|
||||||
|
|
||||||
//! \~english Copy operator
|
//! \~english Copy operator
|
||||||
//! \~russian Оператор присваивания
|
//! \~russian Оператор присваивания
|
||||||
PIChar & operator=(const char v) {
|
PIChar & operator =(const char v) {ch = v; return *this;}
|
||||||
ch = v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Copy operator
|
//! \~english Copy operator
|
||||||
//! \~russian Оператор присваивания
|
//! \~russian Оператор присваивания
|
||||||
PIChar & operator=(const wchar_t v) {
|
PIChar & operator =(const wchar_t v) {ch = v; return *this;}
|
||||||
ch = v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -81,7 +75,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
bool operator!=(const PIChar & o) const { return !(*this == o); }
|
bool operator !=(const PIChar & o) const {return !(o == *this);}
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -177,91 +171,95 @@ public:
|
|||||||
//! \~russian Возвращает символ из системной кодировки
|
//! \~russian Возвращает символ из системной кодировки
|
||||||
static PIChar fromSystem(char c);
|
static PIChar fromSystem(char c);
|
||||||
|
|
||||||
//! \~english Returns symbol from system codepage
|
|
||||||
//! \~russian Возвращает символ из системной кодировки
|
|
||||||
static PIChar fromSystem(const char * c);
|
|
||||||
|
|
||||||
//! \~english Returns symbol from UTF8 codepage
|
//! \~english Returns symbol from UTF8 codepage
|
||||||
//! \~russian Возвращает символ из UTF8 кодировки
|
//! \~russian Возвращает символ из UTF8 кодировки
|
||||||
static PIChar fromUTF8(const char * c);
|
static PIChar fromUTF8(const char * c);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ushort ch;
|
ushort ch;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Output operator to \a PICout
|
//! \~english Output operator to \a PICout
|
||||||
//! \~russian Оператор вывода в \a PICout
|
//! \~russian Оператор вывода в \a PICout
|
||||||
PIP_EXPORT PICout operator<<(PICout s, const PIChar & v);
|
PICout PIP_EXPORT operator <<(PICout s, const PIChar & v);
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator==(const char v, const PIChar & c) {
|
inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);}
|
||||||
return (PIChar(v) == c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator>(const char v, const PIChar & c) {
|
inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);}
|
||||||
return (PIChar(v) > c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator<(const char v, const PIChar & c) {
|
inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);}
|
||||||
return (PIChar(v) < c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator>=(const char v, const PIChar & c) {
|
inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);}
|
||||||
return (PIChar(v) >= c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator<=(const char v, const PIChar & c) {
|
inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);}
|
||||||
return (PIChar(v) <= c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator==(ushort v, const PIChar & c) {
|
inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);}
|
||||||
return (PIChar(v) == c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator>(ushort v, const PIChar & c) {
|
inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);}
|
||||||
return (PIChar(v) > c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator<(ushort v, const PIChar & c) {
|
inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);}
|
||||||
return (PIChar(v) < c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator>=(ushort v, const PIChar & c) {
|
inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);}
|
||||||
return (PIChar(v) >= c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \relatesalso PIChar
|
//! \relatesalso PIChar
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
inline bool operator<=(ushort v, const PIChar & c) {
|
inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= 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);}
|
||||||
|
|
||||||
|
//! \relatesalso PIChar
|
||||||
|
//! \~english Compare operator
|
||||||
|
//! \~russian Оператор сравнения
|
||||||
|
inline bool operator >(const int v, const PIChar & c) {return (PIChar((ushort)v) > c);}
|
||||||
|
|
||||||
|
//! \relatesalso PIChar
|
||||||
|
//! \~english Compare operator
|
||||||
|
//! \~russian Оператор сравнения
|
||||||
|
inline bool operator <(const int v, const PIChar & c) {return (PIChar((ushort)v) < c);}
|
||||||
|
|
||||||
|
//! \relatesalso PIChar
|
||||||
|
//! \~english Compare operator
|
||||||
|
//! \~russian Оператор сравнения
|
||||||
|
inline bool operator >=(const int v, const PIChar & c) {return (PIChar((ushort)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
|
#endif // PICHAR_H
|
||||||
@@ -110,12 +110,14 @@ PIByteArray PIChunkStream::data() const {
|
|||||||
|
|
||||||
int PIChunkStream::read() {
|
int PIChunkStream::read() {
|
||||||
switch (version_) {
|
switch (version_) {
|
||||||
case Version_1: (*data_) >> last_id >> last_data; break;
|
case Version_1:
|
||||||
|
(*data_) >> last_id >> last_data;
|
||||||
|
break;
|
||||||
case Version_2:
|
case Version_2:
|
||||||
last_id = readVInt(*data_);
|
last_id = readVInt(*data_);
|
||||||
last_data.resize(readVInt(*data_));
|
last_data.resize(readVInt(*data_));
|
||||||
//piCout << last_id << last_data.size();
|
//piCout << last_id << last_data.size();
|
||||||
(*data_) >> PIMemoryBlock(last_data.data(), last_data.size_s());
|
(*data_) >> PIByteArray::RawData(last_data.data(), last_data.size_s());
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@@ -123,12 +125,15 @@ int PIChunkStream::read() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PIChunkStream::peekVInt(Version version_, uchar * data_, int sz, uint & ret) {
|
int PIChunkStream::peekVInt(Version version_, PIByteArray * data_, int pos, PIByteArray & hdr, uint & ret) {
|
||||||
switch (version_) {
|
switch (version_) {
|
||||||
case Version_1: memcpy(&ret, data_, 4); return 4;
|
case Version_1:
|
||||||
|
memcpy(&ret, data_->data(pos), 4);
|
||||||
|
return 4;
|
||||||
case Version_2: {
|
case Version_2: {
|
||||||
PIByteArray hdr(data_, piMini(5, sz));
|
hdr.resize(4);
|
||||||
hdr.resize(5);
|
hdr.fill(uchar(0));
|
||||||
|
memcpy(hdr.data(), data_->data(pos), piMini(4, data_->size_s() - pos));
|
||||||
uchar hsz = 0;
|
uchar hsz = 0;
|
||||||
ret = readVInt(hdr, &hsz);
|
ret = readVInt(hdr, &hsz);
|
||||||
return hsz;
|
return hsz;
|
||||||
@@ -148,17 +153,14 @@ void PIChunkStream::replaceChunk(int id, const PIByteArray & v) {
|
|||||||
pos.length = v.size_s();
|
pos.length = v.size_s();
|
||||||
if (size_mod != 0) {
|
if (size_mod != 0) {
|
||||||
auto it = data_map.makeIterator();
|
auto it = data_map.makeIterator();
|
||||||
while (it.next()) {
|
while (it.next())
|
||||||
if (it.value().start > pos.start) {
|
if (it.valueRef().start > pos.start)
|
||||||
it.value().start += size_mod;
|
it.valueRef().start += size_mod;
|
||||||
}
|
if (size_mod > 0)
|
||||||
}
|
|
||||||
if (size_mod > 0) {
|
|
||||||
data_->insert(pos.start, PIByteArray(size_mod));
|
data_->insert(pos.start, PIByteArray(size_mod));
|
||||||
} else {
|
else
|
||||||
data_->remove(pos.start, -size_mod);
|
data_->remove(pos.start, -size_mod);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
memcpy(data_->data(pos.start - pos.size_bytes), nsba.data(), nsba.size());
|
memcpy(data_->data(pos.start - pos.size_bytes), nsba.data(), nsba.size());
|
||||||
pos.start += nsba.size_s() - pos.size_bytes;
|
pos.start += nsba.size_s() - pos.size_bytes;
|
||||||
memcpy(data_->data(pos.start), v.data(), pos.length);
|
memcpy(data_->data(pos.start), v.data(), pos.length);
|
||||||
@@ -170,9 +172,10 @@ void PIChunkStream::readAll() {
|
|||||||
if (!data_) return;
|
if (!data_) return;
|
||||||
int pos = 0, sz = data_->size_s(), hsz = 0;
|
int pos = 0, sz = data_->size_s(), hsz = 0;
|
||||||
uint csz = 0, cid = 0;
|
uint csz = 0, cid = 0;
|
||||||
|
PIByteArray hdr;
|
||||||
while (pos < sz) {
|
while (pos < sz) {
|
||||||
pos += peekVInt((Version)version_, data_->data(pos), data_->size_s() - pos, cid);
|
pos += peekVInt((Version)version_, data_, pos, hdr, cid);
|
||||||
hsz = peekVInt((Version)version_, data_->data(pos), data_->size_s() - pos, csz);
|
hsz = peekVInt((Version)version_, data_, pos, hdr, csz);
|
||||||
pos += hsz;
|
pos += hsz;
|
||||||
data_map[cid] = CacheEntry(pos, csz, hsz);
|
data_map[cid] = CacheEntry(pos, csz, hsz);
|
||||||
pos += csz;
|
pos += csz;
|
||||||
@@ -180,7 +183,20 @@ void PIChunkStream::readAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIChunkStream::~PIChunkStream() {}
|
PIChunkStream::~PIChunkStream() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIChunkStream::extract(PIByteArray & data, bool read_all) {
|
||||||
|
if (data.size_s() < 4) return false;
|
||||||
|
data >> tmp_data;
|
||||||
|
if (tmp_data.size_s() < 4) return false;
|
||||||
|
data_ = &tmp_data;
|
||||||
|
_init();
|
||||||
|
if (read_all)
|
||||||
|
readAll();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIChunkStream::_init() {
|
void PIChunkStream::_init() {
|
||||||
@@ -192,41 +208,27 @@ void PIChunkStream::_init() {
|
|||||||
if ((v & 0x80) == 0x80) {
|
if ((v & 0x80) == 0x80) {
|
||||||
v &= 0x7f;
|
v &= 0x7f;
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case 2:
|
case 2: version_ = (uchar)Version_2; data_->pop_front(); first_byte_taken = true; break;
|
||||||
version_ = (uchar)Version_2;
|
|
||||||
data_->pop_front();
|
|
||||||
first_byte_taken = true;
|
|
||||||
break;
|
|
||||||
default: version_ = Version_1; break;
|
default: version_ = Version_1; break;
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
version_ = Version_1;
|
version_ = Version_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint PIChunkStream::readVInt(PIByteArray & s, uchar * bytes_cnt) {
|
uint PIChunkStream::readVInt(PIByteArray & s, uchar * bytes_cnt) {
|
||||||
if (s.isEmpty()) return 0;
|
if (s.isEmpty()) return 0;
|
||||||
uchar bytes[4];
|
uchar bytes[4]; s >> bytes[0];
|
||||||
uchar abc;
|
uchar abc = 0;
|
||||||
s >> bytes[0];
|
|
||||||
if (bytes[0] == 0xf0) {
|
|
||||||
abc = 3;
|
|
||||||
for (int i = 0; i < 4; ++i)
|
|
||||||
s >> bytes[i];
|
|
||||||
if (bytes_cnt) *bytes_cnt = 5;
|
|
||||||
} else {
|
|
||||||
for (abc = 0; abc < 3; ++abc) {
|
for (abc = 0; abc < 3; ++abc) {
|
||||||
uchar mask = (0x80 >> abc);
|
uchar mask = (0x80 >> abc);
|
||||||
if ((bytes[0] & mask) == mask) {
|
if ((bytes[0] & mask) == mask) {
|
||||||
bytes[0] &= (mask - 1);
|
bytes[0] &= (mask - 1);
|
||||||
s >> bytes[abc + 1];
|
s >> bytes[abc + 1];
|
||||||
} else
|
} else break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (bytes_cnt) *bytes_cnt = (abc + 1);
|
if (bytes_cnt) *bytes_cnt = (abc + 1);
|
||||||
}
|
|
||||||
uint ret = 0;
|
uint ret = 0;
|
||||||
for (int i = 0; i <= abc; ++i) {
|
for (int i = 0; i <= abc; ++i) {
|
||||||
ret += (bytes[i] << (8 * ((int)abc - i)));
|
ret += (bytes[i] << (8 * ((int)abc - i)));
|
||||||
@@ -236,15 +238,18 @@ uint PIChunkStream::readVInt(PIByteArray & s, uchar * bytes_cnt) {
|
|||||||
|
|
||||||
|
|
||||||
void PIChunkStream::writeVInt(PIByteArray & s, uint val) {
|
void PIChunkStream::writeVInt(PIByteArray & s, uint val) {
|
||||||
|
if (val > 0xfffffff) return;
|
||||||
if (val <= 0x7f) {
|
if (val <= 0x7f) {
|
||||||
s << uchar(val);
|
s << uchar(val);
|
||||||
} else if (val <= 0x3fff) {
|
return;
|
||||||
|
}
|
||||||
|
if (val <= 0x3fff) {
|
||||||
s << uchar((val >> 8) | 0x80) << uchar(val & 0xff);
|
s << uchar((val >> 8) | 0x80) << uchar(val & 0xff);
|
||||||
} else if (val <= 0x1fffff) {
|
return;
|
||||||
|
}
|
||||||
|
if (val <= 0x1fffff) {
|
||||||
s << uchar((val >> 16) | 0xc0) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
s << uchar((val >> 16) | 0xc0) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
||||||
} else if (val <= 0xfffffff) {
|
return;
|
||||||
|
}
|
||||||
s << uchar((val >> 24) | 0xe0) << uchar((val >> 16) & 0xff) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
s << uchar((val >> 24) | 0xe0) << uchar((val >> 16) & 0xff) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
||||||
} else {
|
|
||||||
s << uchar(0xf0) << uchar((val >> 24) & 0xff) << uchar((val >> 16) & 0xff) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*! \file pichunkstream.h
|
/*! \file pichunkstream.h
|
||||||
* \ingroup Serialization
|
* \ingroup Core
|
||||||
* \~\brief
|
* \~\brief
|
||||||
* \~english Binary markup de/serializator stream
|
* \~english Binary markup de/serializator stream
|
||||||
* \~russian Бинарный поток для де/сериализации с разметкой
|
* \~russian Бинарный поток для де/сериализации с разметкой
|
||||||
@@ -29,12 +29,14 @@
|
|||||||
#include "pibytearray.h"
|
#include "pibytearray.h"
|
||||||
|
|
||||||
|
|
||||||
//! \ingroup Serialization
|
//! \ingroup Core
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Class for binary de/serialization.
|
//! \~english Class for binary de/serialization.
|
||||||
//! \~russian Класс для бинарной де/сериализации.
|
//! \~russian Класс для бинарной де/сериализации.
|
||||||
class PIP_EXPORT PIChunkStream {
|
class PIP_EXPORT PIChunkStream
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! \~english
|
//! \~english
|
||||||
//! Version of data packing. Read-access %PIChunkStream automatic detect version, but write-access
|
//! Version of data packing. Read-access %PIChunkStream automatic detect version, but write-access
|
||||||
//! %PIChunkStream by default write in new version, be careful!
|
//! %PIChunkStream by default write in new version, be careful!
|
||||||
@@ -75,36 +77,21 @@ public:
|
|||||||
|
|
||||||
//! \~english 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" для записи в поток
|
//! \~russian Возвращает чанк с ID "id" и значением "data" для записи в поток
|
||||||
template<typename T>
|
template <typename T> static ChunkConst<T> chunk(int id, const T & data) {return ChunkConst<T>(id, data);}
|
||||||
static ChunkConst<T> chunk(int id, const T & data) {
|
|
||||||
return ChunkConst<T>(id, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Add to this stream chunk with ID "id" and value "data"
|
//! \~english Add to this stream chunk with ID "id" and value "data"
|
||||||
//! \~russian Добавляет в этот поток чанк с ID "id" и значением "data"
|
//! \~russian Добавляет в этот поток чанк с ID "id" и значением "data"
|
||||||
template<typename T>
|
template <typename T> PIChunkStream & add(int id, const T & data) {*this << ChunkConst<T>(id, data); return *this;}
|
||||||
PIChunkStream & add(int id, const T & data) {
|
|
||||||
*this << ChunkConst<T>(id, data);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english
|
//! \~english
|
||||||
//! Extract %PIByteArray from "stream" and set it current stream.
|
//! Extract %PIByteArray from "data" and set it current stream.
|
||||||
//! If "read_all" then call \a readAll() after extract.
|
//! If "read_all" then call \a readAll() after extract.
|
||||||
//! Returns if has data to read.
|
//! Returns if has data to read.
|
||||||
//! \~russian
|
//! \~russian
|
||||||
//! Извлекает %PIByteArray из "stream" и инициализирует им поток.
|
//! Извлекает %PIByteArray из "data" и инициализирует им поток.
|
||||||
//! Если указан "read_all", то вызывает \a readAll() после инициализации.
|
//! Если указан "read_all", то вызывает \a readAll() после инициализации.
|
||||||
//! Возвращает если ли данные для чтения.
|
//! Возвращает если ли данные для чтения.
|
||||||
template<typename T>
|
bool extract(PIByteArray & data, bool read_all = false);
|
||||||
bool extract(PIBinaryStream<T> & stream, bool read_all = false) {
|
|
||||||
stream >> tmp_data;
|
|
||||||
if (stream.wasReadError() || tmp_data.size_s() < 4) return false;
|
|
||||||
data_ = &tmp_data;
|
|
||||||
_init();
|
|
||||||
if (read_all) readAll();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSource(const PIByteArray & data);
|
void setSource(const PIByteArray & data);
|
||||||
void setSource(PIByteArray * data);
|
void setSource(PIByteArray * data);
|
||||||
@@ -137,19 +124,12 @@ public:
|
|||||||
//! \~english Returns value of last readed chunk
|
//! \~english Returns value of last readed chunk
|
||||||
//! \~russian Возвращает значение последнего прочитанного чанка
|
//! \~russian Возвращает значение последнего прочитанного чанка
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T getData() const {
|
T getData() const {T ret; PIByteArray s(last_data); s >> ret; return ret;}
|
||||||
T ret{};
|
|
||||||
PIByteArray s(last_data);
|
|
||||||
s >> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Place value of last readed chunk into \"v\"
|
//! \~english Place value of last readed chunk into \"v\"
|
||||||
//! \~russian Записывает значение последнего прочитанного чанка в \"v\"
|
//! \~russian Записывает значение последнего прочитанного чанка в \"v\"
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void get(T & v) const {
|
void get(T & v) const {v = getData<T>();}
|
||||||
v = getData<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english 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() перед использованием этого метода!
|
//! \~russian Записывает значение чанка с ID \"id\" в \"v\". Необходимо вызвать \a readAll() перед использованием этого метода!
|
||||||
@@ -158,7 +138,8 @@ public:
|
|||||||
CacheEntry pos = data_map.value(id);
|
CacheEntry pos = data_map.value(id);
|
||||||
if (pos.start < 0 || pos.length == 0) return *this;
|
if (pos.start < 0 || pos.length == 0) return *this;
|
||||||
PIByteArray ba(data_->data(pos.start), pos.length);
|
PIByteArray ba(data_->data(pos.start), pos.length);
|
||||||
if (!ba.isEmpty()) ba >> v;
|
if (!ba.isEmpty())
|
||||||
|
ba >> v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +165,7 @@ private:
|
|||||||
|
|
||||||
static uint readVInt(PIByteArray & s, uchar * bytes = 0);
|
static uint readVInt(PIByteArray & s, uchar * bytes = 0);
|
||||||
static void writeVInt(PIByteArray & s, uint val);
|
static void writeVInt(PIByteArray & s, uint val);
|
||||||
static int peekVInt(Version version_, uchar * data_, int sz, uint & ret);
|
static int peekVInt(Version version_, PIByteArray * data_, int pos, PIByteArray & hdr, uint & ret);
|
||||||
void replaceChunk(int id, const PIByteArray & v);
|
void replaceChunk(int id, const PIByteArray & v);
|
||||||
|
|
||||||
int last_id;
|
int last_id;
|
||||||
@@ -193,10 +174,8 @@ private:
|
|||||||
PIMap<int, CacheEntry> data_map;
|
PIMap<int, CacheEntry> data_map;
|
||||||
bool first_byte_taken;
|
bool first_byte_taken;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c);
|
||||||
friend PIChunkStream & operator<<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c);
|
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst<T> & c);
|
||||||
template<typename T>
|
|
||||||
friend PIChunkStream & operator<<(PIChunkStream & s, const PIChunkStream::ChunkConst<T> & c);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -204,9 +183,12 @@ PIChunkStream & operator<<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c)
|
|||||||
PIByteArray ba;
|
PIByteArray ba;
|
||||||
ba << c.data;
|
ba << c.data;
|
||||||
switch (s.version_) {
|
switch (s.version_) {
|
||||||
case PIChunkStream::Version_1: (*(s.data_)) << c.id << ba; break;
|
case PIChunkStream::Version_1:
|
||||||
|
(*(s.data_)) << c.id << ba;
|
||||||
|
break;
|
||||||
case PIChunkStream::Version_2:
|
case PIChunkStream::Version_2:
|
||||||
if (s.data_->isEmpty()) (*(s.data_)) << uchar(uchar(s.version_) | 0x80);
|
if (s.data_->isEmpty())
|
||||||
|
(*(s.data_)) << uchar(uchar(s.version_) | 0x80);
|
||||||
PIChunkStream::writeVInt(*(s.data_), c.id);
|
PIChunkStream::writeVInt(*(s.data_), c.id);
|
||||||
PIChunkStream::writeVInt(*(s.data_), ba.size());
|
PIChunkStream::writeVInt(*(s.data_), ba.size());
|
||||||
s.data_->append(ba);
|
s.data_->append(ba);
|
||||||
@@ -220,9 +202,12 @@ PIChunkStream & operator<<(PIChunkStream & s, const PIChunkStream::ChunkConst<T>
|
|||||||
PIByteArray ba;
|
PIByteArray ba;
|
||||||
ba << c.data;
|
ba << c.data;
|
||||||
switch (s.version_) {
|
switch (s.version_) {
|
||||||
case PIChunkStream::Version_1: (*(s.data_)) << c.id << ba; break;
|
case PIChunkStream::Version_1:
|
||||||
|
(*(s.data_)) << c.id << ba;
|
||||||
|
break;
|
||||||
case PIChunkStream::Version_2:
|
case PIChunkStream::Version_2:
|
||||||
if (s.data_->isEmpty()) (*(s.data_)) << uchar(uchar(s.version_) | 0x80);
|
if (s.data_->isEmpty())
|
||||||
|
(*(s.data_)) << uchar(uchar(s.version_) | 0x80);
|
||||||
PIChunkStream::writeVInt(*(s.data_), c.id);
|
PIChunkStream::writeVInt(*(s.data_), c.id);
|
||||||
PIChunkStream::writeVInt(*(s.data_), ba.size());
|
PIChunkStream::writeVInt(*(s.data_), ba.size());
|
||||||
s.data_->append(ba);
|
s.data_->append(ba);
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "picli.h"
|
#include "picli.h"
|
||||||
|
|
||||||
#include "pisysteminfo.h"
|
#include "pisysteminfo.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@
|
|||||||
//! Этот класс предоставляет удобный механизм для разбора аргументов командной строки.
|
//! Этот класс предоставляет удобный механизм для разбора аргументов командной строки.
|
||||||
//! Сперва необходимо добавить аргументы в %PICLI с помощью методов \a addArgument().
|
//! Сперва необходимо добавить аргументы в %PICLI с помощью методов \a addArgument().
|
||||||
//! Далее можно проверять аргументы на наличие в командной строке методом \a hasArgument(),
|
//! Далее можно проверять аргументы на наличие в командной строке методом \a hasArgument(),
|
||||||
//! а также получать их значения при помощи \a argumentValue().
|
//! а также получить их значения при помощи \a argumentValue().
|
||||||
//!
|
//!
|
||||||
//! \~english \section PICLI_sec1 Example
|
//! \~english \section PICLI_sec1 Example
|
||||||
//! \~russian \section PICLI_sec1 Пример
|
//! \~russian \section PICLI_sec1 Пример
|
||||||
@@ -53,12 +52,8 @@
|
|||||||
//! piCout << "Value =" << cli.argumentValue("Value");
|
//! piCout << "Value =" << cli.argumentValue("Value");
|
||||||
//! return 0;
|
//! return 0;
|
||||||
//! }
|
//! }
|
||||||
//! \endcode
|
|
||||||
//!
|
//!
|
||||||
//! \~english These executions are similar:
|
//! These executions are similar:
|
||||||
//! \~russian Эти вызовы будут идентичны:
|
|
||||||
//!
|
|
||||||
//! \~\code
|
|
||||||
//! a.out -cd -v 10
|
//! a.out -cd -v 10
|
||||||
//! a.out --value 10 -dc
|
//! a.out --value 10 -dc
|
||||||
//! a.out -c -v 10 -d
|
//! a.out -c -v 10 -d
|
||||||
@@ -76,7 +71,8 @@ PICLI::PICLI(int argc, char * argv[]) {
|
|||||||
_count_mand = 0;
|
_count_mand = 0;
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
_args_raw << argv[i];
|
_args_raw << argv[i];
|
||||||
if (argc > 0) PISystemInfo::instance()->execCommand = argv[0];
|
if (argc > 0)
|
||||||
|
PISystemInfo::instance()->execCommand = argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,147 +26,77 @@
|
|||||||
#ifndef PICLI_H
|
#ifndef PICLI_H
|
||||||
#define PICLI_H
|
#define PICLI_H
|
||||||
|
|
||||||
#include "piset.h"
|
|
||||||
#include "pistringlist.h"
|
#include "pistringlist.h"
|
||||||
|
#include "piset.h"
|
||||||
|
|
||||||
//! \ingroup Core
|
//! \ingroup Core
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Command-Line parser.
|
//! \~english Command-Line parser.
|
||||||
//! \~russian Парсер командной строки.
|
//! \~russian Парсер командной строки.
|
||||||
class PIP_EXPORT PICLI {
|
class PIP_EXPORT PICLI
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
//! \~english Constructs %PICLI from "argc" and "argv" from "int main()" method.
|
|
||||||
//! \~russian Создает %PICLI из "argc" и "argv" из метода "int main()".
|
//! \~english Constructor
|
||||||
|
//! \~russian Конструктор
|
||||||
PICLI(int argc, char * argv[]);
|
PICLI(int argc, char * argv[]);
|
||||||
|
|
||||||
|
|
||||||
//! \~english Add argument with name "name", short key = name first letter and full key = name.
|
//! \~english Add argument with name "name", short key = name first letter and full key = name
|
||||||
//! \~russian Добавляет аргумент с именем "name", коротким ключом = первой букве имени и полным ключом = имени.
|
//! \~russian Добавляет аргумент с именем "name", коротким ключом = первой букве имени и полным ключом = имени
|
||||||
void addArgument(const PIString & name, bool value = false) {
|
void addArgument(const PIString & name, bool value = false) {_args << Argument(name, name[0], name, value); needParse = true;}
|
||||||
_args << Argument(name, name[0], name, value);
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Add argument with name "name", short key = "shortKey" and full key = name.
|
//! \~english Add argument with name "name", short key = "shortKey" and full key = name
|
||||||
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени.
|
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени
|
||||||
void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {
|
void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {_args << Argument(name, shortKey, name, value); needParse = true;}
|
||||||
_args << Argument(name, shortKey, name, value);
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Add argument with name "name", short key = "shortKey" and full key = name.
|
//! \~english Add argument with name "name", short key = "shortKey" and full key = name
|
||||||
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени.
|
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = имени
|
||||||
void addArgument(const PIString & name, const char * shortKey, bool value = false) {
|
void addArgument(const PIString & name, const char * shortKey, bool value = false) {_args << Argument(name, PIChar(shortKey), name, value); needParse = true;}
|
||||||
_args << Argument(name, PIChar::fromUTF8(shortKey), name, value);
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey".
|
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey"
|
||||||
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey".
|
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey"
|
||||||
void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {
|
void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, shortKey, fullKey, value); needParse = true;}
|
||||||
_args << Argument(name, shortKey, fullKey, value);
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey".
|
//! \~english Add argument with name "name", short key = "shortKey" and full key = "fullKey"
|
||||||
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey".
|
//! \~russian Добавляет аргумент с именем "name", коротким ключом = "shortKey" и полным ключом = "fullKey"
|
||||||
void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {
|
void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, PIChar(shortKey), fullKey, value); needParse = true;}
|
||||||
_args << Argument(name, PIChar::fromUTF8(shortKey), fullKey, value);
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \~english 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 это команда вызова программы.
|
//! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы
|
||||||
PIString rawArgument(int index) {
|
PIString rawArgument(int index) {parse(); return _args_raw[index];}
|
||||||
parse();
|
PIString mandatoryArgument(int index) {parse(); return _args_mand[index];}
|
||||||
return _args_raw[index];
|
PIString optionalArgument(int index) {parse(); return _args_opt[index];}
|
||||||
}
|
|
||||||
PIString mandatoryArgument(int index) {
|
|
||||||
parse();
|
|
||||||
return _args_mand[index];
|
|
||||||
}
|
|
||||||
PIString optionalArgument(int index) {
|
|
||||||
parse();
|
|
||||||
return _args_opt[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns unparsed command-line arguments.
|
//! \~english Returns unparsed command-line arguments
|
||||||
//! \~russian Возвращает исходные аргументы командной строки.
|
//! \~russian Возвращает исходные аргументы командной строки
|
||||||
const PIStringList & rawArguments() {
|
const PIStringList & rawArguments() {parse(); return _args_raw;}
|
||||||
parse();
|
const PIStringList & mandatoryArguments() {parse(); return _args_mand;}
|
||||||
return _args_raw;
|
const PIStringList & optionalArguments() {parse(); return _args_opt;}
|
||||||
}
|
|
||||||
const PIStringList & mandatoryArguments() {
|
|
||||||
parse();
|
|
||||||
return _args_mand;
|
|
||||||
}
|
|
||||||
const PIStringList & optionalArguments() {
|
|
||||||
parse();
|
|
||||||
return _args_opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns program execute command without arguments.
|
//! \~english Returns program execute command without arguments
|
||||||
//! \~russian Возвращает команду вызова программы без аргументов.
|
//! \~russian Возвращает команду вызова программы без аргументов
|
||||||
PIString programCommand() {
|
PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();}
|
||||||
parse();
|
|
||||||
return _args_raw.size() > 0 ? _args_raw.front() : PIString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns if argument "name" found.
|
//! \~english Returns if argument "name" found
|
||||||
//! \~russian Возвращает найден ли аргумент "name".
|
//! \~russian Возвращает найден ли аргумент "name"
|
||||||
bool hasArgument(const PIString & name) {
|
bool hasArgument(const PIString & name) {parse(); piForeach (Argument & i, _args) if (i.name == name && i.found) return true; return false;}
|
||||||
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.
|
//! \~english Returns argument "name" value, or empty string if this is no value
|
||||||
//! \~russian Возвращает значение аргумента "name" или пустую строку, если значения нет.
|
//! \~russian Возвращает значение аргумента "name" или пустую строку, если значения нет
|
||||||
PIString argumentValue(const PIString & name) {
|
PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();}
|
||||||
parse();
|
PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();}
|
||||||
piForeach(Argument & i, _args)
|
PIString argumentFullKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.full_key; return PIString();}
|
||||||
if (i.name == name && i.found) return i.value;
|
|
||||||
return PIString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns short key of argument "name", or empty string if this is no argument.
|
|
||||||
//! \~russian Возвращает короткий ключ аргумента "name" или пустую строку, если аргумента нет.
|
|
||||||
PIString argumentShortKey(const PIString & name) {
|
|
||||||
piForeach(Argument & i, _args)
|
|
||||||
if (i.name == name) return PIString(i.short_key);
|
|
||||||
return PIString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Returns full key of argument "name", or empty string if this is no argument.
|
|
||||||
//! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет.
|
|
||||||
PIString argumentFullKey(const PIString & name) {
|
|
||||||
piForeach(Argument & i, _args)
|
|
||||||
if (i.name == name) return i.full_key;
|
|
||||||
return PIString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const PIString & shortKeyPrefix() const {return _prefix_short;}
|
const PIString & shortKeyPrefix() const {return _prefix_short;}
|
||||||
const PIString & fullKeyPrefix() const {return _prefix_full;}
|
const PIString & fullKeyPrefix() const {return _prefix_full;}
|
||||||
int mandatoryArgumentsCount() const {return _count_mand;}
|
int mandatoryArgumentsCount() const {return _count_mand;}
|
||||||
int optionalArgumentsCount() const {return _count_opt;}
|
int optionalArgumentsCount() const {return _count_opt;}
|
||||||
void setShortKeyPrefix(const PIString & prefix) {
|
void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix; needParse = true;}
|
||||||
_prefix_short = prefix;
|
void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix; needParse = true;}
|
||||||
needParse = true;
|
void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;}
|
||||||
}
|
void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;}
|
||||||
void setFullKeyPrefix(const PIString & prefix) {
|
|
||||||
_prefix_full = prefix;
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
void setMandatoryArgumentsCount(const int count) {
|
|
||||||
_count_mand = count;
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
void setOptionalArgumentsCount(const int count) {
|
|
||||||
_count_opt = count;
|
|
||||||
needParse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug() const {return debug_;}
|
bool debug() const {return debug_;}
|
||||||
void setDebug(bool debug) {debug_ = debug;}
|
void setDebug(bool debug) {debug_ = debug;}
|
||||||
@@ -176,13 +106,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct Argument {
|
struct Argument {
|
||||||
Argument() {has_value = found = false;}
|
Argument() {has_value = found = false;}
|
||||||
Argument(const PIString & n, const PIChar & s, const PIString & f, bool v) {
|
Argument(const PIString & n, const PIChar & s, const PIString & f, bool v) {name = n; short_key = s; full_key = f; has_value = v; found = false;}
|
||||||
name = n;
|
|
||||||
short_key = s;
|
|
||||||
full_key = f;
|
|
||||||
has_value = v;
|
|
||||||
found = false;
|
|
||||||
}
|
|
||||||
PIString name;
|
PIString name;
|
||||||
PIChar short_key;
|
PIChar short_key;
|
||||||
PIString full_key;
|
PIString full_key;
|
||||||
@@ -198,6 +122,7 @@ private:
|
|||||||
PIVector<Argument> _args;
|
PIVector<Argument> _args;
|
||||||
int _count_mand, _count_opt;
|
int _count_mand, _count_opt;
|
||||||
bool needParse, debug_;
|
bool needParse, debug_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PICLI_H
|
#endif // PICLI_H
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ PIStringList PICollection::groups() {
|
|||||||
PIVector<const PIObject * > PICollection::groupElements(const PIString & group) {
|
PIVector<const PIObject * > PICollection::groupElements(const PIString & group) {
|
||||||
PIVector<PICollection::Group> & cg(_groups());
|
PIVector<PICollection::Group> & cg(_groups());
|
||||||
piForeachC (Group & g, cg)
|
piForeachC (Group & g, cg)
|
||||||
if (g.name == group) return g.elements;
|
if (g.name == group)
|
||||||
|
return g.elements;
|
||||||
return PIVector<const PIObject * >();
|
return PIVector<const PIObject * >();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +62,8 @@ bool PICollection::addToGroup(const PIString & group, const PIObject * element)
|
|||||||
piForeach (Group & g, cg)
|
piForeach (Group & g, cg)
|
||||||
if (g.name == group) {
|
if (g.name == group) {
|
||||||
for (int i = 0; i < g.elements.size_s(); ++i)
|
for (int i = 0; i < g.elements.size_s(); ++i)
|
||||||
if (PIString(g.elements[i]->className()) == n) return false;
|
if (PIString(g.elements[i]->className()) == n)
|
||||||
|
return false;
|
||||||
g.elements << element;
|
g.elements << element;
|
||||||
//piCout << "new group" << group << ", ok";
|
//piCout << "new group" << group << ", ok";
|
||||||
return true;
|
return true;
|
||||||
@@ -81,7 +83,9 @@ PIVector<PICollection::Group> & PICollection::_groups() {
|
|||||||
|
|
||||||
PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name, bool own) {
|
PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name, bool own) {
|
||||||
if (!element) return;
|
if (!element) return;
|
||||||
if (name.isNotEmpty()) const_cast<PIObject *>(element)->setName(name);
|
if (name.isNotEmpty())
|
||||||
|
const_cast<PIObject * >(element)->setName(name);
|
||||||
bool added = PICollection::addToGroup(group, element);
|
bool added = PICollection::addToGroup(group, element);
|
||||||
if (!added && own) delete element;
|
if (!added && own)
|
||||||
|
delete element;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,9 +104,9 @@
|
|||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english Helper to collect and retrieve classes to groups.
|
//! \~english Helper to collect and retrieve classes to groups.
|
||||||
//! \~russian Помощник для создания и получения классов в группы.
|
//! \~russian Помощник для создания и получения классов в группы.
|
||||||
class PIP_EXPORT PICollection {
|
class PIP_EXPORT PICollection
|
||||||
|
{
|
||||||
friend class __PICollectionInitializer;
|
friend class __PICollectionInitializer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PICollection() {;}
|
PICollection() {;}
|
||||||
|
|
||||||
@@ -133,6 +133,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static PIVector<Group> & _groups();
|
static PIVector<Group> & _groups();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PICOLLECTION_H
|
#endif // PICOLLECTION_H
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "piconstchars.h"
|
#include "piconstchars.h"
|
||||||
|
|
||||||
#include "pistring.h"
|
#include "pistring.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -43,13 +42,6 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
|
|
||||||
bool PIConstChars::contains(char c) const {
|
|
||||||
for (int i = 0; i < (int)len; ++i)
|
|
||||||
if (str[i] == c) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PIConstChars::startsWith(const PIConstChars & str) const {
|
bool PIConstChars::startsWith(const PIConstChars & str) const {
|
||||||
if (size() < str.size()) return false;
|
if (size() < str.size()) return false;
|
||||||
return str == left(str.size());
|
return str == left(str.size());
|
||||||
@@ -84,7 +76,8 @@ PIConstChars PIConstChars::mid(const int start, const int len) const {
|
|||||||
if (l < 0) {
|
if (l < 0) {
|
||||||
return PIConstChars(str + s, (int)size() - s);
|
return PIConstChars(str + s, (int)size() - s);
|
||||||
} else {
|
} else {
|
||||||
if (l > (int)size() - s) l = (int)size() - s;
|
if (l > (int)size() - s)
|
||||||
|
l = (int)size() - s;
|
||||||
return PIConstChars(str + s, l);
|
return PIConstChars(str + s, l);
|
||||||
}
|
}
|
||||||
return PIConstChars("");
|
return PIConstChars("");
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*! \file piconstchars.h
|
/*! \file piconstchars.h
|
||||||
* \ingroup Text
|
* \ingroup Core
|
||||||
* \brief
|
* \brief
|
||||||
* \~english C-String class
|
* \~english C-String class
|
||||||
* \~russian Класс C-строки
|
* \~russian Класс C-строки
|
||||||
@@ -29,12 +29,13 @@
|
|||||||
#include "picout.h"
|
#include "picout.h"
|
||||||
|
|
||||||
|
|
||||||
//! \ingroup Text
|
//! \ingroup Core
|
||||||
//! \~\brief
|
//! \~\brief
|
||||||
//! \~english C-String class.
|
//! \~english C-String class.
|
||||||
//! \~russian Класс C-строки.
|
//! \~russian Класс C-строки.
|
||||||
class PIP_EXPORT PIConstChars {
|
class PIP_EXPORT PIConstChars {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! \~english Contructs an null string.
|
//! \~english Contructs an null string.
|
||||||
//! \~russian Создает нулевую строку.
|
//! \~russian Создает нулевую строку.
|
||||||
PIConstChars() {}
|
PIConstChars() {}
|
||||||
@@ -85,10 +86,6 @@ public:
|
|||||||
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
|
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
|
||||||
inline bool isNotEmpty() const {return len > 0;}
|
inline bool isNotEmpty() const {return len > 0;}
|
||||||
|
|
||||||
//! \~english Returns \c true if string contains character "c".
|
|
||||||
//! \~russian Возвращает \c true если строка содержит символ "c".
|
|
||||||
bool contains(char c) const;
|
|
||||||
|
|
||||||
//! \~english Returns characters length of string.
|
//! \~english Returns characters length of string.
|
||||||
//! \~russian Возвращает длину строки в символах.
|
//! \~russian Возвращает длину строки в символах.
|
||||||
inline size_t length() const {return len;}
|
inline size_t length() const {return len;}
|
||||||
@@ -209,7 +206,8 @@ public:
|
|||||||
if ( isNull() && s.isNull()) return false;
|
if ( isNull() && s.isNull()) return false;
|
||||||
if ( isNull() && !s.isNull()) return true ;
|
if ( isNull() && !s.isNull()) return true ;
|
||||||
if (!isNull() && s.isNull()) return false;
|
if (!isNull() && s.isNull()) return false;
|
||||||
if (size() == s.size()) return strcmp(str, s.str) < 0;
|
if (size() == s.size())
|
||||||
|
return strcmp(str, s.str) < 0;
|
||||||
return size() < s.size();
|
return size() < s.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +217,8 @@ public:
|
|||||||
if ( isNull() && s.isNull()) return false;
|
if ( isNull() && s.isNull()) return false;
|
||||||
if ( isNull() && !s.isNull()) return false;
|
if ( isNull() && !s.isNull()) return false;
|
||||||
if (!isNull() && s.isNull()) return true ;
|
if (!isNull() && s.isNull()) return true ;
|
||||||
if (size() == s.size()) return strcmp(str, s.str) > 0;
|
if (size() == s.size())
|
||||||
|
return strcmp(str, s.str) > 0;
|
||||||
return size() > s.size();
|
return size() > s.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,10 +256,7 @@ inline PICout operator<<(PICout s, const PIConstChars & v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<> inline uint piHash(const PIConstChars & s) {return s.hash();}
|
||||||
inline uint piHash(const PIConstChars & s) {
|
|
||||||
return s.hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PICONSTCHARS_H
|
#endif // PICONSTCHARS_H
|
||||||
@@ -51,12 +51,11 @@
|
|||||||
#ifndef PICOREMODULE_H
|
#ifndef PICOREMODULE_H
|
||||||
#define PICOREMODULE_H
|
#define PICOREMODULE_H
|
||||||
|
|
||||||
#include "pichunkstream.h"
|
|
||||||
#include "picli.h"
|
|
||||||
#include "picollection.h"
|
#include "picollection.h"
|
||||||
#include "pijson.h"
|
|
||||||
#include "piobject.h"
|
#include "piobject.h"
|
||||||
#include "pipropertystorage.h"
|
|
||||||
#include "pitime.h"
|
#include "pitime.h"
|
||||||
|
#include "picli.h"
|
||||||
|
#include "pichunkstream.h"
|
||||||
|
#include "pipropertystorage.h"
|
||||||
|
|
||||||
#endif // PICOREMODULE_H
|
#endif // PICOREMODULE_H
|
||||||
|
|||||||
@@ -16,21 +16,20 @@
|
|||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "picout.h"
|
|
||||||
|
|
||||||
#include "pibytearray.h"
|
|
||||||
#include "piincludes_p.h"
|
#include "piincludes_p.h"
|
||||||
#include "piobject.h"
|
#include "picout.h"
|
||||||
|
#include "pibytearray.h"
|
||||||
#include "pistack.h"
|
#include "pistack.h"
|
||||||
|
#include "piobject.h"
|
||||||
#include "pistring_std.h"
|
#include "pistring_std.h"
|
||||||
#ifdef HAS_LOCALE
|
#ifdef HAS_LOCALE
|
||||||
# include <codecvt>
|
|
||||||
# include <locale>
|
# include <locale>
|
||||||
|
# include <codecvt>
|
||||||
#endif
|
#endif
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
# include <wincon.h>
|
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <wingdi.h>
|
# include <wingdi.h>
|
||||||
|
# include <wincon.h>
|
||||||
# define COMMON_LVB_UNDERSCORE 0x8000
|
# define COMMON_LVB_UNDERSCORE 0x8000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -107,13 +106,13 @@
|
|||||||
|
|
||||||
class NotifierObject: public PIObject {
|
class NotifierObject: public PIObject {
|
||||||
PIOBJECT(NotifierObject)
|
PIOBJECT(NotifierObject)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NotifierObject() {}
|
NotifierObject() {}
|
||||||
EVENT2(finished, int, id, PIString *, buffer);
|
EVENT2(finished, int, id, PIString*, buffer)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PICout::Notifier::Notifier() {
|
PICout::Notifier::Notifier() {
|
||||||
o = new NotifierObject();
|
o = new NotifierObject();
|
||||||
}
|
}
|
||||||
@@ -130,16 +129,12 @@ PIObject * PICout::Notifier::object() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using namespace PICoutManipulators;
|
using namespace PICoutManipulators;
|
||||||
|
|
||||||
PIMutex & PICout::__mutex__() {
|
PIMutex & PICout::__mutex__() {static PIMutex * ret = new PIMutex(); return *ret;}
|
||||||
static PIMutex * ret = new PIMutex();
|
PIString & PICout::__string__() {static PIString * ret = new PIString(); return *ret;}
|
||||||
return *ret;
|
|
||||||
}
|
|
||||||
PIString & PICout::__string__() {
|
|
||||||
static PIString * ret = new PIString();
|
|
||||||
return *ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout::OutputDevices PICout::devs = PICout::StdOut;
|
PICout::OutputDevices PICout::devs = PICout::StdOut;
|
||||||
|
|
||||||
@@ -159,26 +154,27 @@ DWORD PICout::__Private__::smode = 0;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
PICout::PICout(int controls): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(controls) {
|
PICout::PICout(int controls): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(controls) {
|
||||||
buffer_ = nullptr;
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) {
|
PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) {
|
||||||
buffer_ = nullptr;
|
buffer_ = nullptr;
|
||||||
if (act_) init();
|
if (act_)
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout::PICout(const PICout & other)
|
PICout::PICout(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls): fo_(true), cc_(false),
|
||||||
: fo_(other.fo_)
|
fc_(false), act_(true), cnb_(10), co_(controls) {
|
||||||
, cc_(true)
|
init();
|
||||||
, fc_(false)
|
buffer_ = buffer;
|
||||||
, act_(other.act_)
|
id_ = id;
|
||||||
, cnb_(other.cnb_)
|
}
|
||||||
, attr_(other.attr_)
|
|
||||||
, id_(other.id_)
|
|
||||||
, buffer_(other.buffer_)
|
PICout::PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), act_(other.act_), cnb_(other.cnb_), attr_(other.attr_),
|
||||||
, co_(other.co_) {}
|
id_(other.id_), buffer_(other.buffer_), co_(other.co_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout::~PICout() {
|
PICout::~PICout() {
|
||||||
@@ -186,16 +182,14 @@ PICout::~PICout() {
|
|||||||
if (fc_) applyFormat(PICoutManipulators::Default);
|
if (fc_) applyFormat(PICoutManipulators::Default);
|
||||||
if (cc_) return;
|
if (cc_) return;
|
||||||
newLine();
|
newLine();
|
||||||
if ((co_ & NoLock) != NoLock) {
|
if ((co_ & NoLock) != NoLock)
|
||||||
PICout::__mutex__().unlock();
|
PICout::__mutex__().unlock();
|
||||||
}
|
if (buffer_)
|
||||||
if (buffer_) {
|
|
||||||
((NotifierObject*)Notifier::object())->finished(id_, buffer_);
|
((NotifierObject*)Notifier::object())->finished(id_, buffer_);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(PICoutAction v) {
|
PICout PICout::operator <<(const PICoutAction v) {
|
||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||||
@@ -204,9 +198,8 @@ PICout & PICout::operator<<(PICoutAction v) {
|
|||||||
#endif
|
#endif
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case PICoutManipulators::Flush:
|
case PICoutManipulators::Flush:
|
||||||
if (!buffer_ && isOutputDeviceActive(StdOut)) {
|
if (!buffer_ && isOutputDeviceActive(StdOut))
|
||||||
std::cout << std::flush;
|
std::cout << std::flush;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case PICoutManipulators::Backspace:
|
case PICoutManipulators::Backspace:
|
||||||
if (isOutputDeviceActive(StdOut)) {
|
if (isOutputDeviceActive(StdOut)) {
|
||||||
@@ -274,15 +267,15 @@ PICout & PICout::operator<<(PICoutAction v) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PICoutManipulators::SaveContol: saveControls(); break;
|
case PICoutManipulators::SaveContol: saveControl(); break;
|
||||||
case PICoutManipulators::RestoreControl: restoreControls(); break;
|
case PICoutManipulators::RestoreControl: restoreControl(); break;
|
||||||
default: break;
|
default: break;
|
||||||
};
|
};
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(PICoutManipulators::PICoutFormat v) {
|
PICout PICout::operator <<(const PICoutManipulators::PICoutFormat v) {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case PICoutManipulators::Bin: cnb_ = 2; break;
|
case PICoutManipulators::Bin: cnb_ = 2; break;
|
||||||
case PICoutManipulators::Oct: cnb_ = 8; break;
|
case PICoutManipulators::Oct: cnb_ = 8; break;
|
||||||
@@ -294,7 +287,7 @@ PICout & PICout::operator<<(PICoutManipulators::PICoutFormat v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(PIFlags<PICoutManipulators::PICoutFormat> v) {
|
PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) {
|
||||||
if (v[PICoutManipulators::Bin]) cnb_ = 2;
|
if (v[PICoutManipulators::Bin]) cnb_ = 2;
|
||||||
if (v[PICoutManipulators::Oct]) cnb_ = 8;
|
if (v[PICoutManipulators::Oct]) cnb_ = 8;
|
||||||
if (v[PICoutManipulators::Dec]) cnb_ = 10;
|
if (v[PICoutManipulators::Dec]) cnb_ = 10;
|
||||||
@@ -324,175 +317,121 @@ PICout & PICout::operator<<(PIFlags<PICoutManipulators::PICoutFormat> v) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PIINTCOUT(v) \
|
|
||||||
{ \
|
#define PICOUTTOTARGET(v) { \
|
||||||
if (!act_) return *this; \
|
|
||||||
space(); \
|
|
||||||
if (cnb_ == 10) { \
|
|
||||||
if (buffer_) {\
|
if (buffer_) {\
|
||||||
(*buffer_) += PIString::fromNumber(v); \
|
(*buffer_) << (v);\
|
||||||
} else {\
|
} else {\
|
||||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
||||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v); \
|
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||||
}\
|
}\
|
||||||
} else \
|
}
|
||||||
write(PIString::fromNumber(v, cnb_)); \
|
|
||||||
|
#define PINUMERICCOUT(v) { \
|
||||||
|
if (!act_) return *this; \
|
||||||
|
space(); \
|
||||||
|
if (cnb_ == 10) PICOUTTOTARGET(v) \
|
||||||
|
else write(PIString::fromNumber(v, cnb_)); \
|
||||||
return *this; \
|
return *this; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PIFLOATCOUT(v) \
|
|
||||||
{ \
|
|
||||||
if (buffer_) { \
|
|
||||||
(*buffer_) += PIString::fromNumber(v, 'g'); \
|
|
||||||
} else { \
|
|
||||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v); \
|
|
||||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g'); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const char * v) {if (!act_ || !v) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
|
||||||
|
|
||||||
PICout & PICout::operator<<(const PIString & v) {
|
PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
|
||||||
space();
|
|
||||||
quote();
|
|
||||||
write(v);
|
|
||||||
quote();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(const char * v) {
|
PICout PICout::operator <<(const char v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
|
||||||
if (!act_ || !v) return *this;
|
|
||||||
if (v[0] == '\0') return *this;
|
|
||||||
space();
|
|
||||||
quote();
|
|
||||||
write(v);
|
|
||||||
quote();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(bool v) {
|
PICout PICout::operator <<(const uchar v) {PINUMERICCOUT(ushort(v))}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const short int v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const ushort v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const int v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const uint v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const long v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const ulong v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const llong v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const ullong v) {PINUMERICCOUT(v)}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const float v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const double v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const void * v) {if (!act_) return *this; space(); PICOUTTOTARGET("0x") write(PIString::fromNumber(ullong(v), 16)); return *this;}
|
||||||
|
|
||||||
|
PICout PICout::operator <<(const PIObject * v) {
|
||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
space();
|
space();
|
||||||
if (v)
|
if (v == 0) PICOUTTOTARGET("PIObject*(0x0)")
|
||||||
write("true");
|
|
||||||
else
|
|
||||||
write("false");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(char v) {
|
|
||||||
if (!act_) return *this;
|
|
||||||
space();
|
|
||||||
write(v);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(uchar v){PIINTCOUT(ushort(v))}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(short int v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(ushort v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(int v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(uint v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(long v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(ulong v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(llong v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(ullong v){PIINTCOUT(v)}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(float v) {
|
|
||||||
if (!act_) return *this;
|
|
||||||
space();
|
|
||||||
PIFLOATCOUT(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(double v) {
|
|
||||||
if (!act_) return *this;
|
|
||||||
space();
|
|
||||||
PIFLOATCOUT(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(ldouble v) {
|
|
||||||
if (!act_) return *this;
|
|
||||||
space();
|
|
||||||
PIFLOATCOUT(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(const void * v) {
|
|
||||||
if (!act_) return *this;
|
|
||||||
space();
|
|
||||||
write("0x" + PIString::fromNumber(ullong(v), 16));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PICout & PICout::operator<<(const PIObject * v) {
|
|
||||||
if (!act_) return *this;
|
|
||||||
space();
|
|
||||||
if (v == 0)
|
|
||||||
write("PIObject*(0x0)");
|
|
||||||
else {
|
else {
|
||||||
write(v->className());
|
PICOUTTOTARGET(v->className())
|
||||||
write("*(0x" + PIString::fromNumber(ullong(v), 16) + ", \"" + v->name() + "\")");
|
PICOUTTOTARGET("*(0x")
|
||||||
|
write(PIString::fromNumber(ullong(v), 16));
|
||||||
|
PICOUTTOTARGET(", \"")
|
||||||
|
write(v->name());
|
||||||
|
PICOUTTOTARGET("\")")
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PICout & PICout::operator<<(PICoutSpecialChar v) {
|
PICout PICout::operator <<(const PICoutSpecialChar v) {
|
||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case Null:
|
case Null:
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += PIChar();
|
(*buffer_) << PIChar();
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
|
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar();
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NewLine:
|
case NewLine:
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += "\n";
|
(*buffer_) << "\n";
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << '\n';
|
if (isOutputDeviceActive(StdOut)) std::cout << '\n';
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
|
||||||
}
|
}
|
||||||
fo_ = true;
|
fo_ = true;
|
||||||
break;
|
break;
|
||||||
case Tab:
|
case Tab:
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += "\t";
|
(*buffer_) << "\t";
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << '\t';
|
if (isOutputDeviceActive(StdOut)) std::cout << '\t';
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\t";
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\t";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Esc:
|
case Esc:
|
||||||
#ifdef CC_VC
|
#ifdef CC_VC
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += PIChar(27);
|
(*buffer_) << PIChar(27);
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << char(27);
|
if (isOutputDeviceActive(StdOut)) std::cout << char(27);
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIChar(27);
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar(27);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += "\e";
|
(*buffer_) << "\e";
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << '\e';
|
if (isOutputDeviceActive(StdOut)) std::cout << '\e';
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\e";
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\e";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case Quote:
|
case Quote:
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += "\"";
|
(*buffer_) << "\"";
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@@ -500,14 +439,14 @@ PICout & PICout::operator<<(PICoutSpecialChar v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout & PICout::saveControls() {
|
PICout & PICout::saveControl() {
|
||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
PRIVATE->cos_.push(co_);
|
PRIVATE->cos_.push(co_);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout & PICout::restoreControls() {
|
PICout & PICout::restoreControl() {
|
||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
if (!PRIVATE->cos_.isEmpty()) {
|
if (!PRIVATE->cos_.isEmpty()) {
|
||||||
co_ = PRIVATE->cos_.top();
|
co_ = PRIVATE->cos_.top();
|
||||||
@@ -517,6 +456,9 @@ PICout & PICout::restoreControls() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef PICOUTTOTARGET
|
||||||
|
#undef PINUMERICCOUT
|
||||||
|
|
||||||
//! \details
|
//! \details
|
||||||
//! \~english
|
//! \~english
|
||||||
//! If it is not a first output and control \a AddSpaces is set space character is put
|
//! If it is not a first output and control \a AddSpaces is set space character is put
|
||||||
@@ -527,10 +469,10 @@ PICout & PICout::space() {
|
|||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
if (!fo_ && co_[AddSpaces]) {
|
if (!fo_ && co_[AddSpaces]) {
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += " ";
|
(*buffer_) << " ";
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << ' ';
|
if (isOutputDeviceActive(StdOut)) std::cout << ' ';
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += " ";
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fo_ = false;
|
fo_ = false;
|
||||||
@@ -547,10 +489,10 @@ PICout & PICout::quote() {
|
|||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
if (co_[AddQuotes]) {
|
if (co_[AddQuotes]) {
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += "\"";
|
(*buffer_) << "\"";
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\"";
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fo_ = false;
|
fo_ = false;
|
||||||
@@ -567,10 +509,10 @@ PICout & PICout::newLine() {
|
|||||||
if (!act_) return *this;
|
if (!act_) return *this;
|
||||||
if (co_[AddNewLine]) {
|
if (co_[AddNewLine]) {
|
||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
(*buffer_) += "\n";
|
(*buffer_) << "\n";
|
||||||
} else {
|
} else {
|
||||||
if (isOutputDeviceActive(StdOut)) std::cout << std::endl;
|
if (isOutputDeviceActive(StdOut)) std::cout << std::endl;
|
||||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() += "\n";
|
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fo_ = false;
|
fo_ = false;
|
||||||
@@ -578,18 +520,6 @@ PICout & PICout::newLine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout & PICout::write(char c) {
|
|
||||||
if (!act_) return *this;
|
|
||||||
if (buffer_) {
|
|
||||||
buffer_->append(c);
|
|
||||||
} else {
|
|
||||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << c;
|
|
||||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(c);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PICout & PICout::write(const char * str) {
|
PICout & PICout::write(const char * str) {
|
||||||
if (!act_ || !str) return *this;
|
if (!act_ || !str) return *this;
|
||||||
return write(str, strlen(str));
|
return write(str, strlen(str));
|
||||||
@@ -613,7 +543,8 @@ PICout & PICout::write(const PIString & s) {
|
|||||||
if (buffer_) {
|
if (buffer_) {
|
||||||
buffer_->append(s);
|
buffer_->append(s);
|
||||||
} else {
|
} else {
|
||||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) stdoutPIString(s);
|
if (PICout::isOutputDeviceActive(PICout::StdOut))
|
||||||
|
stdoutPIString(s);
|
||||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s);
|
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__().append(s);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -623,11 +554,9 @@ PICout & PICout::write(const PIString & s) {
|
|||||||
void PICout::stdoutPIString(const PIString & s) {
|
void PICout::stdoutPIString(const PIString & s) {
|
||||||
#ifdef HAS_LOCALE
|
#ifdef HAS_LOCALE
|
||||||
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> utf8conv;
|
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> utf8conv;
|
||||||
std::cout << utf8conv.to_bytes((char16_t *)&(const_cast<PIString &>(s).front()),
|
std::cout << utf8conv.to_bytes((char16_t*)&(const_cast<PIString&>(s).front()), (char16_t*)&(const_cast<PIString&>(s).front()) + s.size());
|
||||||
(char16_t *)&(const_cast<PIString &>(s).front()) + s.size());
|
|
||||||
#else
|
#else
|
||||||
for (PIChar c: s)
|
for (PIChar c: s) std::wcout.put(c.toWChar());
|
||||||
std::wcout.put(c.toWChar());
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,11 +571,11 @@ void PICout::init() {
|
|||||||
}
|
}
|
||||||
attr_ = __Private__::dattr;
|
attr_ = __Private__::dattr;
|
||||||
#endif
|
#endif
|
||||||
|
buffer_ = nullptr;
|
||||||
id_ = 0;
|
id_ = 0;
|
||||||
if ((co_ & NoLock) != NoLock) {
|
if ((co_ & NoLock) != NoLock)
|
||||||
PICout::__mutex__().lock();
|
PICout::__mutex__().lock();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PICout::applyFormat(PICoutFormat f) {
|
void PICout::applyFormat(PICoutFormat f) {
|
||||||
@@ -657,10 +586,7 @@ void PICout::applyFormat(PICoutFormat f) {
|
|||||||
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
|
static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
|
||||||
switch (f) {
|
switch (f) {
|
||||||
case Bin:
|
case Bin: case Oct: case Dec: case Hex: break;
|
||||||
case Oct:
|
|
||||||
case Dec:
|
|
||||||
case Hex: break;
|
|
||||||
case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break;
|
case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break;
|
||||||
case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break;
|
case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break;
|
||||||
case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break;
|
case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break;
|
||||||
@@ -685,10 +611,7 @@ void PICout::applyFormat(PICoutFormat f) {
|
|||||||
SetConsoleTextAttribute(__Private__::hOut, attr_);
|
SetConsoleTextAttribute(__Private__::hOut, attr_);
|
||||||
#else
|
#else
|
||||||
switch (f) {
|
switch (f) {
|
||||||
case Bin:
|
case Bin: case Oct: case Dec: case Hex: break;
|
||||||
case Oct:
|
|
||||||
case Dec:
|
|
||||||
case Hex: break;
|
|
||||||
case PICoutManipulators::Bold: printf("\e[1m"); break;
|
case PICoutManipulators::Bold: printf("\e[1m"); break;
|
||||||
case PICoutManipulators::Faint: printf("\e[2m"); break;
|
case PICoutManipulators::Faint: printf("\e[2m"); break;
|
||||||
case PICoutManipulators::Italic: printf("\e[3m"); break;
|
case PICoutManipulators::Italic: printf("\e[3m"); break;
|
||||||
@@ -717,17 +640,24 @@ void PICout::applyFormat(PICoutFormat f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIString PICout::getBuffer() {
|
bool PICout::setBufferActive(bool on, bool clear) {
|
||||||
PIMutexLocker ml(PICout::__mutex__());
|
PIMutexLocker ml(PICout::__mutex__());
|
||||||
PIString ret = PICout::__string__();
|
bool ret = isBufferActive();
|
||||||
|
if (clear) PICout::__string__().clear();
|
||||||
|
setOutputDevice(Buffer, on);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIString PICout::getBufferAndClear() {
|
bool PICout::isBufferActive() {
|
||||||
|
return isOutputDeviceActive(Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString PICout::buffer(bool clear) {
|
||||||
PIMutexLocker ml(PICout::__mutex__());
|
PIMutexLocker ml(PICout::__mutex__());
|
||||||
PIString ret = PICout::__string__();
|
PIString ret = PICout::__string__();
|
||||||
PICout::__string__().clear();
|
if (clear) PICout::__string__().clear();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,11 +683,3 @@ void PICout::setOutputDevices(PICout::OutputDevices d) {
|
|||||||
bool PICout::isOutputDeviceActive(PICout::OutputDevice d) {
|
bool PICout::isOutputDeviceActive(PICout::OutputDevice d) {
|
||||||
return devs[d];
|
return devs[d];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout PICout::withExternalBuffer(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls) {
|
|
||||||
PICout c(controls);
|
|
||||||
c.buffer_ = buffer;
|
|
||||||
c.id_ = id;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -41,9 +41,7 @@
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
# define piCout PICout(piDebug)
|
# define piCout PICout(piDebug)
|
||||||
# define piCoutObj \
|
# define piCoutObj PICout(piDebug && debug()) << (PIStringAscii("[") + className() + (name().isEmpty() ? "]" : PIStringAscii(" \"") + name() + PIStringAscii("\"]")))
|
||||||
PICout(piDebug && debug()) << (PIStringAscii("[") + className() + \
|
|
||||||
(name().isEmpty() ? "]" : PIStringAscii(" \"") + name() + PIStringAscii("\"]")))
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -75,8 +73,7 @@ enum PICoutAction {
|
|||||||
ClearLine /*! \~english Clear current line \~russian Очистить текущую строку */,
|
ClearLine /*! \~english Clear current line \~russian Очистить текущую строку */,
|
||||||
ClearScreen /*! \~english Clear the screen \~russian Очистить экран */,
|
ClearScreen /*! \~english Clear the screen \~russian Очистить экран */,
|
||||||
SaveContol /*! \~english Save control flags, equivalent to \a saveControl() \~russian Сохранить флаги, аналогично \a saveControl() */,
|
SaveContol /*! \~english Save control flags, equivalent to \a saveControl() \~russian Сохранить флаги, аналогично \a saveControl() */,
|
||||||
RestoreControl /*! \~english Restore control flags, equivalent to \a restoreControl() \~russian Восстановить флаги, аналогично \a
|
RestoreControl /*! \~english Restore control flags, equivalent to \a restoreControl() \~russian Восстановить флаги, аналогично \a restoreControl() */
|
||||||
restoreControl() */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \~english Enum contains control of PICout
|
//! \~english Enum contains control of PICout
|
||||||
@@ -123,7 +120,9 @@ enum PICoutFormat {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef PIFlags<PICoutControl> PICoutControls;
|
typedef PIFlags<PICoutControl> PICoutControls;
|
||||||
} // namespace PICoutManipulators
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//! \ingroup Core
|
//! \ingroup Core
|
||||||
@@ -132,6 +131,7 @@ typedef PIFlags<PICoutControl> PICoutControls;
|
|||||||
//! \~russian Универсальный вывод в консоль.
|
//! \~russian Универсальный вывод в консоль.
|
||||||
class PIP_EXPORT PICout {
|
class PIP_EXPORT PICout {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! \~english Default constructor with default features (AddSpaces and AddNewLine)
|
//! \~english Default constructor with default features (AddSpaces and AddNewLine)
|
||||||
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine)
|
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine)
|
||||||
PICout(int controls = PICoutManipulators::DefaultControls);
|
PICout(int controls = PICoutManipulators::DefaultControls);
|
||||||
@@ -140,6 +140,10 @@ public:
|
|||||||
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine), но если не \"active\" то будет неактивным
|
//! \~russian Конструктор по умолчанию (AddSpaces и AddNewLine), но если не \"active\" то будет неактивным
|
||||||
PICout(bool active);
|
PICout(bool active);
|
||||||
|
|
||||||
|
//! \~english Construct with external buffer and ID "id". See \a Notifier for details
|
||||||
|
//! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier
|
||||||
|
PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
|
||||||
|
|
||||||
PICout(const PICout & other);
|
PICout(const PICout & other);
|
||||||
|
|
||||||
~PICout();
|
~PICout();
|
||||||
@@ -154,7 +158,6 @@ public:
|
|||||||
//! \~english Object that emit events from %PICout
|
//! \~english Object that emit events from %PICout
|
||||||
//! \~russian Объект, который посылает события от %PICout
|
//! \~russian Объект, который посылает события от %PICout
|
||||||
static PIObject * object();
|
static PIObject * object();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Notifier();
|
Notifier();
|
||||||
PIObject * o;
|
PIObject * o;
|
||||||
@@ -173,123 +176,104 @@ public:
|
|||||||
|
|
||||||
//! \~english 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>
|
//! \~russian Оператор вывода для строк <tt>"const char * "</tt>
|
||||||
PICout & operator<<(const char * v);
|
PICout operator <<(const char * v);
|
||||||
|
|
||||||
//! \~english Output operator for \a PIString
|
// ! Output operator for strings with <tt>"std::string"</tt> type
|
||||||
//! \~russian Оператор вывода для \a PIString
|
//PICout operator <<(const std::string & v);
|
||||||
PICout & operator<<(const PIString & v);
|
|
||||||
|
|
||||||
//! \~english Output operator for boolean values
|
//! \~english Output operator for boolean values
|
||||||
//! \~russian Оператор вывода для логических значений
|
//! \~russian Оператор вывода для логических значений
|
||||||
PICout & operator<<(bool v);
|
PICout operator <<(const bool v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"char"</tt> values
|
//! \~english Output operator for <tt>"char"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"char"</tt> значений
|
//! \~russian Оператор вывода для <tt>"char"</tt> значений
|
||||||
PICout & operator<<(char v);
|
PICout operator <<(const char v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"unsigned char"</tt> values
|
//! \~english Output operator for <tt>"unsigned char"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"unsigned char"</tt> значений
|
//! \~russian Оператор вывода для <tt>"unsigned char"</tt> значений
|
||||||
PICout & operator<<(uchar v);
|
PICout operator <<(const uchar v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"short"</tt> values
|
//! \~english Output operator for <tt>"short"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"short"</tt> значений
|
//! \~russian Оператор вывода для <tt>"short"</tt> значений
|
||||||
PICout & operator<<(short v);
|
PICout operator <<(const short v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"unsigned short"</tt> values
|
//! \~english Output operator for <tt>"unsigned short"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"unsigned short"</tt> значений
|
//! \~russian Оператор вывода для <tt>"unsigned short"</tt> значений
|
||||||
PICout & operator<<(ushort v);
|
PICout operator <<(const ushort v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"int"</tt> values
|
//! \~english Output operator for <tt>"int"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"int"</tt> значений
|
//! \~russian Оператор вывода для <tt>"int"</tt> значений
|
||||||
PICout & operator<<(int v);
|
PICout operator <<(const int v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"unsigned int"</tt> values
|
//! \~english Output operator for <tt>"unsigned int"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"unsigned int"</tt> значений
|
//! \~russian Оператор вывода для <tt>"unsigned int"</tt> значений
|
||||||
PICout & operator<<(uint v);
|
PICout operator <<(const uint v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"long"</tt> values
|
//! \~english Output operator for <tt>"long"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"long"</tt> значений
|
//! \~russian Оператор вывода для <tt>"long"</tt> значений
|
||||||
PICout & operator<<(long v);
|
PICout operator <<(const long v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"unsigned long"</tt> values
|
//! \~english Output operator for <tt>"unsigned long"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"unsigned long"</tt> значений
|
//! \~russian Оператор вывода для <tt>"unsigned long"</tt> значений
|
||||||
PICout & operator<<(ulong v);
|
PICout operator <<(const ulong v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"long long"</tt> values
|
//! \~english Output operator for <tt>"long long"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"long long"</tt> значений
|
//! \~russian Оператор вывода для <tt>"long long"</tt> значений
|
||||||
PICout & operator<<(llong v);
|
PICout operator <<(const llong v);
|
||||||
|
|
||||||
//! \~english 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> значений
|
//! \~russian Оператор вывода для <tt>"unsigned long long"</tt> значений
|
||||||
PICout & operator<<(ullong v);
|
PICout operator <<(const ullong v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"float"</tt> values
|
//! \~english Output operator for <tt>"float"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"float"</tt> значений
|
//! \~russian Оператор вывода для <tt>"float"</tt> значений
|
||||||
PICout & operator<<(float v);
|
PICout operator <<(const float v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"double"</tt> values
|
//! \~english Output operator for <tt>"double"</tt> values
|
||||||
//! \~russian Оператор вывода для <tt>"double"</tt> значений
|
//! \~russian Оператор вывода для <tt>"double"</tt> значений
|
||||||
PICout & operator<<(double v);
|
PICout operator <<(const double v);
|
||||||
|
|
||||||
//! \~english Output operator for <tt>"ldouble"</tt> values
|
|
||||||
//! \~russian Оператор вывода для <tt>"ldouble"</tt> значений
|
|
||||||
PICout & operator<<(ldouble v);
|
|
||||||
|
|
||||||
//! \~english Output operator for pointers
|
//! \~english Output operator for pointers
|
||||||
//! \~russian Оператор вывода для указателей
|
//! \~russian Оператор вывода для указателей
|
||||||
PICout & operator<<(const void * v);
|
PICout operator <<(const void * v);
|
||||||
|
|
||||||
//! \~english Output operator for PIObject and ancestors
|
//! \~english Output operator for PIObject and ancestors
|
||||||
//! \~russian Оператор вывода для PIObject и наследников
|
//! \~russian Оператор вывода для PIObject и наследников
|
||||||
PICout & operator<<(const PIObject * v);
|
PICout operator <<(const PIObject * v);
|
||||||
|
|
||||||
//! \~english Output operator for \a PICoutSpecialChar values
|
//! \~english Output operator for \a PICoutSpecialChar values
|
||||||
//! \~russian Оператор вывода для \a PICoutSpecialChar
|
//! \~russian Оператор вывода для \a PICoutSpecialChar
|
||||||
PICout & operator<<(PICoutManipulators::PICoutSpecialChar v);
|
PICout operator <<(const PICoutManipulators::PICoutSpecialChar v);
|
||||||
|
|
||||||
//! \~english Output operator for \a PIFlags<PICoutFormat> values
|
//! \~english Output operator for \a PIFlags<PICoutFormat> values
|
||||||
//! \~russian Оператор вывода для \a PIFlags<PICoutFormat>
|
//! \~russian Оператор вывода для \a PIFlags<PICoutFormat>
|
||||||
PICout & operator<<(PIFlags<PICoutManipulators::PICoutFormat> v);
|
PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v);
|
||||||
|
|
||||||
//! \~english Output operator for \a PICoutFormat values
|
//! \~english Output operator for \a PICoutFormat values
|
||||||
//! \~russian Оператор вывода для \a PICoutFormat
|
//! \~russian Оператор вывода для \a PICoutFormat
|
||||||
PICout & operator<<(PICoutManipulators::PICoutFormat v);
|
PICout operator <<(const PICoutManipulators::PICoutFormat v);
|
||||||
|
|
||||||
//! \~english Do some action
|
//! \~english Do some action
|
||||||
//! \~russian Делает действие
|
//! \~russian Делает действие
|
||||||
PICout & operator<<(PICoutManipulators::PICoutAction v);
|
PICout operator <<(const PICoutManipulators::PICoutAction v);
|
||||||
|
|
||||||
//! \~english Set control flag "c" is "on" state
|
//! \~english Set control flag "c" is "on" state
|
||||||
//! \~russian Установить флаг "c" в "on" состояние
|
//! \~russian Установить флаг "c" в "on" состояние
|
||||||
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {
|
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
|
||||||
co_.setFlag(c, on);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Set control flags "c"
|
//! \~english Set control flags "c" and if "save" exec \a saveControl()
|
||||||
//! \~russian Установить флаги "c"
|
//! \~russian Установить флаг "c" и если "save" то выполнить \a saveControl()
|
||||||
PICout & setControls(PICoutManipulators::PICoutControls c) {
|
PICout & setControl(PICoutManipulators::PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;}
|
||||||
co_ = c;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Exec \a saveControls() and set control flags to "c"
|
|
||||||
//! \~russian Иыполнить \a saveControls() и Установить флаги "c"
|
|
||||||
PICout & saveAndSetControls(PICoutManipulators::PICoutControls c) {
|
|
||||||
saveControls();
|
|
||||||
co_ = c;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \~english Save control flags to internal stack
|
//! \~english Save control flags to internal stack
|
||||||
//! \~russian Сохраняет состояние флагов во внутренний стек
|
//! \~russian Сохраняет состояние флагов во внутренний стек
|
||||||
//! \~\sa \a restoreControl()
|
//! \~\sa \a restoreControl()
|
||||||
PICout & saveControls();
|
PICout & saveControl();
|
||||||
|
|
||||||
//! \~english Restore control flags from internal stack
|
//! \~english Restore control flags from internal stack
|
||||||
//! \~russian Восстанавливает состояние флагов из внутреннего стека
|
//! \~russian Восстанавливает состояние флагов из внутреннего стека
|
||||||
//! \~\sa \a saveControl()
|
//! \~\sa \a saveControl()
|
||||||
PICout & restoreControls();
|
PICout & restoreControl();
|
||||||
|
|
||||||
//! \~english Conditional put space character to output
|
//! \~english Conditional put space character to output
|
||||||
//! \~russian Условно добавляет пробел
|
//! \~russian Условно добавляет пробел
|
||||||
@@ -303,10 +287,6 @@ public:
|
|||||||
//! \~russian Условно добавляет новую строку
|
//! \~russian Условно добавляет новую строку
|
||||||
PICout & newLine();
|
PICout & newLine();
|
||||||
|
|
||||||
//! \~english Write char
|
|
||||||
//! \~russian Пишет символ
|
|
||||||
PICout & write(char c);
|
|
||||||
|
|
||||||
//! \~english Write raw data
|
//! \~english Write raw data
|
||||||
//! \~russian Пишет сырые символы
|
//! \~russian Пишет сырые символы
|
||||||
PICout & write(const char * str);
|
PICout & write(const char * str);
|
||||||
@@ -323,13 +303,17 @@ public:
|
|||||||
//! \~russian Вывод \a PIString в stdout
|
//! \~russian Вывод \a PIString в stdout
|
||||||
static void stdoutPIString(const PIString & s);
|
static void stdoutPIString(const PIString & s);
|
||||||
|
|
||||||
//! \~english Returns internal PIString buffer
|
//! \~english Set output device to \a PICout::Buffer and if "clear" clear it
|
||||||
//! \~russian Возвращает внутренний PIString буфер
|
//! \~russian Устанавливает устройство вывода на \a PICout::Buffer и если "clear" то очищает его
|
||||||
static PIString getBuffer();
|
static bool setBufferActive(bool on, bool clear = false);
|
||||||
|
|
||||||
//! \~english Returns internal PIString buffer and clear it
|
//! \~english Equivalent to \a isOutputDeviceActive(OutputDevice)
|
||||||
//! \~russian Возвращает внутренний PIString буфер и очищает его
|
//! \~russian Аналог \a isOutputDeviceActive(OutputDevice)
|
||||||
static PIString getBufferAndClear();
|
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
|
//! \~english Clear internal PIString buffer
|
||||||
//! \~russian Очищает внутренний PIString буфер
|
//! \~russian Очищает внутренний PIString буфер
|
||||||
@@ -340,34 +324,14 @@ public:
|
|||||||
//! \~russian Устройство вывода "d" устанавливается в "on". Возвращает было ли устройство активно
|
//! \~russian Устройство вывода "d" устанавливается в "on". Возвращает было ли устройство активно
|
||||||
static bool setOutputDevice(OutputDevice d, bool on = true);
|
static bool setOutputDevice(OutputDevice d, bool on = true);
|
||||||
|
|
||||||
//! \~english Turn on output device "d". Returns if it was enabled
|
|
||||||
//! \~russian Включает устройство вывода "d". Возвращает было ли устройство активно
|
|
||||||
static bool enableOutputDevice(OutputDevice d) { return setOutputDevice(d, true); }
|
|
||||||
|
|
||||||
//! \~english Turn off output device "d". Returns if it was enabled
|
|
||||||
//! \~russian Выключает устройство вывода "d". Возвращает было ли устройство активно
|
|
||||||
static bool disableOutputDevice(OutputDevice d) { return setOutputDevice(d, false); }
|
|
||||||
|
|
||||||
//! \~english Set output to devices to "d"
|
//! \~english Set output to devices to "d"
|
||||||
//! \~russian Устанавливает устройства вывода "d"
|
//! \~russian Устанавливает устройства вывода "d"
|
||||||
static void setOutputDevices(OutputDevices d);
|
static void setOutputDevices(OutputDevices d);
|
||||||
|
|
||||||
//! \~english Returns current output devices
|
|
||||||
//! \~russian Возвращает текущие устройства вывода
|
|
||||||
static OutputDevices currentOutputDevices() { return devs; }
|
|
||||||
|
|
||||||
//! \~english Returns if output device "d" is active
|
//! \~english Returns if output device "d" is active
|
||||||
//! \~russian Возвращает активно ли устройство вывода "d"
|
//! \~russian Возвращает активно ли устройство вывода "d"
|
||||||
static bool isOutputDeviceActive(OutputDevice d);
|
static bool isOutputDeviceActive(OutputDevice d);
|
||||||
|
|
||||||
|
|
||||||
//! \~english Construct with external buffer and ID "id". See \a Notifier for details
|
|
||||||
//! \~russian Конструктор с внешним буфером и ID "id". Подробнее \a Notifier
|
|
||||||
static PICout withExternalBuffer(PIString * buffer,
|
|
||||||
int id = 0,
|
|
||||||
PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces |
|
|
||||||
PICoutManipulators::AddNewLine);
|
|
||||||
|
|
||||||
static PIMutex & __mutex__();
|
static PIMutex & __mutex__();
|
||||||
static PIString & __string__();
|
static PIString & __string__();
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user